From 88de2e11fb5f79135ec64761a3c26af4e607488f Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Wed, 17 Dec 2014 10:57:05 -0800 Subject: [PATCH] Refactor auth stringSet into common.StringSet Docker-DCO-1.1-Signed-off-by: Josh Hawn (github: jlhawn) --- auth/token/accesscontroller.go | 20 +++++++------ auth/token/token.go | 17 +++++------ auth/token/token_test.go | 8 ++++-- auth/token/util.go | 52 ++++++++-------------------------- common/stringset.go | 35 +++++++++++++++++++++++ 5 files changed, 72 insertions(+), 60 deletions(-) create mode 100644 common/stringset.go diff --git a/auth/token/accesscontroller.go b/auth/token/accesscontroller.go index 52e06912..66bf1c31 100644 --- a/auth/token/accesscontroller.go +++ b/auth/token/accesscontroller.go @@ -12,8 +12,10 @@ import ( "strconv" "strings" - "github.com/docker/docker-registry/auth" "github.com/docker/libtrust" + + "github.com/docker/docker-registry/auth" + "github.com/docker/docker-registry/common" ) // accessSet maps a typed, named resource to @@ -31,13 +33,13 @@ func newAccessSet(accessItems ...auth.Access) accessSet { Name: access.Name, } - set := accessSet[resource] - if set == nil { - set = make(actionSet) + set, exists := accessSet[resource] + if !exists { + set = newActionSet() accessSet[resource] = set } - set[access.Action] = struct{}{} + set.Add(access.Action) } return accessSet @@ -47,7 +49,7 @@ func newAccessSet(accessItems ...auth.Access) accessSet { func (s accessSet) contains(access auth.Access) bool { actionSet, ok := s[access.Resource] if ok { - return actionSet.contains(access.Action) + return actionSet.Contains(access.Action) } return false @@ -60,7 +62,7 @@ func (s accessSet) scopeParam() string { scopes := make([]string, 0, len(s)) for resource, actionSet := range s { - actions := strings.Join(actionSet.keys(), ",") + actions := strings.Join(actionSet.Keys(), ",") scopes = append(scopes, fmt.Sprintf("%s:%s:%s", resource.Type, resource.Name, actions)) } @@ -240,8 +242,8 @@ func (ac *accessController) Authorized(req *http.Request, accessItems ...auth.Ac } verifyOpts := VerifyOptions{ - TrustedIssuers: newStringSet(ac.issuer), - AccpetedAudiences: newStringSet(ac.service), + TrustedIssuers: common.NewStringSet(ac.issuer), + AccpetedAudiences: common.NewStringSet(ac.service), Roots: ac.rootCerts, TrustedKeys: ac.trustedKeys, } diff --git a/auth/token/token.go b/auth/token/token.go index d1baafe6..d1b0d67a 100644 --- a/auth/token/token.go +++ b/auth/token/token.go @@ -14,6 +14,7 @@ import ( "github.com/docker/libtrust" "github.com/docker/docker-registry/auth" + "github.com/docker/docker-registry/common" ) const ( @@ -85,8 +86,8 @@ type Token struct { // VerifyOptions is used to specify // options when verifying a JSON Web Token. type VerifyOptions struct { - TrustedIssuers stringSet - AccpetedAudiences stringSet + TrustedIssuers common.StringSet + AccpetedAudiences common.StringSet Roots *x509.CertPool TrustedKeys map[string]libtrust.PublicKey } @@ -155,13 +156,13 @@ func (t *Token) Verify(verifyOpts VerifyOptions) error { } // Verify that the Issuer claim is a trusted authority. - if !verifyOpts.TrustedIssuers.contains(t.Claims.Issuer) { + if !verifyOpts.TrustedIssuers.Contains(t.Claims.Issuer) { log.Errorf("token from untrusted issuer: %q", t.Claims.Issuer) return ErrInvalidToken } // Verify that the Audience claim is allowed. - if !verifyOpts.AccpetedAudiences.contains(t.Claims.Audience) { + if !verifyOpts.AccpetedAudiences.Contains(t.Claims.Audience) { log.Errorf("token intended for another audience: %q", t.Claims.Audience) return ErrInvalidToken } @@ -319,14 +320,14 @@ func (t *Token) accessSet() accessSet { Name: resourceActions.Name, } - set := accessSet[resource] - if set == nil { - set = make(actionSet) + set, exists := accessSet[resource] + if !exists { + set = newActionSet() accessSet[resource] = set } for _, action := range resourceActions.Actions { - set[action] = struct{}{} + set.Add(action) } } diff --git a/auth/token/token_test.go b/auth/token/token_test.go index be7470c9..da466dde 100644 --- a/auth/token/token_test.go +++ b/auth/token/token_test.go @@ -15,8 +15,10 @@ import ( "testing" "time" - "github.com/docker/docker-registry/auth" "github.com/docker/libtrust" + + "github.com/docker/docker-registry/auth" + "github.com/docker/docker-registry/common" ) func makeRootKeys(numKeys int) ([]libtrust.PrivateKey, error) { @@ -194,8 +196,8 @@ func TestTokenVerify(t *testing.T) { } verifyOps := VerifyOptions{ - TrustedIssuers: newStringSet(issuer), - AccpetedAudiences: newStringSet(audience), + TrustedIssuers: common.NewStringSet(issuer), + AccpetedAudiences: common.NewStringSet(audience), Roots: rootPool, TrustedKeys: trustedKeys, } diff --git a/auth/token/util.go b/auth/token/util.go index 94078fb8..7ec52cef 100644 --- a/auth/token/util.go +++ b/auth/token/util.go @@ -4,6 +4,8 @@ import ( "encoding/base64" "errors" "strings" + + "github.com/docker/docker-registry/common" ) // joseBase64UrlEncode encodes the given data using the standard base64 url @@ -31,47 +33,17 @@ func joseBase64UrlDecode(s string) ([]byte, error) { return base64.URLEncoding.DecodeString(s) } -// stringSet is a useful type for looking up strings. -type stringSet map[string]struct{} - -func newStringSet(strs ...string) stringSet { - set := make(stringSet, len(strs)) - for _, str := range strs { - set[str] = struct{}{} - } - - return set -} - -// contains returns whether the given key is in this StringSet. -func (ss stringSet) contains(key string) bool { - _, ok := ss[key] - return ok -} - -// keys returns a slice of all keys in this stringSet. -func (ss stringSet) keys() []string { - keys := make([]string, 0, len(ss)) - - for key := range ss { - keys = append(keys, key) - } - - return keys -} - // actionSet is a special type of stringSet. -type actionSet stringSet +type actionSet struct { + common.StringSet +} -// contains calls stringSet.contains() for +func newActionSet(actions ...string) actionSet { + return actionSet{common.NewStringSet(actions...)} +} + +// Contains calls StringSet.Contains() for // either "*" or the given action string. -func (s actionSet) contains(action string) bool { - ss := stringSet(s) - - return ss.contains("*") || ss.contains(action) -} - -// keys wraps stringSet.keys() -func (s actionSet) keys() []string { - return stringSet(s).keys() +func (s actionSet) Contains(action string) bool { + return s.StringSet.Contains("*") || s.StringSet.Contains(action) } diff --git a/common/stringset.go b/common/stringset.go new file mode 100644 index 00000000..36f4ba5a --- /dev/null +++ b/common/stringset.go @@ -0,0 +1,35 @@ +package common + +// StringSet is a useful type for looking up strings. +type StringSet map[string]struct{} + +// NewStringSet creates a new StringSet with the given strings. +func NewStringSet(keys ...string) StringSet { + ss := make(StringSet, len(keys)) + ss.Add(keys...) + return ss +} + +// Add inserts the given keys into this StringSet. +func (ss StringSet) Add(keys ...string) { + for _, key := range keys { + ss[key] = struct{}{} + } +} + +// Contains returns whether the given key is in this StringSet. +func (ss StringSet) Contains(key string) bool { + _, ok := ss[key] + return ok +} + +// Keys returns a slice of all keys in this StringSet. +func (ss StringSet) Keys() []string { + keys := make([]string, 0, len(ss)) + + for key := range ss { + keys = append(keys, key) + } + + return keys +}