| 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 |