Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package coordinator | 5 package coordinator |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "errors" | |
| 9 "fmt" | 8 "fmt" |
| 9 "strings" | |
| 10 | 10 |
| 11 "github.com/luci/gae/service/info" | 11 "github.com/luci/gae/service/info" |
| 12 "github.com/luci/luci-go/appengine/logdog/coordinator/config" | |
| 13 log "github.com/luci/luci-go/common/logging" | 12 log "github.com/luci/luci-go/common/logging" |
| 14 "github.com/luci/luci-go/common/proto/logdog/svcconfig" | 13 "github.com/luci/luci-go/common/proto/logdog/svcconfig" |
| 15 "github.com/luci/luci-go/server/auth" | 14 "github.com/luci/luci-go/server/auth" |
| 16 "github.com/luci/luci-go/server/auth/identity" | 15 "github.com/luci/luci-go/server/auth/identity" |
| 17 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
| 18 ) | 17 ) |
| 19 | 18 |
| 20 // ErrNoAccess is returned if the user has no access to the requested project. | |
| 21 var ErrNoAccess = config.ErrNoAccess | |
| 22 | |
| 23 // IsAdminUser tests whether the current user belongs to the administrative | 19 // IsAdminUser tests whether the current user belongs to the administrative |
| 24 // users group. It will return an error if the user does not. | 20 // users group. |
| 21 // | |
|
nodir
2016/05/19 17:17:20
I think separating these two paragraphs is unneces
dnj (Google)
2016/05/19 20:10:46
I'm okay with it. I like to separate the purpose o
| |
| 22 // If the user is not, a MembershipError will be returned. | |
| 25 func IsAdminUser(c context.Context) error { | 23 func IsAdminUser(c context.Context) error { |
| 26 » return isMember(c, func(cfg *svcconfig.Coordinator) string { | 24 » cfg, err := GetServices(c).Config(c) |
| 27 » » return cfg.AdminAuthGroup | 25 » if err != nil { |
| 28 » }) | 26 » » return err |
| 27 » } | |
| 28 » return checkMember(c, cfg.Coordinator.AdminAuthGroup) | |
| 29 } | 29 } |
| 30 | 30 |
| 31 // IsServiceUser tests whether the current user belongs to the backend services | 31 // IsServiceUser tests whether the current user belongs to the backend services |
| 32 // users group. It will return an error if the user does not. | 32 // users group. |
| 33 // | |
| 34 // If the user is not, a MembershipError will be returned. | |
| 33 func IsServiceUser(c context.Context) error { | 35 func IsServiceUser(c context.Context) error { |
| 34 » return isMember(c, func(cfg *svcconfig.Coordinator) string { | 36 » cfg, err := GetServices(c).Config(c) |
| 35 » » return cfg.ServiceAuthGroup | 37 » if err != nil { |
| 36 » }) | 38 » » return err |
| 39 » } | |
| 40 » return checkMember(c, cfg.Coordinator.ServiceAuthGroup) | |
| 37 } | 41 } |
| 38 | 42 |
| 39 func isMember(c context.Context, groupNameFunc func(*svcconfig.Coordinator) stri ng) error { | 43 // IsProjectReader tests whether the current user belongs to one of the |
| 44 // project's declared reader groups. | |
| 45 // | |
| 46 // If the user is not, a MembershipError will be returned. | |
| 47 func IsProjectReader(c context.Context, pcfg *svcconfig.ProjectConfig) error { | |
| 48 » return checkMember(c, pcfg.ReaderAuthGroups...) | |
| 49 } | |
| 50 | |
| 51 func checkMember(c context.Context, groups ...string) error { | |
| 40 // On dev-appserver, the superuser has implicit group membership to | 52 // On dev-appserver, the superuser has implicit group membership to |
| 41 // everything. | 53 // everything. |
| 42 if info.Get(c).IsDevAppServer() { | 54 if info.Get(c).IsDevAppServer() { |
| 43 if u := auth.CurrentUser(c); u.Superuser { | 55 if u := auth.CurrentUser(c); u.Superuser { |
| 44 log.Fields{ | 56 log.Fields{ |
| 45 "identity": u.Identity, | 57 "identity": u.Identity, |
| 58 "groups": groups, | |
| 46 }.Infof(c, "Granting superuser implicit group membership on development server.") | 59 }.Infof(c, "Granting superuser implicit group membership on development server.") |
| 47 return nil | 60 return nil |
| 48 } | 61 } |
| 49 } | 62 } |
| 50 | 63 |
| 51 » cfg, err := GetServices(c).Config(c) | 64 » id := auth.CurrentIdentity(c) |
| 52 » if err != nil { | 65 » for _, group := range groups { |
| 53 » » return err | 66 » » is, err := auth.IsMember(c, group) |
| 67 » » if err != nil { | |
| 68 » » » return err | |
| 69 » » } | |
| 70 » » if is { | |
| 71 » » » log.Fields{ | |
| 72 » » » » "identity": id, | |
| 73 » » » » "group": group, | |
| 74 » » » }.Debugf(c, "User access granted.") | |
| 75 » » » return nil | |
| 76 » » } | |
| 54 } | 77 } |
| 55 | 78 |
| 56 » if cfg.Coordinator == nil { | 79 » return &MembershipError{ |
| 57 » » return errors.New("no coordinator configuration") | 80 » » Identity: id, |
| 81 » » Groups: groups, | |
| 58 } | 82 } |
| 59 | |
| 60 groupName := groupNameFunc(cfg.Coordinator) | |
| 61 if groupName == "" { | |
| 62 return errors.New("no auth group is configured") | |
| 63 } | |
| 64 | |
| 65 is, err := auth.IsMember(c, groupName) | |
| 66 if err != nil { | |
| 67 return err | |
| 68 } | |
| 69 if !is { | |
| 70 return &MembershipError{ | |
| 71 Identity: auth.CurrentIdentity(c), | |
| 72 Group: groupName, | |
| 73 } | |
| 74 } | |
| 75 return nil | |
| 76 } | 83 } |
| 77 | 84 |
| 78 // MembershipError is an error returned by group membership checking functions | 85 // MembershipError is an error returned by group membership checking functions |
| 79 // if the current identity is not a member of the requested group. | 86 // if the current identity is not a member of the requested group. |
| 80 type MembershipError struct { | 87 type MembershipError struct { |
| 81 Identity identity.Identity | 88 Identity identity.Identity |
| 82 » Group string | 89 » Groups []string |
| 83 } | 90 } |
| 84 | 91 |
| 85 func (e *MembershipError) Error() string { | 92 func (e *MembershipError) Error() string { |
| 86 » return fmt.Sprintf("user %q is not a member of group %q", e.Identity, e. Group) | 93 » return fmt.Sprintf("user %q is not a member of [%s]", e.Identity, string s.Join(e.Groups, ", ")) |
| 87 } | 94 } |
| 88 | 95 |
| 89 // IsMembershipError returns whether a given error is a membership error. | 96 // IsMembershipError returns whether a given error is a membership error. |
| 90 func IsMembershipError(e error) bool { | 97 func IsMembershipError(e error) bool { |
| 91 _, ok := e.(*MembershipError) | 98 _, ok := e.(*MembershipError) |
| 92 return ok | 99 return ok |
| 93 } | 100 } |
| OLD | NEW |