| OLD | NEW |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. | 1 // Copyright 2017 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 serviceaccounts | 5 package serviceaccounts |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "time" | 9 "time" |
| 10 | 10 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 // Fetch service account rules. They are hot in memory most of the time. | 96 // Fetch service account rules. They are hot in memory most of the time. |
| 97 rules, err := r.Rules(c) | 97 rules, err := r.Rules(c) |
| 98 if err != nil { | 98 if err != nil { |
| 99 // Don't put error details in the message, it may be returned to | 99 // Don't put error details in the message, it may be returned to |
| 100 // unauthorized callers. | 100 // unauthorized callers. |
| 101 logging.WithError(err).Errorf(c, "Failed to load service account
s rules") | 101 logging.WithError(err).Errorf(c, "Failed to load service account
s rules") |
| 102 return nil, grpc.Errorf(codes.Internal, "failed to load service
accounts rules") | 102 return nil, grpc.Errorf(codes.Internal, "failed to load service
accounts rules") |
| 103 } | 103 } |
| 104 | 104 |
| 105 » // Grab the rule for this account. Don't leak information about presence
or | 105 » // Check that requested usage is allowed and grab the corresponding rule
. |
| 106 » // absence of the account to the caller, they may not be authorized to s
ee the | 106 » rule, err := rules.Check(c, &RulesQuery{ |
| 107 » // account at all. | 107 » » ServiceAccount: req.ServiceAccount, |
| 108 » rule := rules.Rule(req.ServiceAccount) | 108 » » Proxy: callerID, |
| 109 » if rule == nil { | 109 » » EndUser: endUserID, |
| 110 » » logging.Errorf(c, "No rule for service account %q in the config
rev %s", req.ServiceAccount, rules.ConfigRevision()) | 110 » }) |
| 111 » » return nil, grpc.Errorf(codes.PermissionDenied, "unknown service
account or not enough permissions to use it") | 111 » if err != nil { |
| 112 » } | 112 » » return nil, err // it is already gRPC error, and it's already lo
gged |
| 113 » logging.Infof(c, "Found the matching rule %q in the config rev %s", rule
.Rule.Name, rules.ConfigRevision()) | |
| 114 | |
| 115 » // If the caller is in 'Proxies' list, we assume it's known to us and we
trust | |
| 116 » // it enough to start returning more detailed error messages. | |
| 117 » switch known, err := rule.Proxies.IsMember(c, callerID); { | |
| 118 » case err != nil: | |
| 119 » » logging.WithError(err).Errorf(c, "Failed to check membership of
caller %q", callerID) | |
| 120 » » return nil, grpc.Errorf(codes.Internal, "membership check failed
") | |
| 121 » case !known: | |
| 122 » » logging.Errorf(c, "Caller %q is not authorized to use account %q
", callerID, req.ServiceAccount) | |
| 123 » » return nil, grpc.Errorf(codes.PermissionDenied, "unknown service
account or not enough permissions to use it") | |
| 124 } | 113 } |
| 125 | 114 |
| 126 » // Check ValidityDuration next, it is easiest check. | 115 » // ValidityDuration check is specific to this RPC, it's not done by 'Che
ck'. |
| 127 if req.ValidityDuration == 0 { | 116 if req.ValidityDuration == 0 { |
| 128 req.ValidityDuration = 3600 | 117 req.ValidityDuration = 3600 |
| 129 } | 118 } |
| 130 if req.ValidityDuration > rule.Rule.MaxGrantValidityDuration { | 119 if req.ValidityDuration > rule.Rule.MaxGrantValidityDuration { |
| 131 logging.Errorf(c, "Requested validity is larger than max allowed
: %d > %d", req.ValidityDuration, rule.Rule.MaxGrantValidityDuration) | 120 logging.Errorf(c, "Requested validity is larger than max allowed
: %d > %d", req.ValidityDuration, rule.Rule.MaxGrantValidityDuration) |
| 132 return nil, grpc.Errorf(codes.InvalidArgument, "per rule %q the
validity duration should be <= %d", rule.Rule.Name, rule.Rule.MaxGrantValidityDu
ration) | 121 return nil, grpc.Errorf(codes.InvalidArgument, "per rule %q the
validity duration should be <= %d", rule.Rule.Name, rule.Rule.MaxGrantValidityDu
ration) |
| 133 } | 122 } |
| 134 | 123 |
| 135 // Next is EndUsers check (involves membership lookups). | |
| 136 switch known, err := rule.EndUsers.IsMember(c, endUserID); { | |
| 137 case err != nil: | |
| 138 logging.WithError(err).Errorf(c, "Failed to check membership of
end user %q", endUserID) | |
| 139 return nil, grpc.Errorf(codes.Internal, "membership check failed
") | |
| 140 case !known: | |
| 141 logging.Errorf(c, "End user %q is not authorized to use account
%q", endUserID, req.ServiceAccount) | |
| 142 return nil, grpc.Errorf( | |
| 143 codes.PermissionDenied, "per rule %q the user %q is not
authorized to use the service account %q", | |
| 144 rule.Rule.Name, endUserID, req.ServiceAccount) | |
| 145 } | |
| 146 | |
| 147 // All checks are done! Note that AllowedScopes is checked later during | 124 // All checks are done! Note that AllowedScopes is checked later during |
| 148 // MintOAuthTokenViaGrant. Here we don't even know what OAuth scopes wil
l be | 125 // MintOAuthTokenViaGrant. Here we don't even know what OAuth scopes wil
l be |
| 149 // requested. | 126 // requested. |
| 150 var resp *minter.MintOAuthTokenGrantResponse | 127 var resp *minter.MintOAuthTokenGrantResponse |
| 151 p := mintParams{ | 128 p := mintParams{ |
| 152 serviceAccount: req.ServiceAccount, | 129 serviceAccount: req.ServiceAccount, |
| 153 proxyID: callerID, | 130 proxyID: callerID, |
| 154 endUserID: endUserID, | 131 endUserID: endUserID, |
| 155 validityDuration: req.ValidityDuration, | 132 validityDuration: req.ValidityDuration, |
| 156 serviceVer: serviceVer, | 133 serviceVer: serviceVer, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 logging.WithError(err).Errorf(c, "Error when signing the token") | 178 logging.WithError(err).Errorf(c, "Error when signing the token") |
| 202 return nil, grpc.Errorf(codes.Internal, "error when signing the
token - %s", err) | 179 return nil, grpc.Errorf(codes.Internal, "error when signing the
token - %s", err) |
| 203 } | 180 } |
| 204 | 181 |
| 205 return &minter.MintOAuthTokenGrantResponse{ | 182 return &minter.MintOAuthTokenGrantResponse{ |
| 206 GrantToken: signed, | 183 GrantToken: signed, |
| 207 Expiry: google.NewTimestamp(expiry), | 184 Expiry: google.NewTimestamp(expiry), |
| 208 ServiceVersion: p.serviceVer, | 185 ServiceVersion: p.serviceVer, |
| 209 }, nil | 186 }, nil |
| 210 } | 187 } |
| OLD | NEW |