You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: keps/sig-auth/4412-projected-service-account-tokens-for-kubelet-image-credential-providers/README.md
+34-6Lines changed: 34 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -316,6 +316,7 @@ the design is written to meet the following criteria:
316
316
- No changes to any registry
317
317
- Minimal changes to Kubelet
318
318
- Minimal changes to Kubelet credential providers
319
+
- Minimal changes to Kube API Server
319
320
320
321
## Design Details
321
322
@@ -333,9 +334,10 @@ Adding a new field `TokenAttributes` to the `CredentialProvider` struct in the k
333
334
1.`ServiceAccountTokenAudience` is the intended audience for the credentials. If set, the kubelet will generate a service account token for the audience and pass it to the plugin.
334
335
1. Only a single audience can be configured.
335
336
2. The credential provider can be set up multiple times for each audience.
337
+
1. The name in the credential provider config must match the name of the provider executable as seen by the kubelet. To configure multiple instances of the same provider with different audiences, the name of the provider executable must be different and this can be done by creating a symlink to the same executable with a different name.
336
338
3. By setting this field, the credential provider is opting into using service account tokens for image pull.
337
339
2.`ServiceAccountAnnotationKeys` is the list of annotation keys that the plugin is interested in. The keys defined in this list will be extracted from the corresponding service account
338
-
and passed to the plugin as part of `CredentialProviderRequest`. Plugins can use to extract additional information required to fetch credentials. The plugin is responsible for validating the existence of annotations and their values.
340
+
and passed to the plugin as part of `CredentialProviderRequest`. Plugins can use to extract additional information required to fetch credentials. The plugin is responsible for validating the existence of annotations and their values. There are existing integrations like Azure and GCP that use the extra metadata to link the KSA name to a cloud identity, and this field will allow them to continue to do so. None of the existing integrations use this metadata as any form of security decision, it is simply to aid in doing token exchanges with the KSA token.
339
341
1. Service account annotations are significantly more stable (and map naturally to the service account being the partioning dimension).
340
342
2. This field makes the provider opt into getting the annotations it wants, avoids sending arbitrary annotation contents down to the plugin (including stuff like client-side apply annotations) and shrinks the set of annotations that could invalidate the cache.
341
343
3. This field can't be set without setting the `ServiceAccountTokenAudience` field.
@@ -357,7 +359,7 @@ The configuration will not support a plugin to function in 2 modes simultaneousl
357
359
+ //
358
360
+ // The service account metadata and token attributes will be used as a dimension to cache
359
361
+ // the credentials in kubelet. The cache key is generated by combining the service account metadata
360
-
+ // (namespace, name, UID, and annotations map with keys defined in ServiceAccountTokenAttribute.serviceAccountAnnotationKeys).
362
+
+ // (namespace, name, UID, and annotations key+value for the keys defined in ServiceAccountTokenAttribute.serviceAccountAnnotationKeys).
361
363
+ TokenAttributes *ServiceAccountTokenAttributes
362
364
+}
363
365
+
@@ -397,6 +399,7 @@ providers:
397
399
serviceAccountAnnotationKeys:
398
400
- domain.io/identity-id
399
401
- domain.io/identity-type
402
+
- domain.io/annotation-that-does-not-exist
400
403
```
401
404
402
405
##### Kubernetes API Server (KAS) Changes
@@ -406,6 +409,9 @@ Add a new flag `--allowed-kubelet-audiences` to KAS to allow configuring the lis
406
409
The node audience restriction will be enforced by the [NodeRestriction admission controller](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction)
407
410
and kubelet will only be allowed to generate a service account token for the audience configured in the credential provider configuration if it is present in the list of audiences configured in KAS.
408
411
412
+
Today we only verify the SA in KAS and allow the kubelet to generate a token for any audience. We want to start verifying the audience as well, so we need to be explicit here about what audiences are allowed.
413
+
The other sources of audiences for the SA token can be observed via the Kubernetes API but this one can't, so we're adding the flag.
414
+
409
415
#### Credential Provider Request API
410
416
411
417
Add `ServiceAccountToken` and `ServiceAccountAnnotations` fields to `CredentialProviderRequest`.
@@ -460,6 +466,10 @@ Example credential provider request:
460
466
"serviceAccountAnnotations": {
461
467
"domain.io/identity-id": "12345",
462
468
"domain.io/identity-type": "user"
469
+
// In the tokenAttributes.serviceAccountAnnotationKeys field in the credential provider configuration above we have configured
470
+
// domain.io/annotation-that-does-not-exist which is not present in the service account annotations. Because of this, this annotation
471
+
// will not be passed to the plugin. The plugin is responsible for validating the existence of annotations and their values that's required
472
+
// to fetch credentials.
463
473
}
464
474
}
465
475
```
@@ -493,7 +503,9 @@ Notes from reviewing the current KEP and discussion with @stlaz:
493
503
2. Same KSA for the image will result in allowing pod to use the image.
494
504
1. How would expiry work in this scenario?
495
505
1. I think it'll just be tied to the KSA and not so much to the expiry of the token because we're doing the same thing with image pull secrets (considered valid until deleted and recreated). Deletion and recreation of KSA will result in change in UID and that'll result in KSA not found in cache for the image (assuming the key used to store in cache is consistent with the cache key used in the credential provider cache that takes UID into consideration). Need to share the cache key generation logic to be consistent.
496
-
3. Need an update to `ImagePullCredentials` struct to also store coordinates of the KSA
506
+
3. Need an update to `ImagePullCredentials` struct to also store coordinates of the KSA.
507
+
508
+
Until the two implementations are updated to work together, the alpha implementation of this KEP will use the KSA token based flow unless the pod is using image pull policy set to `Always`. This keeps the feature from misbehaving until we fix the implementations.
497
509
498
510
### Test Plan
499
511
@@ -689,7 +701,17 @@ enhancement:
689
701
CRI or CNI may require updating that component before the kubelet.
690
702
-->
691
703
692
-
Not applicable because this feature is contained to only the kubelet and does not require communication to other components.
704
+
<!-- What about skew between kubelet and old/new credential plugins? How does a kubelet admin migrate to the new approach, one workload at a time? I assume all kubelets would need to be updated with new config/plugins and then restarted, followed by upgrades to workloads?
705
+
706
+
Also API server config needs to be updated because kubelets can safely use this feature. -->
707
+
708
+
To migrate to the new approach,
709
+
710
+
1. KAS will need to be updated to the new version to configure the list of audiences for which the kubelet is allowed to generate service account tokens for image pulls via the `--allowed-kubelet-audiences` flag.
711
+
2. kubelet on the node needs to be updated to enable the feature flag and configure the credential provider to use service account tokens for image pull via the `TokenAttributes` field in the kubelet credential provider configuration.
712
+
1. The credential provider plugin will need to be updated to use the service account token for the audience configured in the kubelet credential provider configuration.
713
+
714
+
Migration of the workloads to the new approach can be done per image or per registry basis by configuring the credential provider multiple times with different names for the same plugin (w or w/o service account tokens, different audiences).
693
715
694
716
## Production Readiness Review Questionnaire
695
717
@@ -955,6 +977,7 @@ Focusing mostly on:
955
977
-->
956
978
957
979
Yes. Kubelet will request a KSA token from KAS for pod + KSA for every provider (audience) that is configured to use service account tokens for image pull.
980
+
The load is small because the token generation happens only once during pod startup.
958
981
959
982
###### Will enabling / using this feature result in introducing new API types?
960
983
@@ -975,7 +998,10 @@ Describe them, providing:
975
998
- Estimated increase:
976
999
-->
977
1000
978
-
No.
1001
+
This depends on the credential provider plugin implementation on how it fetches the credentials using the service account token.
1002
+
The plugin will now be called for every unique KSA + (image/registry) combination that is being pulled if not already cached unlike
1003
+
today where the cache is based on the image/registry URL. This could result in more calls to the cloud provider from the plugin to
1004
+
exchange the KSA token for the credentials.
979
1005
980
1006
###### Will enabling / using this feature result in increasing size or count of the existing API objects?
981
1007
@@ -999,7 +1025,9 @@ Think about adding additional work or introducing new steps in between
0 commit comments