diff --git a/config/v1/types.go b/config/v1/types.go index ca3a3e9..4999765 100644 --- a/config/v1/types.go +++ b/config/v1/types.go @@ -88,6 +88,66 @@ type CredentialProvider struct { // to pass argument to the plugin. // +optional Env []ExecEnvVar `json:"env,omitempty"` + + // tokenAttributes is the configuration for the service account token that will be passed to the plugin. + // The credential provider opts in to using service account tokens for image pull by setting this field. + // When this field is set, kubelet will generate a service account token bound to the pod for which the + // image is being pulled and pass to the plugin as part of CredentialProviderRequest along with other + // attributes required by the plugin. + // + // The service account metadata and token attributes will be used as a dimension to cache + // the credentials in kubelet. The cache key is generated by combining the service account metadata + // (namespace, name, UID, and annotations key+value for the keys defined in + // serviceAccountTokenAttribute.requiredServiceAccountAnnotationKeys and serviceAccountTokenAttribute.optionalServiceAccountAnnotationKeys). + // The pod metadata (namespace, name, UID) that are in the service account token are not used as a dimension + // to cache the credentials in kubelet. This means workloads that are using the same service account + // could end up using the same credentials for image pull. For plugins that don't want this behavior, or + // plugins that operate in pass-through mode; i.e., they return the service account token as-is, they + // can set the credentialProviderResponse.cacheDuration to 0. This will disable the caching of + // credentials in kubelet and the plugin will be invoked for every image pull. This does result in + // token generation overhead for every image pull, but it is the only way to ensure that the + // credentials are not shared across pods (even if they are using the same service account). + // +optional + TokenAttributes *ServiceAccountTokenAttributes `json:"tokenAttributes,omitempty"` +} + +// ServiceAccountTokenAttributes is the configuration for the service account token that will be passed to the plugin. +type ServiceAccountTokenAttributes struct { + // serviceAccountTokenAudience is the intended audience for the projected service account token. + // +required + ServiceAccountTokenAudience string `json:"serviceAccountTokenAudience"` + + // requireServiceAccount indicates whether the plugin requires the pod to have a service account. + // If set to true, kubelet will only invoke the plugin if the pod has a service account. + // If set to false, kubelet will invoke the plugin even if the pod does not have a service account + // and will not include a token in the CredentialProviderRequest in that scenario. This is useful for plugins that + // are used to pull images for pods without service accounts (e.g., static pods). + // +required + RequireServiceAccount *bool `json:"requireServiceAccount"` + + // requiredServiceAccountAnnotationKeys is the list of annotation keys that the plugin is interested in + // and that are required to be present in the service account. + // The keys defined in this list will be extracted from the corresponding service account and passed + // to the plugin as part of the CredentialProviderRequest. If any of the keys defined in this list + // are not present in the service account, kubelet will not invoke the plugin and will return an error. + // This field is optional and may be empty. Plugins may use this field to extract + // additional information required to fetch credentials or allow workloads to opt in to + // using service account tokens for image pull. + // If non-empty, requireServiceAccount must be set to true. + // +optional + // +listType=set + RequiredServiceAccountAnnotationKeys []string `json:"requiredServiceAccountAnnotationKeys,omitempty"` + + // optionalServiceAccountAnnotationKeys is the list of annotation keys that the plugin is interested in + // and that are optional to be present in the service account. + // The keys defined in this list will be extracted from the corresponding service account and passed + // to the plugin as part of the CredentialProviderRequest. The plugin is responsible for validating + // the existence of annotations and their values. + // This field is optional and may be empty. Plugins may use this field to extract + // additional information required to fetch credentials. + // +optional + // +listType=set + OptionalServiceAccountAnnotationKeys []string `json:"optionalServiceAccountAnnotationKeys,omitempty"` } // ExecEnvVar is used for setting environment variables when executing an exec-based diff --git a/config/v1/zz_generated.deepcopy.go b/config/v1/zz_generated.deepcopy.go index 8b51897..481dd98 100644 --- a/config/v1/zz_generated.deepcopy.go +++ b/config/v1/zz_generated.deepcopy.go @@ -49,6 +49,11 @@ func (in *CredentialProvider) DeepCopyInto(out *CredentialProvider) { *out = make([]ExecEnvVar, len(*in)) copy(*out, *in) } + if in.TokenAttributes != nil { + in, out := &in.TokenAttributes, &out.TokenAttributes + *out = new(ServiceAccountTokenAttributes) + (*in).DeepCopyInto(*out) + } return } @@ -109,3 +114,34 @@ func (in *ExecEnvVar) DeepCopy() *ExecEnvVar { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAccountTokenAttributes) DeepCopyInto(out *ServiceAccountTokenAttributes) { + *out = *in + if in.RequireServiceAccount != nil { + in, out := &in.RequireServiceAccount, &out.RequireServiceAccount + *out = new(bool) + **out = **in + } + if in.RequiredServiceAccountAnnotationKeys != nil { + in, out := &in.RequiredServiceAccountAnnotationKeys, &out.RequiredServiceAccountAnnotationKeys + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.OptionalServiceAccountAnnotationKeys != nil { + in, out := &in.OptionalServiceAccountAnnotationKeys, &out.OptionalServiceAccountAnnotationKeys + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountTokenAttributes. +func (in *ServiceAccountTokenAttributes) DeepCopy() *ServiceAccountTokenAttributes { + if in == nil { + return nil + } + out := new(ServiceAccountTokenAttributes) + in.DeepCopyInto(out) + return out +}