Skip to content

Commit

Permalink
Handling parsing of multiple scopes combined in a single string.
Browse files Browse the repository at this point in the history
It is possible for challenge headers to contain multiple scopes in a single string. This change ensures that this case is handled when parsing the scopes by splitting out scopes combined in a single string.

Signed-off-by: Jacob MacElroy <jacob@okteto.com>
  • Loading branch information
Jacob MacElroy committed Oct 27, 2021
1 parent 33fb83e commit 5279e68
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 18 deletions.
39 changes: 21 additions & 18 deletions util/resolver/authorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,25 +434,28 @@ type scopes map[string]map[string]struct{}
func parseScopes(s []string) scopes {
// https://docs.docker.com/registry/spec/auth/scope/
m := map[string]map[string]struct{}{}
for _, scope := range s {
parts := strings.SplitN(scope, ":", 3)
names := []string{parts[0]}
if len(parts) > 1 {
names = append(names, parts[1])
}
var actions []string
if len(parts) == 3 {
actions = append(actions, strings.Split(parts[2], ",")...)
}
name := strings.Join(names, ":")
ma, ok := m[name]
if !ok {
ma = map[string]struct{}{}
m[name] = ma
}
for _, scopeStr := range s {
// The scopeStr may have strings that contain multiple scopes separated by a space.
for _, scope := range strings.Split(scopeStr, " ") {
parts := strings.SplitN(scope, ":", 3)
names := []string{parts[0]}
if len(parts) > 1 {
names = append(names, parts[1])
}
var actions []string
if len(parts) == 3 {
actions = append(actions, strings.Split(parts[2], ",")...)
}
name := strings.Join(names, ":")
ma, ok := m[name]
if !ok {
ma = map[string]struct{}{}
m[name] = ma
}

for _, a := range actions {
ma[a] = struct{}{}
for _, a := range actions {
ma[a] = struct{}{}
}
}
}
return m
Expand Down
51 changes: 51 additions & 0 deletions util/resolver/authorizer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package resolver

import (
"reflect"
"testing"
)

func TestParseScopes(t *testing.T) {
for _, tc := range []struct {
name string
input []string
expected scopes
}{
{
name: "SeparateStrings",
input: []string{
"repository:foo/bar:pull",
"repository:foo/baz:pull,push",
},
expected: map[string]map[string]struct{}{
"repository:foo/bar": {
"pull": struct{}{},
},
"repository:foo/baz": {
"pull": struct{}{},
"push": struct{}{},
},
},
},
{
name: "CombinedStrings",
input: []string{"repository:foo/bar:pull repository:foo/baz:pull,push"},
expected: map[string]map[string]struct{}{
"repository:foo/bar": {
"pull": struct{}{},
},
"repository:foo/baz": {
"pull": struct{}{},
"push": struct{}{},
},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
parsed := parseScopes(tc.input)
if !reflect.DeepEqual(parsed, tc.expected) {
t.Fatalf("expected %v, got %v", tc.expected, parsed)
}
})
}
}

0 comments on commit 5279e68

Please sign in to comment.