]> Cypherpunks repositories - gostls13.git/commitdiff
dashboard: do not require key in source code
authorRuss Cox <rsc@golang.org>
Thu, 22 Dec 2011 15:21:59 +0000 (10:21 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 22 Dec 2011 15:21:59 +0000 (10:21 -0500)
Or else eventually someone will check it in.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5504071

misc/dashboard/app/build/handler.go
misc/dashboard/app/build/key.go

index dd32365f88a2434db3ef67f0c886b76fba45ff3e..eba8d0eaf666a5121c58e3d69330b994cdc20644 100644 (file)
@@ -322,7 +322,7 @@ func AuthHandler(h dashHandler) http.HandlerFunc {
                // Validate key query parameter for POST requests only.
                key := r.FormValue("key")
                builder := r.FormValue("builder")
-               if r.Method == "POST" && !validKey(key, builder) {
+               if r.Method == "POST" && !validKey(c, key, builder) {
                        err = os.NewError("invalid key: " + key)
                }
 
@@ -368,7 +368,8 @@ func keyHandler(w http.ResponseWriter, r *http.Request) {
                logErr(w, r, os.NewError("must supply builder in query string"))
                return
        }
-       fmt.Fprint(w, builderKey(builder))
+       c := appengine.NewContext(r)
+       fmt.Fprint(w, builderKey(c, builder))
 }
 
 func init() {
@@ -392,18 +393,18 @@ func validHash(hash string) bool {
        return hash != ""
 }
 
-func validKey(key, builder string) bool {
+func validKey(c appengine.Context, key, builder string) bool {
        if appengine.IsDevAppServer() {
                return true
        }
-       if key == secretKey {
+       if key == secretKey(c) {
                return true
        }
-       return key == builderKey(builder)
+       return key == builderKey(c, builder)
 }
 
-func builderKey(builder string) string {
-       h := hmac.NewMD5([]byte(secretKey))
+func builderKey(c appengine.Context, builder string) string {
+       h := hmac.NewMD5([]byte(secretKey(c)))
        h.Write([]byte(builder))
        return fmt.Sprintf("%x", h.Sum())
 }
index d31bef9da0bb55b00d51554655ede7a5428de748..5306c3b6bd6d38ec1b0877700798bb67846b06bc 100644 (file)
@@ -4,13 +4,59 @@
 
 package build
 
-import "appengine"
+import (
+       "sync"
 
-// Delete this init function before deploying to production.
-func init() {
-       if !appengine.IsDevAppServer() {
-               panic("please read misc/dashboard/app/build/key.go")
-       }
+       "appengine"
+       "appengine/datastore"
+)
+
+var theKey struct {
+       sync.RWMutex
+       BuilderKey
+}
+
+type BuilderKey struct {
+       Secret string
 }
 
-const secretKey = "" // Important! Put a secret here before deploying!
+func (k *BuilderKey) Key(c appengine.Context) *datastore.Key {
+       return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
+}
+
+func secretKey(c appengine.Context) string {
+       // check with rlock
+       theKey.RLock()
+       k := theKey.Secret
+       theKey.RUnlock()
+       if k != "" {
+               return k
+       }
+
+       // prepare to fill; check with lock and keep lock
+       theKey.Lock()
+       defer theKey.Unlock()
+       if theKey.Secret != "" {
+               return theKey.Secret
+       }
+
+       // fill
+       if err := datastore.Get(c, theKey.Key(c), &theKey.BuilderKey); err != nil {
+               if err == datastore.ErrNoSuchEntity {
+                       // If the key is not stored in datastore, write it.
+                       // This only happens at the beginning of a new deployment.
+                       // The code is left here for SDK use and in case a fresh
+                       // deployment is ever needed.  "gophers rule" is not the
+                       // real key.
+                       if !appengine.IsDevAppServer() {
+                               panic("lost key from datastore")
+                       }
+                       theKey.Secret = "gophers rule"
+                       datastore.Put(c, theKey.Key(c), &theKey.BuilderKey)
+                       return theKey.Secret
+               }
+               panic("cannot load builder key: " + err.String())
+       }
+
+       return theKey.Secret
+}