Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
feature-gate.release.openshift.io/CRIOCredentialProviderConfig: "true"
name: criocredentialproviderconfigs.config.openshift.io
spec:
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: |-
CRIOCredentialProviderConfig holds cluster-wide singleton resource configurations for CRI-O credential provider, the name of this instance is "cluster". CRI-O credential provider is a binary shipped with CRI-O that provides a way to obtain container image pull credentials from external sources.
For example, it can be used to fetch mirror registry credentials from secrets resources in the cluster within the same namespace the pod will be running in.
CRIOCredentialProviderConfig configuration specifies the pod image sources registries that should trigger the CRI-O credential provider execution, which will resolve the CRI-O mirror configurations and obtain the necessary credentials for pod creation.
Note: Configuration changes will only take effect after the kubelet restarts, which is automatically managed by the cluster during rollout.

The resource is a singleton named "cluster".

Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: |-
spec defines the desired configuration of the CRI-O Credential Provider.
This field is required and must be provided when creating the resource.
minProperties: 0
properties:
matchImages:
description: |-
matchImages is a list of string patterns used to determine whether
the CRI-O credential provider should be invoked for a given image. This list is
passed to the kubelet CredentialProviderConfig, and if any pattern matches
the requested image, CRI-O credential provider will be invoked to obtain credentials for pulling
that image or its mirrors.
Depending on the platform, the CRI-O credential provider may be installed alongside an existing platform specific provider.
Conflicts between the existing platform specific provider image match configuration and this list will be handled by
the following precedence rule: credentials from built-in kubelet providers (e.g., ECR, GCR, ACR) take precedence over those
from the CRIOCredentialProviderConfig when both match the same image.
To avoid uncertainty, it is recommended to avoid configuring your private image patterns to overlap with
existing platform specific provider config(e.g., the entries from https://github.com/openshift/machine-config-operator/blob/main/templates/common/aws/files/etc-kubernetes-credential-providers-ecr-credential-provider.yaml).
You can check the resource's Status conditions
to see if any entries were ignored due to exact matches with known built-in provider patterns.

This field is optional, the items of the list must contain between 1 and 50 entries.
The list is treated as a set, so duplicate entries are not allowed.

For more details, see:
https://kubernetes.io/docs/tasks/administer-cluster/kubelet-credential-provider/
https://github.com/cri-o/crio-credential-provider#architecture

Each entry in matchImages is a pattern which can optionally contain a port and a path. Each entry must be no longer than 512 characters.
Wildcards ('*') are supported for full subdomain labels, such as '*.k8s.io' or 'k8s.*.io',
and for top-level domains, such as 'k8s.*' (which matches 'k8s.io' or 'k8s.net').
A global wildcard '*' (matching any domain) is not allowed.
Wildcards may replace an entire hostname label (e.g., *.example.com), but they cannot appear within a label (e.g., f*oo.example.com) and are not allowed in the port or path.
For example, 'example.*.com' is valid, but 'exa*mple.*.com' is not.
Each wildcard matches only a single domain label,
so '*.io' does **not** match '*.k8s.io'.

A match exists between an image and a matchImage when all of the below are true:
Both contain the same number of domain parts and each part matches.
The URL path of an matchImages must be a prefix of the target image URL path.
If the matchImages contains a port, then the port must match in the image as well.

Example values of matchImages:
- 123456789.dkr.ecr.us-east-1.amazonaws.com
- *.azurecr.io
- gcr.io
- *.*.registry.io
- registry.io:8080/path
items:
description: |-
MatchImage is a string pattern used to match container image registry addresses.
It must be a valid fully qualified domain name with optional wildcard, port, and path.
The maximum length is 512 characters.

Wildcards ('*') are supported for full subdomain labels and top-level domains.
Each entry can optionally contain a port (e.g., :8080) and a path (e.g., /path).
Wildcards are not allowed in the port or path portions.

Examples:
- "registry.io" - matches exactly registry.io
- "*.azurecr.io" - matches any single subdomain of azurecr.io
- "registry.io:8080/path" - matches with specific port and path prefix
maxLength: 512
minLength: 1
type: string
x-kubernetes-validations:
- message: global wildcard '*' is not allowed
rule: self != '*'
- message: invalid matchImages value, must be a valid fully qualified
domain name in lowercase with optional wildcard, port, and path
rule: self.matches('^((\\*|[a-z0-9]([a-z0-9-]*[a-z0-9])?)(\\.(\\*|[a-z0-9]([a-z0-9-]*[a-z0-9])?))*)(:[0-9]+)?(/[-a-z0-9._/]*)?$')
maxItems: 50
minItems: 1
type: array
x-kubernetes-list-type: set
type: object
status:
description: |-
status represents the current state of the CRIOCredentialProviderConfig.
When omitted or nil, it indicates that the status has not yet been set by the controller.
The controller will populate this field with validation conditions and operational state.
minProperties: 1
properties:
conditions:
description: |-
conditions represent the latest available observations of the configuration state.
When omitted, it indicates that no conditions have been reported yet.
The maximum number of conditions is 16.
Conditions are stored as a map keyed by condition type, ensuring uniqueness.

Expected condition types include:
"Validated": indicates whether the matchImages configuration is valid
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
maxItems: 16
minItems: 1
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
type: object
required:
- spec
type: object
x-kubernetes-validations:
- message: criocredentialproviderconfig is a singleton, .metadata.name must
be 'cluster'
rule: self.metadata.name == 'cluster'
served: true
storage: false
subresources:
status: {}
2 changes: 2 additions & 0 deletions config/v1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ClusterImagePolicyList{},
&InsightsDataGather{},
&InsightsDataGatherList{},
&CRIOCredentialProviderConfig{},
&CRIOCredentialProviderConfigList{},
)
metav1.AddToGroupVersion(scheme, GroupVersion)
return nil
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
name: "CRIOCredentialProviderConfig"
crdName: "criocredentialproviderconfigs.config.openshift.io"
version: v1
featureGates:
- CRIOCredentialProviderConfig
tests:
onCreate:
- name: Should create a minimal CRIOCredentialProviderConfig
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec: {}
expected: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec: {}
- name: Should create a valid CRIOCredentialProviderConfig
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- 123456789.dkr.ecr.us-east-1.amazonaws.com
- "*.azurecr.io"
- gcr.io
- "*.*.registry.io"
- registry.io:8080/path
expected: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- 123456789.dkr.ecr.us-east-1.amazonaws.com
- "*.azurecr.io"
- gcr.io
- "*.*.registry.io"
- registry.io:8080/path
- name: Should reject matchImages with invalid characters
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "reg!stry.io"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name in lowercase with optional wildcard, port, and path"
- name: Should reject matchImages with uppercase hostname
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "Registry.COM"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name in lowercase with optional wildcard, port, and path"
- name: Should reject matchImages with uppercase in the path
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "registry.io/PaTh"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name in lowercase with optional wildcard, port, and path"
- name: Should reject matchImages wildcard in the path
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "registry.io:8080/pa*th"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name in lowercase with optional wildcard, port, and path"
- name: Should reject wildcard for partial subdomains
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "example.app*.com"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name in lowercase with optional wildcard, port, and path"
- name: Should reject global wildcard '*'
initial: |
apiVersion: config.openshift.io/v1
kind: CRIOCredentialProviderConfig
metadata:
name: cluster
spec:
matchImages:
- "*"
expectedError: "spec.matchImages[0]: Invalid value: \"string\": global wildcard '*' is not allowed"
Loading