mirror of
https://github.com/golang/go
synced 2024-11-18 15:14:44 -07:00
godoc/dl: use datastore to retrieve secret key.
godoc still runs on App Engine (not Managed VMs). The metadata server is only available from Compute Engine and Managed VMs, but not App Engine. Change-Id: I0e5e9ef3f169f6d24ca7562df744c8f1556b825f Reviewed-on: https://go-review.googlesource.com/17391 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
b844739462
commit
eb69368e05
@ -21,6 +21,7 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
@ -30,7 +31,6 @@ import (
|
||||
"google.golang.org/appengine/log"
|
||||
"google.golang.org/appengine/memcache"
|
||||
"google.golang.org/appengine/user"
|
||||
"google.golang.org/cloud/compute/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -39,12 +39,6 @@ const (
|
||||
cacheDuration = time.Hour
|
||||
)
|
||||
|
||||
var builderKey string
|
||||
|
||||
func init() {
|
||||
builderKey, _ = metadata.ProjectAttributeValue("builder-key")
|
||||
}
|
||||
|
||||
func RegisterHandlers(mux *http.ServeMux) {
|
||||
mux.Handle("/dl", http.RedirectHandler("/dl/", http.StatusFound))
|
||||
mux.HandleFunc("/dl/", getHandler) // also serves listHandler
|
||||
@ -336,10 +330,6 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "bad user", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if builderKey == "" {
|
||||
http.Error(w, "no builder-key found in project metadata", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if r.FormValue("key") != userKey(c, user) {
|
||||
http.Error(w, "bad key", http.StatusForbidden)
|
||||
return
|
||||
@ -393,7 +383,7 @@ func validUser(user string) bool {
|
||||
}
|
||||
|
||||
func userKey(c context.Context, user string) string {
|
||||
h := hmac.New(md5.New, []byte(builderKey))
|
||||
h := hmac.New(md5.New, []byte(secret(c)))
|
||||
h.Write([]byte("user-" + user))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
@ -448,3 +438,55 @@ var prettyStrings = map[string]string{
|
||||
"installer": "Installer",
|
||||
"source": "Source",
|
||||
}
|
||||
|
||||
// Code below copied from x/build/app/key
|
||||
|
||||
var theKey struct {
|
||||
sync.RWMutex
|
||||
builderKey
|
||||
}
|
||||
|
||||
type builderKey struct {
|
||||
Secret string
|
||||
}
|
||||
|
||||
func (k *builderKey) Key(c context.Context) *datastore.Key {
|
||||
return datastore.NewKey(c, "BuilderKey", "root", 0, nil)
|
||||
}
|
||||
|
||||
func secret(c context.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.Error())
|
||||
}
|
||||
|
||||
return theKey.Secret
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user