Skip to content

Commit 41bd600

Browse files
committed
Add CRIOCredentialProviderConfig API and related functionality
- Add feature gate for CRIOCredentialProviderConfig in various feature gate manifests. Signed-off-by: Qi Wang <[email protected]>
1 parent 1b67472 commit 41bd600

20 files changed

+1452
-0
lines changed

config/v1alpha1/register.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
4040
&ImagePolicyList{},
4141
&ClusterImagePolicy{},
4242
&ClusterImagePolicyList{},
43+
&CRIOCredentialProviderConfig{},
44+
&CRIOCredentialProviderConfigList{},
4345
)
4446
metav1.AddToGroupVersion(scheme, GroupVersion)
4547
return nil
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
2+
name: "CRIOCredentialProviderConfig"
3+
crdName: "criocredentialproviderconfigs.config.openshift.io"
4+
featureGates:
5+
- CRIOCredentialProviderConfig
6+
tests:
7+
onCreate:
8+
- name: Should create a valid CRIOCredentialProviderConfig
9+
initial: |
10+
apiVersion: config.openshift.io/v1alpha1
11+
kind: CRIOCredentialProviderConfig
12+
spec:
13+
matchImages:
14+
- 123456789.dkr.ecr.us-east-1.amazonaws.com
15+
- "*.azurecr.io"
16+
- gcr.io
17+
- "*.*.registry.io"
18+
- registry.io:8080/path
19+
expected: |
20+
apiVersion: config.openshift.io/v1alpha1
21+
kind: CRIOCredentialProviderConfig
22+
spec:
23+
matchImages:
24+
- 123456789.dkr.ecr.us-east-1.amazonaws.com
25+
- "*.azurecr.io"
26+
- gcr.io
27+
- "*.*.registry.io"
28+
- registry.io:8080/path
29+
- name: Should reject matchImages with invalid characters
30+
initial: |
31+
apiVersion: config.openshift.io/v1alpha1
32+
kind: CRIOCredentialProviderConfig
33+
spec:
34+
matchImages:
35+
- "reg!stry.io"
36+
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name with optional wildcard, port, and path"
37+
- name: Should reject matchImages wildcard in the path
38+
initial: |
39+
apiVersion: config.openshift.io/v1alpha1
40+
kind: CRIOCredentialProviderConfig
41+
spec:
42+
matchImages:
43+
- "registry.io:8080/pa*th"
44+
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name with optional wildcard, port, and path"
45+
- name: Should reject wildcard for partial subdomains
46+
initial: |
47+
apiVersion: config.openshift.io/v1alpha1
48+
kind: CRIOCredentialProviderConfig
49+
spec:
50+
matchImages:
51+
- "example.app*.com"
52+
expectedError: "spec.matchImages[0]: Invalid value: \"string\": invalid matchImages value, must be a valid fully qualified domain name with optional wildcard, port, and path"
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package v1alpha1
2+
3+
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4+
5+
// +genclient
6+
// +genclient:nonNamespaced
7+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
8+
9+
// CRIOCredentialProviderConfig holds cluster-wide configurations for CRI-O credential provider. CRI-O credential provider is a binary shipped with CRI-O that provides a way to obtain container image pull credentials from external sources.
10+
// 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.
11+
// 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.
12+
//
13+
// 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.
14+
// +kubebuilder:object:root=true
15+
// +kubebuilder:resource:path=criocredentialproviderconfigs,scope=Cluster
16+
// +kubebuilder:subresource:status
17+
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1929
18+
// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=config-operator,operatorOrdering=01
19+
// +openshift:enable:FeatureGate=CRIOCredentialProviderConfig
20+
// +openshift:compatibility-gen:level=4
21+
type CRIOCredentialProviderConfig struct {
22+
metav1.TypeMeta `json:",inline"`
23+
24+
// metadata is the standard object's metadata.
25+
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
26+
// +optional
27+
metav1.ObjectMeta `json:"metadata"`
28+
29+
// spec defines the desired configuration of the CRIO Credential Provider.
30+
// This field is required and must be provided when creating the resource.
31+
// +required
32+
Spec CRIOCredentialProviderConfigSpec `json:"spec,omitzero"`
33+
34+
// status represents the current state of the CRIOCredentialProviderConfig.
35+
// When omitted or nil, it indicates that the status has not yet been set by the controller.
36+
// The controller will populate this field with validation conditions and operational state.
37+
// +optional
38+
Status *CRIOCredentialProviderConfigStatus `json:"status,omitempty"`
39+
}
40+
41+
// CRIOCredentialProviderConfigSpec defines the desired configuration of the CRI-O Credential Provider.
42+
type CRIOCredentialProviderConfigSpec struct {
43+
// matchImages is a required list of string patterns used to determine whether
44+
// the CRI-O credential provider should be invoked for a given image. This list is
45+
// passed to the kubelet CredentialProviderConfig, and if any pattern matches
46+
// the requested image, CRI-O credential provider will be invoked to obtain credentials for pulling
47+
// that image or its mirrors.
48+
//
49+
// This field is required and must contain between 1 and 50 entries.
50+
// The list is treated as a set, so duplicate entries are not allowed.
51+
//
52+
// For more details, see:
53+
// - https://kubernetes.io/docs/tasks/administer-cluster/kubelet-credential-provider/
54+
// - https://github.com/cri-o/crio-credential-provider#architecture
55+
//
56+
// Each entry in matchImages is a pattern which can optionally contain a port and a path.
57+
// Wildcards ('*') are supported for full subdomain labels, such as '*.k8s.io' or 'k8s.*.io',
58+
// and for top-level domains, such as 'k8s.*' (which matches 'k8s.io' or 'k8s.net').
59+
// Wildcards are not allowed in the port or path, nor may they appear in the middle of a hostname label.
60+
// For example, '*.example.com' is valid, but 'example*.*.com' is not.
61+
// Each wildcard matches only a single domain label,
62+
// so '*.io' does **not** match '*.k8s.io'.
63+
//
64+
// A match exists between an image and a matchImage when all of the below are true:
65+
// - Both contain the same number of domain parts and each part matches.
66+
// - The URL path of an matchImages must be a prefix of the target image URL path.
67+
// - If the matchImages contains a port, then the port must match in the image as well.
68+
//
69+
// Example values of matchImages:
70+
// - 123456789.dkr.ecr.us-east-1.amazonaws.com
71+
// - *.azurecr.io
72+
// - gcr.io
73+
// - *.*.registry.io
74+
// - registry.io:8080/path
75+
//
76+
// +kubebuilder:validation:MaxItems=50
77+
// +kubebuilder:validation:MinItems=1
78+
// +listType=set
79+
// +required
80+
MatchImages []MatchImage `json:"matchImages,omitempty"`
81+
}
82+
83+
// MatchImage is a string pattern used to match container image registry addresses.
84+
// It must be a valid fully qualified domain name with optional wildcard, port, and path.
85+
// The maximum length is 512 characters.
86+
//
87+
// Wildcards ('*') are supported for full subdomain labels and top-level domains.
88+
// Each entry can optionally contain a port (e.g., :8080) and a path (e.g., /path).
89+
// Wildcards are not allowed in the port or path portions.
90+
//
91+
// Examples:
92+
// - "registry.io" - matches exactly registry.io
93+
// - "*.azurecr.io" - matches any single subdomain of azurecr.io
94+
// - "registry.io:8080/path" - matches with specific port and path prefix
95+
//
96+
// +kubebuilder:validation:MaxLength=512
97+
// +kubebuilder:validation:XValidation:rule=`self.matches('^((\\*|[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)(\\.(\\*|[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?))*)(:[0-9]+)?(/[-a-zA-Z0-9_/]*)?$')`,message="invalid matchImages value, must be a valid fully qualified domain name with optional wildcard, port, and path"
98+
type MatchImage string
99+
100+
// +k8s:deepcopy-gen=true
101+
// CRIOCredentialProviderConfigStatus defines the observed state of CRIOCredentialProviderConfig
102+
type CRIOCredentialProviderConfigStatus struct {
103+
// conditions represent the latest available observations of the configuration state.
104+
// When omitted or empty, it indicates that no conditions have been reported yet.
105+
// The maximum number of conditions is 4.
106+
// Conditions are stored as a map keyed by condition type, ensuring uniqueness.
107+
//
108+
// Expected condition types include:
109+
// - "Validated": indicates whether the matchImages configuration is valid
110+
// +optional
111+
// +kubebuilder:validation:MaxItems=4
112+
// +listType=map
113+
// +listMapKey=type
114+
Conditions []metav1.Condition `json:"conditions,omitempty"`
115+
}
116+
117+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
118+
119+
// CRIOCredentialProviderConfigList contains a list of CRIOCredentialProviderConfig resources
120+
//
121+
// 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.
122+
// +openshift:compatibility-gen:level=4
123+
type CRIOCredentialProviderConfigList struct {
124+
metav1.TypeMeta `json:",inline"`
125+
126+
// metadata is the standard list's metadata.
127+
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
128+
metav1.ListMeta `json:"metadata"`
129+
130+
Items []CRIOCredentialProviderConfig `json:"items"`
131+
}
132+
133+
const (
134+
135+
// ConditionTypeValidated is a condition type that indicates whether the CRIOCredentialProviderConfig
136+
// matchImages configuration has been validated successfully.
137+
// When True, all matchImage patterns are valid and have been applied.
138+
// When False, the configuration contains errors (see Reason for details).
139+
// Possible reasons for False status:
140+
// - ValidationFailed: matchImages contains invalid patterns
141+
// - ConfigurationPartiallyApplied: some matchImage entries were ignored due to conflicts
142+
ConditionTypeValidated = "Validated"
143+
144+
// ReasonValidationFailed is a condition reason used with ConditionTypeValidated=False
145+
// to indicate that the matchImages configuration contains one or more invalid registry patterns
146+
// that do not conform to the required format (valid FQDN with optional wildcard, port, and path).
147+
ReasonValidationFailed = "ValidationFailed"
148+
149+
// ReasonConfigurationPartiallyApplied is a condition reason used with ConditionTypeValidated=False
150+
// to indicate that some matchImage entries were ignored due to conflicts or overlapping patterns.
151+
// The condition message will contain details about which entries were ignored and why.
152+
ReasonConfigurationPartiallyApplied = "ConfigurationPartiallyApplied"
153+
)

0 commit comments

Comments
 (0)