1
16
17 package serviceaccount
18
19 import (
20 "context"
21 "crypto"
22 "crypto/ecdsa"
23 "crypto/elliptic"
24 "crypto/rsa"
25 "crypto/x509"
26 "encoding/base64"
27 "encoding/json"
28 "fmt"
29 "strings"
30
31 jose "gopkg.in/square/go-jose.v2"
32 "gopkg.in/square/go-jose.v2/jwt"
33
34 v1 "k8s.io/api/core/v1"
35 utilerrors "k8s.io/apimachinery/pkg/util/errors"
36 "k8s.io/apiserver/pkg/audit"
37 "k8s.io/apiserver/pkg/authentication/authenticator"
38 apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
39 )
40
41
42 type ServiceAccountTokenGetter interface {
43 GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error)
44 GetPod(namespace, name string) (*v1.Pod, error)
45 GetSecret(namespace, name string) (*v1.Secret, error)
46 GetNode(name string) (*v1.Node, error)
47 }
48
49 type TokenGenerator interface {
50
51
52
53
54
55
56 GenerateToken(claims *jwt.Claims, privateClaims interface{}) (string, error)
57 }
58
59
60
61 func JWTTokenGenerator(iss string, privateKey interface{}) (TokenGenerator, error) {
62 var signer jose.Signer
63 var err error
64 switch pk := privateKey.(type) {
65 case *rsa.PrivateKey:
66 signer, err = signerFromRSAPrivateKey(pk)
67 if err != nil {
68 return nil, fmt.Errorf("could not generate signer for RSA keypair: %v", err)
69 }
70 case *ecdsa.PrivateKey:
71 signer, err = signerFromECDSAPrivateKey(pk)
72 if err != nil {
73 return nil, fmt.Errorf("could not generate signer for ECDSA keypair: %v", err)
74 }
75 case jose.OpaqueSigner:
76 signer, err = signerFromOpaqueSigner(pk)
77 if err != nil {
78 return nil, fmt.Errorf("could not generate signer for OpaqueSigner: %v", err)
79 }
80 default:
81 return nil, fmt.Errorf("unknown private key type %T, must be *rsa.PrivateKey, *ecdsa.PrivateKey, or jose.OpaqueSigner", privateKey)
82 }
83
84 return &jwtTokenGenerator{
85 iss: iss,
86 signer: signer,
87 }, nil
88 }
89
90
91
92
93
94
95
96
97
98
99 func keyIDFromPublicKey(publicKey interface{}) (string, error) {
100 publicKeyDERBytes, err := x509.MarshalPKIXPublicKey(publicKey)
101 if err != nil {
102 return "", fmt.Errorf("failed to serialize public key to DER format: %v", err)
103 }
104
105 hasher := crypto.SHA256.New()
106 hasher.Write(publicKeyDERBytes)
107 publicKeyDERHash := hasher.Sum(nil)
108
109 keyID := base64.RawURLEncoding.EncodeToString(publicKeyDERHash)
110
111 return keyID, nil
112 }
113
114 func signerFromRSAPrivateKey(keyPair *rsa.PrivateKey) (jose.Signer, error) {
115 keyID, err := keyIDFromPublicKey(&keyPair.PublicKey)
116 if err != nil {
117 return nil, fmt.Errorf("failed to derive keyID: %v", err)
118 }
119
120
121
122
123
124
125 privateJWK := &jose.JSONWebKey{
126 Algorithm: string(jose.RS256),
127 Key: keyPair,
128 KeyID: keyID,
129 Use: "sig",
130 }
131
132 signer, err := jose.NewSigner(
133 jose.SigningKey{
134 Algorithm: jose.RS256,
135 Key: privateJWK,
136 },
137 nil,
138 )
139
140 if err != nil {
141 return nil, fmt.Errorf("failed to create signer: %v", err)
142 }
143
144 return signer, nil
145 }
146
147 func signerFromECDSAPrivateKey(keyPair *ecdsa.PrivateKey) (jose.Signer, error) {
148 var alg jose.SignatureAlgorithm
149 switch keyPair.Curve {
150 case elliptic.P256():
151 alg = jose.ES256
152 case elliptic.P384():
153 alg = jose.ES384
154 case elliptic.P521():
155 alg = jose.ES512
156 default:
157 return nil, fmt.Errorf("unknown private key curve, must be 256, 384, or 521")
158 }
159
160 keyID, err := keyIDFromPublicKey(&keyPair.PublicKey)
161 if err != nil {
162 return nil, fmt.Errorf("failed to derive keyID: %v", err)
163 }
164
165
166 privateJWK := &jose.JSONWebKey{
167 Algorithm: string(alg),
168 Key: keyPair,
169 KeyID: keyID,
170 Use: "sig",
171 }
172
173 signer, err := jose.NewSigner(
174 jose.SigningKey{
175 Algorithm: alg,
176 Key: privateJWK,
177 },
178 nil,
179 )
180 if err != nil {
181 return nil, fmt.Errorf("failed to create signer: %v", err)
182 }
183
184 return signer, nil
185 }
186
187 func signerFromOpaqueSigner(opaqueSigner jose.OpaqueSigner) (jose.Signer, error) {
188 alg := jose.SignatureAlgorithm(opaqueSigner.Public().Algorithm)
189
190 signer, err := jose.NewSigner(
191 jose.SigningKey{
192 Algorithm: alg,
193 Key: &jose.JSONWebKey{
194 Algorithm: string(alg),
195 Key: opaqueSigner,
196 KeyID: opaqueSigner.Public().KeyID,
197 Use: "sig",
198 },
199 },
200 nil,
201 )
202 if err != nil {
203 return nil, fmt.Errorf("failed to create signer: %v", err)
204 }
205
206 return signer, nil
207 }
208
209 type jwtTokenGenerator struct {
210 iss string
211 signer jose.Signer
212 }
213
214 func (j *jwtTokenGenerator) GenerateToken(claims *jwt.Claims, privateClaims interface{}) (string, error) {
215
216 return jwt.Signed(j.signer).
217 Claims(privateClaims).
218 Claims(claims).
219 Claims(&jwt.Claims{
220 Issuer: j.iss,
221 }).
222 CompactSerialize()
223 }
224
225
226
227
228 func JWTTokenAuthenticator(issuers []string, keys []interface{}, implicitAuds authenticator.Audiences, validator Validator) authenticator.Token {
229 issuersMap := make(map[string]bool)
230 for _, issuer := range issuers {
231 issuersMap[issuer] = true
232 }
233 return &jwtTokenAuthenticator{
234 issuers: issuersMap,
235 keys: keys,
236 implicitAuds: implicitAuds,
237 validator: validator,
238 }
239 }
240
241 type jwtTokenAuthenticator struct {
242 issuers map[string]bool
243 keys []interface{}
244 validator Validator
245 implicitAuds authenticator.Audiences
246 }
247
248
249
250 type Validator interface {
251
252
253
254 Validate(ctx context.Context, tokenData string, public *jwt.Claims, private interface{}) (*apiserverserviceaccount.ServiceAccountInfo, error)
255
256
257
258
259
260 NewPrivateClaims() interface{}
261 }
262
263 func (j *jwtTokenAuthenticator) AuthenticateToken(ctx context.Context, tokenData string) (*authenticator.Response, bool, error) {
264 if !j.hasCorrectIssuer(tokenData) {
265 return nil, false, nil
266 }
267
268 tok, err := jwt.ParseSigned(tokenData)
269 if err != nil {
270 return nil, false, nil
271 }
272
273 public := &jwt.Claims{}
274 private := j.validator.NewPrivateClaims()
275
276
277 var (
278 found bool
279 errlist []error
280 )
281 for _, key := range j.keys {
282 if err := tok.Claims(key, public, private); err != nil {
283 errlist = append(errlist, err)
284 continue
285 }
286 found = true
287 break
288 }
289
290 if !found {
291 return nil, false, utilerrors.NewAggregate(errlist)
292 }
293
294
295 if !j.issuers[public.Issuer] {
296 return nil, false, fmt.Errorf("token issuer %q is invalid", public.Issuer)
297 }
298
299 tokenAudiences := authenticator.Audiences(public.Audience)
300 if len(tokenAudiences) == 0 {
301
302 audit.AddAuditAnnotation(ctx, "authentication.k8s.io/legacy-token", public.Subject)
303 legacyTokensTotal.WithContext(ctx).Inc()
304 tokenAudiences = j.implicitAuds
305 }
306
307 requestedAudiences, ok := authenticator.AudiencesFrom(ctx)
308 if !ok {
309
310 requestedAudiences = j.implicitAuds
311 }
312
313 auds := authenticator.Audiences(tokenAudiences).Intersect(requestedAudiences)
314 if len(auds) == 0 && len(j.implicitAuds) != 0 {
315 return nil, false, fmt.Errorf("token audiences %q is invalid for the target audiences %q", tokenAudiences, requestedAudiences)
316 }
317
318
319
320 sa, err := j.validator.Validate(ctx, tokenData, public, private)
321 if err != nil {
322 return nil, false, err
323 }
324
325 return &authenticator.Response{
326 User: sa.UserInfo(),
327 Audiences: auds,
328 }, true, nil
329 }
330
331
332
333
334
335
336
337 func (j *jwtTokenAuthenticator) hasCorrectIssuer(tokenData string) bool {
338 if strings.HasPrefix(strings.TrimSpace(tokenData), "{") {
339 return false
340 }
341 parts := strings.Split(tokenData, ".")
342 if len(parts) != 3 {
343 return false
344 }
345 payload, err := base64.RawURLEncoding.DecodeString(parts[1])
346 if err != nil {
347 return false
348 }
349 claims := struct {
350
351 Issuer string `json:"iss"`
352 }{}
353 if err := json.Unmarshal(payload, &claims); err != nil {
354 return false
355 }
356 return j.issuers[claims.Issuer]
357 }
358
View as plain text