Merge pull request #2748 from canton7/feature/multiple-api-keys

Support multiple API keys (command-line and config) (fixed #2747)
This commit is contained in:
Audrius Butkevicius 2016-02-01 09:20:51 +00:00
commit 60ca7784ba
5 changed files with 18 additions and 10 deletions

View File

@ -238,7 +238,7 @@ func (s *apiService) Serve() {
// Wrap everything in CSRF protection. The /rest prefix should be // Wrap everything in CSRF protection. The /rest prefix should be
// protected, other requests will grant cookies. // 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 // Add the CORS handling
handler = corsMiddleware(handler) handler = corsMiddleware(handler)

View File

@ -33,9 +33,8 @@ func emitLoginAttempt(success bool, username string) {
} }
func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguration, next http.Handler) http.Handler { 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) { 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) next.ServeHTTP(w, r)
return return
} }

View File

@ -13,6 +13,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/sync" "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 // 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 // the request with 403. For / and /index.html, set a new CSRF cookie if none
// is currently set. // 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() loadCsrfTokens()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Allow requests carrying a valid API key // 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) next.ServeHTTP(w, r)
return return
} }

View File

@ -478,7 +478,7 @@ func upgradeViaRest() error {
cfg, _ := loadConfig() cfg, _ := loadConfig()
target := cfg.GUI().URL() target := cfg.GUI().URL()
r, _ := http.NewRequest("POST", target+"/rest/system/upgrade", nil) 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{ tr := &http.Transport{
Dial: dialer.Dial, Dial: dialer.Dial,

View File

@ -76,9 +76,17 @@ func (c GUIConfiguration) URL() string {
return u.String() return u.String()
} }
func (c GUIConfiguration) APIKey() string { // Returns whether the given API key is valid, including both the value in config
if override := os.Getenv("STGUIAPIKEY"); override != "" { // and any overrides
return override 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
} }