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" | 12 » luciConfig "github.com/luci/luci-go/common/config" |
13 log "github.com/luci/luci-go/common/logging" | 13 log "github.com/luci/luci-go/common/logging" |
14 "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 // | |
22 // If the user is not a member of any groups, a MembershipError will be | |
nodir
2016/05/19 00:38:58
which "any groups" you are referring to in the con
dnj (Google)
2016/05/19 16:12:34
Done.
| |
23 // returned. | |
25 func IsAdminUser(c context.Context) error { | 24 func IsAdminUser(c context.Context) error { |
26 » return isMember(c, func(cfg *svcconfig.Coordinator) string { | 25 » cfg, err := GetServices(c).Config(c) |
27 » » return cfg.AdminAuthGroup | 26 » if err != nil { |
28 » }) | 27 » » return err |
28 » } | |
29 » return checkMember(c, cfg.Coordinator.AdminAuthGroup) | |
29 } | 30 } |
30 | 31 |
31 // IsServiceUser tests whether the current user belongs to the backend services | 32 // IsServiceUser tests whether the current user belongs to the backend services |
32 // users group. It will return an error if the user does not. | 33 // users group. |
34 // | |
35 // If the user is not a member of any groups, a MembershipError will be | |
nodir
2016/05/19 00:38:58
same here
dnj (Google)
2016/05/19 16:12:34
Done.
| |
36 // returned. | |
33 func IsServiceUser(c context.Context) error { | 37 func IsServiceUser(c context.Context) error { |
34 » return isMember(c, func(cfg *svcconfig.Coordinator) string { | 38 » cfg, err := GetServices(c).Config(c) |
35 » » return cfg.ServiceAuthGroup | 39 » if err != nil { |
36 » }) | 40 » » return err |
41 » } | |
42 » return checkMember(c, cfg.Coordinator.ServiceAuthGroup) | |
37 } | 43 } |
38 | 44 |
39 func isMember(c context.Context, groupNameFunc func(*svcconfig.Coordinator) stri ng) error { | 45 // IsProjectReader tests whether the current user belongs to one of the |
46 // project's declared reader groups. | |
47 // | |
48 // If the user is not a member of any groups, a MembershipError will be | |
nodir
2016/05/19 00:38:58
english: "any group"?
dnj (Google)
2016/05/19 16:12:34
Yeah this comment has gone through a few stages of
| |
49 // returned. | |
50 func IsProjectReader(c context.Context, project luciConfig.ProjectName) error { | |
51 » pcfg, err := GetServices(c).ProjectConfig(c, project) | |
52 » if err != nil { | |
53 » » return err | |
54 » } | |
55 » return checkMember(c, pcfg.ReaderAuthGroups...) | |
56 } | |
57 | |
58 func checkMember(c context.Context, groups ...string) error { | |
40 // On dev-appserver, the superuser has implicit group membership to | 59 // On dev-appserver, the superuser has implicit group membership to |
41 // everything. | 60 // everything. |
42 if info.Get(c).IsDevAppServer() { | 61 if info.Get(c).IsDevAppServer() { |
43 if u := auth.CurrentUser(c); u.Superuser { | 62 if u := auth.CurrentUser(c); u.Superuser { |
44 log.Fields{ | 63 log.Fields{ |
45 "identity": u.Identity, | 64 "identity": u.Identity, |
65 "groups": groups, | |
46 }.Infof(c, "Granting superuser implicit group membership on development server.") | 66 }.Infof(c, "Granting superuser implicit group membership on development server.") |
47 return nil | 67 return nil |
48 } | 68 } |
49 } | 69 } |
50 | 70 |
51 » cfg, err := GetServices(c).Config(c) | 71 » id := auth.CurrentIdentity(c) |
52 » if err != nil { | 72 » for _, group := range groups { |
53 » » return err | 73 » » is, err := auth.IsMember(c, group) |
74 » » if err != nil { | |
75 » » » return err | |
76 » » } | |
77 » » if is { | |
78 » » » log.Fields{ | |
79 » » » » "identity": id, | |
80 » » » » "group": group, | |
81 » » » }.Debugf(c, "User access granted.") | |
82 » » » return nil | |
83 » » } | |
54 } | 84 } |
55 | 85 |
56 » if cfg.Coordinator == nil { | 86 » return &MembershipError{ |
57 » » return errors.New("no coordinator configuration") | 87 » » Identity: id, |
88 » » Groups: groups, | |
58 } | 89 } |
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 } | 90 } |
77 | 91 |
78 // MembershipError is an error returned by group membership checking functions | 92 // MembershipError is an error returned by group membership checking functions |
79 // if the current identity is not a member of the requested group. | 93 // if the current identity is not a member of the requested group. |
80 type MembershipError struct { | 94 type MembershipError struct { |
81 Identity identity.Identity | 95 Identity identity.Identity |
82 » Group string | 96 » Groups []string |
83 } | 97 } |
84 | 98 |
85 func (e *MembershipError) Error() string { | 99 func (e *MembershipError) Error() string { |
86 » return fmt.Sprintf("user %q is not a member of group %q", e.Identity, e. Group) | 100 » return fmt.Sprintf("user %q is not a member of [%s]", e.Identity, string s.Join(e.Groups, ", ")) |
87 } | 101 } |
88 | 102 |
89 // IsMembershipError returns whether a given error is a membership error. | 103 // IsMembershipError returns whether a given error is a membership error. |
90 func IsMembershipError(e error) bool { | 104 func IsMembershipError(e error) bool { |
91 _, ok := e.(*MembershipError) | 105 _, ok := e.(*MembershipError) |
92 return ok | 106 return ok |
93 } | 107 } |
OLD | NEW |