浏览代码

Support multiple API keys (command-line and config) (fixes #2747)

Antony Male 9 年之前
父节点
当前提交
5971c00a4f
共有 5 个文件被更改,包括 18 次插入10 次删除
  1. 1 1
      cmd/syncthing/gui.go
  2. 1 2
      cmd/syncthing/gui_auth.go
  3. 3 2
      cmd/syncthing/gui_csrf.go
  4. 1 1
      cmd/syncthing/main.go
  5. 12 4
      lib/config/guiconfiguration.go

+ 1 - 1
cmd/syncthing/gui.go

@@ -238,7 +238,7 @@ func (s *apiService) Serve() {
 
 	// Wrap everything in CSRF protection. The /rest prefix should be
 	// protected, other requests will grant cookies.
-	handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg.APIKey(), mux)
+	handler := csrfMiddleware(s.id.String()[:5], "/rest", guiCfg, mux)
 
 	// Add the CORS handling
 	handler = corsMiddleware(handler)

+ 1 - 2
cmd/syncthing/gui_auth.go

@@ -33,9 +33,8 @@ func emitLoginAttempt(success bool, username string) {
 }
 
 func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguration, next http.Handler) http.Handler {
-	apiKey := cfg.APIKey()
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if apiKey != "" && r.Header.Get("X-API-Key") == apiKey {
+		if cfg.IsValidAPIKey(r.Header.Get("X-API-Key")) {
 			next.ServeHTTP(w, r)
 			return
 		}

+ 3 - 2
cmd/syncthing/gui_csrf.go

@@ -13,6 +13,7 @@ import (
 	"os"
 	"strings"
 
+	"github.com/syncthing/syncthing/lib/config"
 	"github.com/syncthing/syncthing/lib/osutil"
 	"github.com/syncthing/syncthing/lib/sync"
 )
@@ -30,11 +31,11 @@ const maxCsrfTokens = 25
 // Check for CSRF token on /rest/ URLs. If a correct one is not given, reject
 // the request with 403. For / and /index.html, set a new CSRF cookie if none
 // is currently set.
-func csrfMiddleware(unique, prefix, apiKey string, next http.Handler) http.Handler {
+func csrfMiddleware(unique string, prefix string, cfg config.GUIConfiguration, next http.Handler) http.Handler {
 	loadCsrfTokens()
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		// Allow requests carrying a valid API key
-		if apiKey != "" && r.Header.Get("X-API-Key") == apiKey {
+		if cfg.IsValidAPIKey(r.Header.Get("X-API-Key")) {
 			next.ServeHTTP(w, r)
 			return
 		}

+ 1 - 1
cmd/syncthing/main.go

@@ -478,7 +478,7 @@ func upgradeViaRest() error {
 	cfg, _ := loadConfig()
 	target := cfg.GUI().URL()
 	r, _ := http.NewRequest("POST", target+"/rest/system/upgrade", nil)
-	r.Header.Set("X-API-Key", cfg.GUI().APIKey())
+	r.Header.Set("X-API-Key", cfg.GUI().RawAPIKey)
 
 	tr := &http.Transport{
 		Dial:            dialer.Dial,

+ 12 - 4
lib/config/guiconfiguration.go

@@ -76,9 +76,17 @@ func (c GUIConfiguration) URL() string {
 	return u.String()
 }
 
-func (c GUIConfiguration) APIKey() string {
-	if override := os.Getenv("STGUIAPIKEY"); override != "" {
-		return override
+// Returns whether the given API key is valid, including both the value in config
+// and any overrides
+func (c GUIConfiguration) IsValidAPIKey(apiKey string) bool {
+	switch apiKey {
+	case "":
+		return false
+
+	case c.RawAPIKey, os.Getenv("STGUIAPIKEY"):
+		return true
+
+	default:
+		return false
 	}
-	return c.RawAPIKey
 }