handle the case when docker request token for multiple scopes

This commit is contained in:
Tan Jiang 2016-04-05 19:48:13 +08:00
parent 54e41ccaaf
commit 0532735d21
3 changed files with 26 additions and 19 deletions

View File

@ -42,13 +42,14 @@ func (a *TokenHandler) Get() {
username, password, _ := request.BasicAuth() username, password, _ := request.BasicAuth()
authenticated := authenticate(username, password) authenticated := authenticate(username, password)
service := a.GetString("service") service := a.GetString("service")
scope := a.GetString("scope") scopes := a.GetStrings("scope")
log.Debugf("scopes: %+v", scopes)
if len(scope) == 0 && !authenticated { if len(scopes) == 0 && !authenticated {
log.Info("login request with invalid credentials") log.Info("login request with invalid credentials")
a.CustomAbort(http.StatusUnauthorized, "") a.CustomAbort(http.StatusUnauthorized, "")
} }
access := svc_utils.GetResourceActions(scope) access := svc_utils.GetResourceActions(scopes)
for _, a := range access { for _, a := range access {
svc_utils.FilterAccess(username, authenticated, a) svc_utils.FilterAccess(username, authenticated, a)
} }

View File

@ -38,17 +38,19 @@ const (
) )
// GetResourceActions ... // GetResourceActions ...
func GetResourceActions(scope string) []*token.ResourceActions { func GetResourceActions(scopes []string) []*token.ResourceActions {
var res []*token.ResourceActions var res []*token.ResourceActions
if scope == "" { for _, s := range scopes {
return res if s == "" {
continue
} }
items := strings.Split(scope, ":") items := strings.Split(s, ":")
res = append(res, &token.ResourceActions{ res = append(res, &token.ResourceActions{
Type: items[0], Type: items[0],
Name: items[1], Name: items[1],
Actions: strings.Split(items[2], ","), Actions: strings.Split(items[2], ","),
}) })
}
return res return res
} }
@ -66,9 +68,12 @@ func FilterAccess(username string, authenticated bool, a *token.ResourceActions)
if strings.Contains(a.Name, "/") { //Only check the permission when the requested image has a namespace, i.e. project if strings.Contains(a.Name, "/") { //Only check the permission when the requested image has a namespace, i.e. project
projectName := a.Name[0:strings.LastIndex(a.Name, "/")] projectName := a.Name[0:strings.LastIndex(a.Name, "/")]
var permission string var permission string
var err error
if authenticated { if authenticated {
if username == "admin" { isAdmin, err := dao.IsAdminRole(username)
if err != nil {
log.Errorf("Error occurred in IsAdminRole: %v")
}
if isAdmin {
exist, err := dao.ProjectExists(projectName) exist, err := dao.ProjectExists(projectName)
if err != nil { if err != nil {
log.Errorf("Error occurred in CheckExistProject: %v", err) log.Errorf("Error occurred in CheckExistProject: %v", err)
@ -100,8 +105,8 @@ func FilterAccess(username string, authenticated bool, a *token.ResourceActions)
} }
// GenTokenForUI is for the UI process to call, so it won't establish a https connection from UI to proxy. // GenTokenForUI is for the UI process to call, so it won't establish a https connection from UI to proxy.
func GenTokenForUI(username, service, scope string) (string, error) { func GenTokenForUI(username string, service string, scopes []string) (string, error) {
access := GetResourceActions(scope) access := GetResourceActions(scopes)
for _, a := range access { for _, a := range access {
FilterAccess(username, true, a) FilterAccess(username, true, a)
} }

View File

@ -63,14 +63,15 @@ func RegistryAPIGet(url, username string) ([]byte, error) {
authenticate := response.Header.Get("WWW-Authenticate") authenticate := response.Header.Get("WWW-Authenticate")
log.Debugf("authenticate header: %s", authenticate) log.Debugf("authenticate header: %s", authenticate)
var service string var service string
var scope string var scopes []string
//Disregard the case for hanlding multiple scopes for http call initiated from UI, as there's refactor planned.
re := regexp.MustCompile(`service=\"(.*?)\".*scope=\"(.*?)\"`) re := regexp.MustCompile(`service=\"(.*?)\".*scope=\"(.*?)\"`)
res := re.FindStringSubmatch(authenticate) res := re.FindStringSubmatch(authenticate)
if len(res) > 2 { if len(res) > 2 {
service = res[1] service = res[1]
scope = res[2] scopes = append(scopes, res[2])
} }
token, err := GenTokenForUI(username, service, scope) token, err := GenTokenForUI(username, service, scopes)
if err != nil { if err != nil {
return nil, err return nil, err
} }