From 70d9a9d543f03cc368dea78a7b4b511075f88e44 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Wed, 29 Jul 2015 12:50:43 -0700 Subject: [PATCH] Automatically generate a HTTP secret if none is provided Log a warning if the registry generates its own secret. Update configuration doc, and remove the default secret from the development config file. Signed-off-by: Aaron Lehmann --- cmd/registry/config.yml | 1 - docs/configuration.md | 7 ++++++- registry/handlers/app.go | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cmd/registry/config.yml b/cmd/registry/config.yml index aad08fb4..3f4616d8 100644 --- a/cmd/registry/config.yml +++ b/cmd/registry/config.yml @@ -30,7 +30,6 @@ storage: enabled: false http: addr: :5000 - secret: asecretforlocaldevelopment debug: addr: localhost:5001 redis: diff --git a/docs/configuration.md b/docs/configuration.md index 1f3f15d3..b45f7da1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1184,7 +1184,12 @@ should have both preceding and trailing slashes, for example /path/ A random piece of data. This is used to sign state that may be stored with the client to protect against tampering. For production environments you should generate a -random piece of data using a cryptographically secure random generator. +random piece of data using a cryptographically secure random generator. This +configuration parameter may be omitted, in which case the registry will automatically +generate a secret at launch. +

+WARNING: If you are building a cluster of registries behind a load balancer, you MUST +ensure the secret is the same for all registries. diff --git a/registry/handlers/app.go b/registry/handlers/app.go index fd8f36bb..9fb82cbb 100644 --- a/registry/handlers/app.go +++ b/registry/handlers/app.go @@ -1,6 +1,7 @@ package handlers import ( + cryptorand "crypto/rand" "expvar" "fmt" "math/rand" @@ -30,6 +31,10 @@ import ( "golang.org/x/net/context" ) +// randomSecretSize is the number of random bytes to generate if no secret +// was specified. +const randomSecretSize = 32 + // App is a global registry application object. Shared resources can be placed // on this object that will be accessible from all requests. Any writable // fields should be protected. @@ -102,6 +107,7 @@ func NewApp(ctx context.Context, configuration configuration.Configuration) *App panic(err) } + app.configureSecret(&configuration) app.configureEvents(&configuration) app.configureRedis(&configuration) app.configureLogHook(&configuration) @@ -337,6 +343,19 @@ func (app *App) configureLogHook(configuration *configuration.Configuration) { } } +// configureSecret creates a random secret if a secret wasn't included in the +// configuration. +func (app *App) configureSecret(configuration *configuration.Configuration) { + if configuration.HTTP.Secret == "" { + var secretBytes [randomSecretSize]byte + if _, err := cryptorand.Read(secretBytes[:]); err != nil { + panic(fmt.Sprintf("could not generate random bytes for HTTP secret: %v", err)) + } + configuration.HTTP.Secret = string(secretBytes[:]) + ctxu.GetLogger(app).Warn("No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable.") + } +} + func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() // ensure that request body is always closed.