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.