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 delegation | 5 package delegation |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/base64" | 8 "encoding/base64" |
9 "fmt" | 9 "fmt" |
10 "strings" | 10 "strings" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 // verified. | 43 // verified. |
44 ErrUnsignedDelegationToken = errors.New("auth: unsigned delegation token
") | 44 ErrUnsignedDelegationToken = errors.New("auth: unsigned delegation token
") |
45 | 45 |
46 // ErrForbiddenDelegationToken is returned if token is structurally corr
ect, | 46 // ErrForbiddenDelegationToken is returned if token is structurally corr
ect, |
47 // but some of its constraints prevents it from being used. For example,
it is | 47 // but some of its constraints prevents it from being used. For example,
it is |
48 // already expired or it was minted for some other services, etc. See lo
gs for | 48 // already expired or it was minted for some other services, etc. See lo
gs for |
49 // details. | 49 // details. |
50 ErrForbiddenDelegationToken = errors.New("auth: forbidden delegation tok
en") | 50 ErrForbiddenDelegationToken = errors.New("auth: forbidden delegation tok
en") |
51 ) | 51 ) |
52 | 52 |
53 // CertificatesProvider is accepted by 'CheckToken'. | 53 // CertificatesProvider is used by 'CheckToken', it is implemented by authdb.DB. |
| 54 // |
| 55 // It returns certificates of services trusted to sign tokens. |
54 type CertificatesProvider interface { | 56 type CertificatesProvider interface { |
55 » // GetAuthServiceCertificates returns a bundle with certificates of a pr
imary | 57 » // GetCertificates returns a bundle with certificates of a trusted signe
r. |
56 » // auth service. | 58 » // |
57 » GetAuthServiceCertificates(c context.Context) (*signing.PublicCertificat
es, error) | 59 » // Returns (nil, nil) if the given signer is not trusted. |
| 60 » // |
| 61 » // Returns errors (usually transient) if the bundle can't be fetched. |
| 62 » GetCertificates(c context.Context, id identity.Identity) (*signing.Publi
cCertificates, error) |
58 } | 63 } |
59 | 64 |
60 // GroupsChecker is accepted by 'CheckToken'. | 65 // GroupsChecker is accepted by 'CheckToken', it is implemented by authdb.DB. |
61 type GroupsChecker interface { | 66 type GroupsChecker interface { |
62 // IsMember returns true if the given identity belongs to the given grou
p. | 67 // IsMember returns true if the given identity belongs to the given grou
p. |
63 // | 68 // |
64 // Unknown groups are considered empty. May return errors if underlying | 69 // Unknown groups are considered empty. May return errors if underlying |
65 // datastore has issues. | 70 // datastore has issues. |
66 IsMember(c context.Context, id identity.Identity, group string) (bool, e
rror) | 71 IsMember(c context.Context, id identity.Identity, group string) (bool, e
rror) |
67 } | 72 } |
68 | 73 |
69 // CheckTokenParams is passed to CheckToken. | 74 // CheckTokenParams is passed to CheckToken. |
70 type CheckTokenParams struct { | 75 type CheckTokenParams struct { |
71 Token string // the delegation token to che
ck | 76 Token string // the delegation token to che
ck |
72 PeerID identity.Identity // identity of the caller, as
extracted from its credentials | 77 PeerID identity.Identity // identity of the caller, as
extracted from its credentials |
73 » CertificatesProvider CertificatesProvider // returns auth service certif
icates | 78 » CertificatesProvider CertificatesProvider // returns certificates with t
rusted keys |
74 GroupsChecker GroupsChecker // knows how to do group looku
ps | 79 GroupsChecker GroupsChecker // knows how to do group looku
ps |
75 OwnServiceIdentity identity.Identity // identity of the current ser
vice | 80 OwnServiceIdentity identity.Identity // identity of the current ser
vice |
76 } | 81 } |
77 | 82 |
78 // CheckToken verifies validity of a delegation token. | 83 // CheckToken verifies validity of a delegation token. |
79 // | 84 // |
80 // If the token is valid, it returns the delegated identity (embedded in the | 85 // If the token is valid, it returns the delegated identity (embedded in the |
81 // token). | 86 // token). |
82 // | 87 // |
83 // May return transient errors. | 88 // May return transient errors. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 if err = proto.Unmarshal(blob, tok); err != nil { | 124 if err = proto.Unmarshal(blob, tok); err != nil { |
120 return nil, err | 125 return nil, err |
121 } | 126 } |
122 return tok, nil | 127 return tok, nil |
123 } | 128 } |
124 | 129 |
125 // unsealToken verifies token's signature and deserializes the subtoken. | 130 // unsealToken verifies token's signature and deserializes the subtoken. |
126 // | 131 // |
127 // May return transient errors. | 132 // May return transient errors. |
128 func unsealToken(c context.Context, tok *messages.DelegationToken, certsProvider
CertificatesProvider) (*messages.Subtoken, error) { | 133 func unsealToken(c context.Context, tok *messages.DelegationToken, certsProvider
CertificatesProvider) (*messages.Subtoken, error) { |
129 » // Grab the public keys of the primary auth service. It is the service t
hat | 134 » // Grab the public keys of the service that signed the token, if we trus
t it. |
130 » // signs tokens. | 135 » signerID, err := identity.MakeIdentity(tok.SignerId) |
131 » // | |
132 » // TODO(vadimsh): There's 'signer_id' field in the DelegationToken proto
. We | |
133 » // ignore it for now. If we ever support multiple trusted signers, we'd
need | |
134 » // to start using it to pick the correct public key. For now only the ce
ntral | |
135 » // auth service is trusted, so we just grab its certs. | |
136 » certs, err := certsProvider.GetAuthServiceCertificates(c) | |
137 if err != nil { | 136 if err != nil { |
138 » » return nil, err | 137 » » return nil, fmt.Errorf("bad signer_id %q - %s", tok.SignerId, er
r) |
| 138 » } |
| 139 » certs, err := certsProvider.GetCertificates(c, signerID) |
| 140 » switch { |
| 141 » case err != nil: |
| 142 » » return nil, fmt.Errorf("failed to grab certificates of %q - %s",
tok.SignerId, err) |
| 143 » case certs == nil: |
| 144 » » return nil, fmt.Errorf("the signer %q is not trusted", tok.Signe
rId) |
139 } | 145 } |
140 | 146 |
141 // Check the signature on the token. | 147 // Check the signature on the token. |
142 err = certs.CheckSignature(tok.SigningKeyId, tok.SerializedSubtoken, tok
.Pkcs1Sha256Sig) | 148 err = certs.CheckSignature(tok.SigningKeyId, tok.SerializedSubtoken, tok
.Pkcs1Sha256Sig) |
143 if err != nil { | 149 if err != nil { |
144 return nil, err | 150 return nil, err |
145 } | 151 } |
146 | 152 |
147 // The signature is correct! Deserialize the subtoken. | 153 // The signature is correct! Deserialize the subtoken. |
148 msg := &messages.Subtoken{} | 154 msg := &messages.Subtoken{} |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 switch ok, err := checker.IsMember(c, ident, strings.Tri
mPrefix(aud, "group:")); { | 255 switch ok, err := checker.IsMember(c, ident, strings.Tri
mPrefix(aud, "group:")); { |
250 case err != nil: | 256 case err != nil: |
251 return err // transient error during group looku
p | 257 return err // transient error during group looku
p |
252 case ok: | 258 case ok: |
253 return nil // success, 'ident' is in the target
audience | 259 return nil // success, 'ident' is in the target
audience |
254 } | 260 } |
255 } | 261 } |
256 } | 262 } |
257 return fmt.Errorf("%s is not allowed to use the token", ident) | 263 return fmt.Errorf("%s is not allowed to use the token", ident) |
258 } | 264 } |
OLD | NEW |