OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // Package access implements a config service access check against a project | 5 // Package access implements a config service access check against a project |
6 // config client. | 6 // config client. |
7 // | 7 // |
8 // Note that this is a soft check, as the true access authority is the config | 8 // Note that this is a soft check, as the true access authority is the config |
9 // service, and this check is not hitting that service. | 9 // service, and this check is not hitting that service. |
10 // | 10 // |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 // Not a project config set, so neither remaining Authority can
access. | 45 // Not a project config set, so neither remaining Authority can
access. |
46 return ErrNoAccess | 46 return ErrNoAccess |
47 } | 47 } |
48 | 48 |
49 // Load the project config. We execute this RPC as the service, not the
user, | 49 // Load the project config. We execute this RPC as the service, not the
user, |
50 // so while this will recurse (and hopefully take advantage of the cache
), it | 50 // so while this will recurse (and hopefully take advantage of the cache
), it |
51 // will not trigger an infinite access check loop. | 51 // will not trigger an infinite access check loop. |
52 var pcfg configPB.ProjectCfg | 52 var pcfg configPB.ProjectCfg |
53 if err := cfgclient.Get(c, cfgclient.AsService, projectConfigSet, cfgcli
ent.ProjectConfigPath, | 53 if err := cfgclient.Get(c, cfgclient.AsService, projectConfigSet, cfgcli
ent.ProjectConfigPath, |
54 textproto.Message(&pcfg), nil); err != nil { | 54 textproto.Message(&pcfg), nil); err != nil { |
55 » » return errors.Annotate(err).Reason("failed to load %(path)q in %
(configSet)q"). | 55 » » return errors.Annotate(err, "failed to load %q in %q", |
56 » » » D("path", cfgclient.ProjectConfigPath).D("configSet", pr
ojectConfigSet).Err() | 56 » » » cfgclient.ProjectConfigPath, projectConfigSet).Err() |
57 } | 57 } |
58 | 58 |
59 id := identity.AnonymousIdentity | 59 id := identity.AnonymousIdentity |
60 if a == backend.AsUser { | 60 if a == backend.AsUser { |
61 id = auth.CurrentIdentity(c) | 61 id = auth.CurrentIdentity(c) |
62 } | 62 } |
63 checkGroups := make([]string, 0, len(pcfg.Access)) | 63 checkGroups := make([]string, 0, len(pcfg.Access)) |
64 for _, access := range pcfg.Access { | 64 for _, access := range pcfg.Access { |
65 if group, ok := trimPrefix(access, "group:"); ok { | 65 if group, ok := trimPrefix(access, "group:"); ok { |
66 // Check group membership. | 66 // Check group membership. |
67 checkGroups = append(checkGroups, group) | 67 checkGroups = append(checkGroups, group) |
68 } else { | 68 } else { |
69 // If there is no ":" in the access string, this is a us
er ACL. | 69 // If there is no ":" in the access string, this is a us
er ACL. |
70 if strings.IndexRune(access, ':') < 0 { | 70 if strings.IndexRune(access, ':') < 0 { |
71 access = "user:" + access | 71 access = "user:" + access |
72 } | 72 } |
73 if identity.Identity(access) == id { | 73 if identity.Identity(access) == id { |
74 return nil | 74 return nil |
75 } | 75 } |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 // No individual accesses, check groups. | 79 // No individual accesses, check groups. |
80 if len(checkGroups) > 0 { | 80 if len(checkGroups) > 0 { |
81 switch canAccess, err := auth.IsMember(c, checkGroups...); { | 81 switch canAccess, err := auth.IsMember(c, checkGroups...); { |
82 case err != nil: | 82 case err != nil: |
83 » » » return errors.Annotate(err).Reason("failed to check grou
p membership").Err() | 83 » » » return errors.Annotate(err, "failed to check group membe
rship").Err() |
84 case canAccess: | 84 case canAccess: |
85 return nil | 85 return nil |
86 } | 86 } |
87 } | 87 } |
88 return ErrNoAccess | 88 return ErrNoAccess |
89 } | 89 } |
90 | 90 |
91 func trimPrefix(v, pfx string) (string, bool) { | 91 func trimPrefix(v, pfx string) (string, bool) { |
92 if strings.HasPrefix(v, pfx) { | 92 if strings.HasPrefix(v, pfx) { |
93 return v[len(pfx):], true | 93 return v[len(pfx):], true |
94 } | 94 } |
95 return v, false | 95 return v, false |
96 } | 96 } |
OLD | NEW |