diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCAuthConfig.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCAuthConfig.yaml
new file mode 100644
index 00000000000..65af2e3bc65
--- /dev/null
+++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCAuthConfig.yaml
@@ -0,0 +1,330 @@
+apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
+name: "Authentication"
+crdName: authentications.config.openshift.io
+featureGates:
+- ExternalOIDCWithNewAuthConfigFields
+tests:
+ onCreate:
+ # DiscoveryURL Tests
+ - name: Valid discoveryURL
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: https://auth.example.com/.well-known/openid-configuration
+
+ - name: discoveryURL must be a valid URL
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: not-a-valid-url
+ error: "discoveryURL must be a valid URL"
+
+ - name: discoveryURL must not contain user info
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: https://user:pass@auth.example.com/
+ error: "discoveryURL must not contain user info"
+
+ - name: discoveryURL exceeds max length
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: "https://auth.example.com/$(printf 'a%.0s' {1..2050})"
+ error: "discoveryURL: Too long"
+
+ - name: discoveryURL must not contain fragment
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: https://auth.example.com/#fragment
+ error: "discoveryURL must not contain a fragment"
+
+ - name: discoveryURL must use https
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: http://auth.example.com/invalid
+ error: "discoveryURL must use https scheme"
+
+ - name: discoveryURL must not contain query
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: https://auth.example.com/path?foo=bar
+ error: "discoveryURL must not contain query parameters"
+
+ - name: discoveryURL must be different from URL
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com/
+ audiences: ['openshift-aud']
+ discoveryURL: https://auth.example.com/
+ error: "discoveryURL must be different from URL"
+
+ # AudienceMatchPolicy Tests
+
+ - name: Valid AudienceMatchPolicy
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com
+ audiences: ['openshift-aud']
+ audienceMatchPolicy: MatchAny
+
+ - name: Invalid AudienceMatchPolicy
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: TokenIssuer
+ spec:
+ issuerURL: https://auth.example.com
+ audiences: ['openshift-aud']
+ audienceMatchPolicy: InvalidPolicy
+ error: "audienceMatchPolicy: Unsupported value"
+
+ # TokenClaimValidationRule Tests
+ - name: Valid RequiredClaim rule
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://auth.example.com
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: RequiredClaim
+ requiredClaim:
+ claim: "role"
+ requiredValue: "admin"
+
+ - name: Missing requiredClaim when type is RequiredClaim
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://auth.example.com
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: RequiredClaim
+ expectedError: "requiredClaim must be set when type is 'RequiredClaim'"
+
+ - name: Valid ExpressionRule configuration
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: Expression
+ expressionRule:
+ expression: "claims.email.endsWith('@example.com')"
+ message: "email must be from example.com"
+ expected: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: Expression
+ expressionRule:
+ expression: "claims.email.endsWith('@example.com')"
+ message: "email must be from example.com"
+
+ - name: Missing expressionRule for Expression type
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: Expression
+ expectedError: "expressionRule must be set when type is 'Expression', and forbidden otherwise"
+
+ - name: Expression too long
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: Expression
+ expressionRule:
+ expression: "{{longExpression}}"
+ replacements:
+ longExpression: "{{'x' * 5000}}"
+ expectedError: "expression: Too long: must have at most 4096 characters"
+
+ - name: Empty expression in expressionRule
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ claimValidationRules:
+ - type: Expression
+ expressionRule:
+ expression: ""
+ message: "must not be empty"
+ expectedError: "expression: Invalid value: \"\": validation failed: value length must be at least 1"
+
+ # TokenUserValidationRule Tests
+
+ - name: Valid TokenUserValidationRule with expression and message
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: "user.username.startsWith('admin')"
+ message: "Only admin users are allowed"
+ expected: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: "user.username.startsWith('admin')"
+ message: "Only admin users are allowed"
+
+ - name: Missing expression in TokenUserValidationRule
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - message: "Should never reach here"
+ expectedError: "expression: Required value"
+
+ - name: Expression too long in TokenUserValidationRule
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: "{{longExpression}}"
+ message: "This expression is too long"
+ replacements:
+ longExpression: "{{'x' * 5000}}"
+ expectedError: "expression: Too long: must have at most 4096 characters"
+
+ - name: Empty expression in TokenUserValidationRule
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: ""
+ message: "Empty expressions are invalid"
+ expectedError: "expression: Invalid value: \"\": validation failed: value length must be at least 1"
+
+ - name: Valid TokenUserValidationRule with expression only
+ initial: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: "user.groups.exists(g, g == 'admins')"
+ expected: |
+ apiVersion: config.openshift.io/v1
+ kind: Authentication
+ spec:
+ type: OIDC
+ oidcProviders:
+ - name: myoidc
+ issuer:
+ issuerURL: https://meh.tld
+ audiences: ['openshift-aud']
+ userValidationRules:
+ - expression: "user.groups.exists(g, g == 'admins')"
+
diff --git a/config/v1/types_authentication.go b/config/v1/types_authentication.go
index 52a41b2fef2..185a118af9e 100644
--- a/config/v1/types_authentication.go
+++ b/config/v1/types_authentication.go
@@ -5,7 +5,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDC;ExternalOIDCWithUIDAndExtraClaimMappings,rule="!has(self.spec.oidcProviders) || self.spec.oidcProviders.all(p, !has(p.oidcClients) || p.oidcClients.all(specC, self.status.oidcClients.exists(statusC, statusC.componentNamespace == specC.componentNamespace && statusC.componentName == specC.componentName) || (has(oldSelf.spec.oidcProviders) && oldSelf.spec.oidcProviders.exists(oldP, oldP.name == p.name && has(oldP.oidcClients) && oldP.oidcClients.exists(oldC, oldC.componentNamespace == specC.componentNamespace && oldC.componentName == specC.componentName)))))",message="all oidcClients in the oidcProviders must match their componentName and componentNamespace to either a previously configured oidcClient or they must exist in the status.oidcClients"
+// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDC;ExternalOIDCWithUIDAndExtraClaimMappings;ExternalOIDCWithNewAuthConfigFields,rule="!has(self.spec.oidcProviders) || self.spec.oidcProviders.all(p, !has(p.oidcClients) || p.oidcClients.all(specC, self.status.oidcClients.exists(statusC, statusC.componentNamespace == specC.componentNamespace && statusC.componentName == specC.componentName) || (has(oldSelf.spec.oidcProviders) && oldSelf.spec.oidcProviders.exists(oldP, oldP.name == p.name && has(oldP.oidcClients) && oldP.oidcClients.exists(oldC, oldC.componentNamespace == specC.componentNamespace && oldC.componentName == specC.componentName)))))",message="all oidcClients in the oidcProviders must match their componentName and componentNamespace to either a previously configured oidcClient or they must exist in the status.oidcClients"
// Authentication specifies cluster-wide settings for authentication (like OAuth and
// webhook token authenticators). The canonical name of an instance is `cluster`.
@@ -91,7 +91,7 @@ type AuthenticationSpec struct {
// +kubebuilder:validation:MaxItems=1
// +openshift:enable:FeatureGate=ExternalOIDC
// +openshift:enable:FeatureGate=ExternalOIDCWithUIDAndExtraClaimMappings
- // +optional
+ // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields
OIDCProviders []OIDCProvider `json:"oidcProviders,omitempty"`
}
@@ -243,11 +243,22 @@ type OIDCProvider struct {
// +listType=atomic
// +optional
ClaimValidationRules []TokenClaimValidationRule `json:"claimValidationRules,omitempty"`
+
+ // userValidationRules defines the set of rules used to validate claims in a user’s token.
+ // These rules determine whether a token subject is considered valid based on its claims.
+ // Each rule is evaluated independently.
+ // See the TokenUserValidationRule type for more information on rule structure.
+
+ // +listType=atomic
+ // +kubebuilder:validation:MaxItems=64
+ // +optional
+ UserValidationRules []TokenUserValidationRule `json:"userValidationRules,omitempty"`
}
// +kubebuilder:validation:MinLength=1
type TokenAudience string
+// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithNewAuthConfigFields,rule="self.discoveryURL.size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find('^.+[^/]') != self.issuerURL.find('^.+[^/]')) : true",message="discoveryURL must be different from issuerURL"
type TokenIssuer struct {
// issuerURL is a required field that configures the URL used to issue tokens
// by the identity provider.
@@ -275,7 +286,7 @@ type TokenIssuer struct {
//
// +listType=set
// +kubebuilder:validation:MinItems=1
- // +kubebuilder:validation:MaxItems=10
+ // +kubebuilder:validation:MaxItems=20
// +required
Audiences []TokenAudience `json:"audiences"`
@@ -291,8 +302,47 @@ type TokenIssuer struct {
//
// +optional
CertificateAuthority ConfigMapNameReference `json:"issuerCertificateAuthority"`
+
+ // discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ // used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ // as "{url}/.well-known/openid-configuration".
+ //
+ // The discoveryURL must:
+ // - Be a valid absolute URL.
+ // - Use the HTTPS scheme.
+ // - Not contain query parameters, user info, or fragments.
+ // - Be different from the value of `url` (ignoring trailing slashes)
+ //
+ // +optional
+ // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields
+ // +kubebuilder:validation:XValidation:rule="self.size() > 0 ? isURL(self) : true",message="discoveryURL must be a valid URL"
+ // +kubebuilder:validation:XValidation:rule="self.size() > 0 ? (isURL(self) && url(self).getScheme() == 'https') : true",message="discoveryURL must be a valid https URL"
+ // +kubebuilder:validation:XValidation:rule="self.matches('^[^?]*$')",message="discoveryURL must not contain query parameters"
+ // +kubebuilder:validation:XValidation:rule="self.matches('^[^#]*$')",message="discoveryURL must not contain fragments"
+ // +kubebuilder:validation:XValidation:rule="self.matches('^[^@]*$')",message="discoveryURL must not contain user info"
+ // +kubebuilder:validation:MaxLength=2048
+ DiscoveryURL *string `json:"discoveryURL,omitempty"`
+
+ // audienceMatchPolicy specifies how token audiences are matched.
+ // If omitted, the system applies a default policy.
+ // Valid values are:
+ // - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ //
+ // +optional
+ // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields
+ AudienceMatchPolicy *AudienceMatchPolicy `json:"audienceMatchPolicy,omitempty"`
}
+// AudienceMatchPolicyType is a set of valid values for Issuer.AudienceMatchPolicy.
+//
+// +kubebuilder:validation:Enum=MatchAny;""
+type AudienceMatchPolicy string
+
+// Valid types for AudienceMatchPolicyType
+const (
+ AudienceMatchPolicyMatchAny AudienceMatchPolicy = "MatchAny"
+)
+
type TokenClaimMappings struct {
// username is a required field that configures how the username of a cluster identity
// should be constructed from the claims in a JWT token issued by the identity provider.
@@ -717,15 +767,23 @@ type PrefixedClaimMapping struct {
Prefix string `json:"prefix"`
}
-// TokenValidationRuleType represents the different
-// claim validation rule types that can be configured.
-// +enum
+// TokenValidationRuleType defines the type of token validation rule.
+//
+// +kubebuilder:validation:Enum=RequiredClaim;Expression
type TokenValidationRuleType string
const (
- TokenValidationRuleTypeRequiredClaim = "RequiredClaim"
+ TokenValidationRuleRequiredClaim = "RequiredClaim"
+ TokenValidationRuleExpression = "Expression"
)
+// TokenClaimValidationRule represents a validation rule based on token claims.
+// If type is RequiredClaim, requiredClaim must be set.
+// If type is Expression, expressionRule must be set.
+//
+// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'RequiredClaim' ? has(self.requiredClaim) : !has(self.requiredClaim)",message="requiredClaim must be set when type is 'RequiredClaim', and forbidden otherwise"
+// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithNewAuthConfigFields,rule="has(self.type) && self.type == 'Expression' ? has(self.expressionRule) : !has(self.expressionRule)",message="expressionRule must be set when type is 'Expression', and forbidden otherwise"
+
type TokenClaimValidationRule struct {
// type is an optional field that configures the type of the validation rule.
//
@@ -738,23 +796,23 @@ type TokenClaimValidationRule struct {
//
// Defaults to 'RequiredClaim'.
//
- // +kubebuilder:validation:Enum={"RequiredClaim"}
// +kubebuilder:default="RequiredClaim"
Type TokenValidationRuleType `json:"type"`
- // requiredClaim is an optional field that configures the required claim
- // and value that the Kubernetes API server will use to validate if an incoming
- // JWT is valid for this identity provider.
- //
+ // requiredClaim allows configuring a required claim name and its expected value.
+ // RequiredClaim is used when type is RequiredClaim.
// +optional
RequiredClaim *TokenRequiredClaim `json:"requiredClaim,omitempty"`
+
+ // expressionRule contains the configuration for the "Expression" type.
+ // Must be set if type == "Expression".
+ //
+ // +optional
+ ExpressionRule *TokenExpressionRule `json:"expressionRule,omitempty"`
}
type TokenRequiredClaim struct {
- // claim is a required field that configures the name of the required claim.
- // When taken from the JWT claims, claim must be a string value.
- //
- // claim must not be an empty string ("").
+ // claim is a name of a required claim. Only claims with string values are supported.
//
// +kubebuilder:validation:MinLength=1
// +required
@@ -771,3 +829,49 @@ type TokenRequiredClaim struct {
// +required
RequiredValue string `json:"requiredValue"`
}
+
+// +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields
+type TokenExpressionRule struct {
+ // expression is a CEL expression evaluated against token claims.
+ // The expression must be a non-empty string and no longer than 4096 characters.
+ // This field is required.
+ //
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=4096
+ // +required
+ Expression string `json:"expression,omitempty"`
+
+ // message allows configuring the human-readable message that is returned
+ // from the Kubernetes API server when a token fails validation based on
+ // the CEL expression defined in 'expression'. This field is optional.
+ //
+ // +optional
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=256
+ Message string `json:"message,omitempty"`
+}
+
+// TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+// Each rule contains a CEL expression that is evaluated against the token’s claims.
+// If the expression evaluates to false, the token is rejected.
+// See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+// At least one rule must evaluate to true for the token to be considered valid.
+// +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields
+type TokenUserValidationRule struct {
+ // expression is a CEL expression that must evaluate
+ // to true for the token to be accepted. The expression is evaluated against the token's
+ // user information (e.g., username, groups). This field must be non-empty and may not
+ // exceed 4096 characters.
+ //
+ // +required
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=4096
+ Expression string `json:"expression,omitempty"`
+ // message is an optional, human-readable message returned by the API server when
+ // this validation rule fails. It can help clarify why a token was rejected.
+ //
+ // +optional
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=256
+ Message string `json:"message,omitempty"`
+}
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
index 4f67bf9e0ca..631a60ecd8b 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
index 2a3b60571cb..c52342acd39 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
@@ -79,34 +79,27 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -115,33 +108,18 @@ spec:
type: object
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -149,28 +127,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -185,40 +160,25 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -227,36 +187,28 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -266,15 +218,10 @@ spec:
x-kubernetes-list-type: set
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -285,77 +232,33 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -366,34 +269,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -409,8 +299,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -534,29 +451,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -630,10 +534,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -645,37 +547,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
index 195efce400b..35a93ad959c 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
index 4e8c79c3201..8f7ca9b741c 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
index 72c798fae70..3a12add701f 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index 998e804191f..e6df57e4854 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 75446be6cca..f7c5674b54b 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/config/v1/zz_generated.deepcopy.go b/config/v1/zz_generated.deepcopy.go
index 788e10479b6..4a300c62165 100644
--- a/config/v1/zz_generated.deepcopy.go
+++ b/config/v1/zz_generated.deepcopy.go
@@ -4599,6 +4599,11 @@ func (in *OIDCProvider) DeepCopyInto(out *OIDCProvider) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ if in.UserValidationRules != nil {
+ in, out := &in.UserValidationRules, &out.UserValidationRules
+ *out = make([]TokenUserValidationRule, len(*in))
+ copy(*out, *in)
+ }
return
}
@@ -6230,6 +6235,11 @@ func (in *TokenClaimValidationRule) DeepCopyInto(out *TokenClaimValidationRule)
*out = new(TokenRequiredClaim)
**out = **in
}
+ if in.ExpressionRule != nil {
+ in, out := &in.ExpressionRule, &out.ExpressionRule
+ *out = new(TokenExpressionRule)
+ **out = **in
+ }
return
}
@@ -6264,6 +6274,22 @@ func (in *TokenConfig) DeepCopy() *TokenConfig {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TokenExpressionRule) DeepCopyInto(out *TokenExpressionRule) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenExpressionRule.
+func (in *TokenExpressionRule) DeepCopy() *TokenExpressionRule {
+ if in == nil {
+ return nil
+ }
+ out := new(TokenExpressionRule)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TokenIssuer) DeepCopyInto(out *TokenIssuer) {
*out = *in
@@ -6273,6 +6299,16 @@ func (in *TokenIssuer) DeepCopyInto(out *TokenIssuer) {
copy(*out, *in)
}
out.CertificateAuthority = in.CertificateAuthority
+ if in.DiscoveryURL != nil {
+ in, out := &in.DiscoveryURL, &out.DiscoveryURL
+ *out = new(string)
+ **out = **in
+ }
+ if in.AudienceMatchPolicy != nil {
+ in, out := &in.AudienceMatchPolicy, &out.AudienceMatchPolicy
+ *out = new(AudienceMatchPolicy)
+ **out = **in
+ }
return
}
@@ -6302,6 +6338,22 @@ func (in *TokenRequiredClaim) DeepCopy() *TokenRequiredClaim {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TokenUserValidationRule) DeepCopyInto(out *TokenUserValidationRule) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenUserValidationRule.
+func (in *TokenUserValidationRule) DeepCopy() *TokenUserValidationRule {
+ if in == nil {
+ return nil
+ }
+ out := new(TokenUserValidationRule)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Update) DeepCopyInto(out *Update) {
*out = *in
diff --git a/config/v1/zz_generated.featuregated-crd-manifests.yaml b/config/v1/zz_generated.featuregated-crd-manifests.yaml
index 6d756e8f904..09d83050102 100644
--- a/config/v1/zz_generated.featuregated-crd-manifests.yaml
+++ b/config/v1/zz_generated.featuregated-crd-manifests.yaml
@@ -30,6 +30,7 @@ authentications.config.openshift.io:
Category: ""
FeatureGates:
- ExternalOIDC
+ - ExternalOIDCWithNewAuthConfigFields
- ExternalOIDCWithUIDAndExtraClaimMappings
FilenameOperatorName: config-operator
FilenameOperatorOrdering: "01"
diff --git a/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDC.yaml b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDC.yaml
index 06d4e0f041c..df833bc4129 100644
--- a/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDC.yaml
+++ b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDC.yaml
@@ -198,18 +198,38 @@ spec:
Validation rules are joined via an AND operation.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
@@ -241,8 +261,14 @@ spec:
Defaults to 'RequiredClaim'.
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
@@ -261,7 +287,7 @@ spec:
items:
minLength: 1
type: string
- maxItems: 10
+ maxItems: 20
minItems: 1
type: array
x-kubernetes-list-type: set
@@ -410,6 +436,37 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
+ maxItems: 64
+ type: array
+ x-kubernetes-list-type: atomic
required:
- claimMappings
- issuer
diff --git a/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml
new file mode 100644
index 00000000000..febd3a30378
--- /dev/null
+++ b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml
@@ -0,0 +1,647 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.openshift.io: https://github.com/openshift/api/pull/470
+ api.openshift.io/filename-cvo-runlevel: "0000_10"
+ api.openshift.io/filename-operator: config-operator
+ api.openshift.io/filename-ordering: "01"
+ feature-gate.release.openshift.io/ExternalOIDCWithNewAuthConfigFields: "true"
+ release.openshift.io/bootstrap-required: "true"
+ name: authentications.config.openshift.io
+spec:
+ group: config.openshift.io
+ names:
+ kind: Authentication
+ listKind: AuthenticationList
+ plural: authentications
+ singular: authentication
+ scope: Cluster
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ Authentication specifies cluster-wide settings for authentication (like OAuth and
+ webhook token authenticators). The canonical name of an instance is `cluster`.
+
+ Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
+ 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 holds user settable values for configuration
+ properties:
+ oauthMetadata:
+ description: |-
+ oauthMetadata contains the discovery endpoint data for OAuth 2.0
+ Authorization Server Metadata for an external OAuth server.
+ This discovery document can be viewed from its served location:
+ oc get --raw '/.well-known/oauth-authorization-server'
+ For further details, see the IETF Draft:
+ https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2
+ If oauthMetadata.name is non-empty, this value has precedence
+ over any metadata reference stored in status.
+ The key "oauthMetadata" is used to locate the data.
+ If specified and the config map or expected key is not found, no metadata is served.
+ If the specified metadata is not valid, no metadata is served.
+ The namespace for this config map is openshift-config.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced config
+ map
+ type: string
+ required:
+ - name
+ type: object
+ oidcProviders:
+ description: |-
+ oidcProviders are OIDC identity providers that can issue tokens
+ for this cluster
+ Can only be set if "Type" is set to "OIDC".
+
+ At most one provider can be configured.
+ items:
+ properties:
+ claimMappings:
+ description: |-
+ claimMappings is a required field that configures the rules to be used by
+ the Kubernetes API server for translating claims in a JWT token, issued
+ by the identity provider, to a cluster identity.
+ properties:
+ groups:
+ description: |-
+ groups is an optional field that configures how the groups of a cluster identity
+ should be constructed from the claims in a JWT token issued
+ by the identity provider.
+ When referencing a claim, if the claim is present in the JWT
+ token, its value must be a list of groups separated by a comma (',').
+ For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ properties:
+ claim:
+ description: |-
+ claim is a required field that configures the JWT token
+ claim whose value is assigned to the cluster identity
+ field associated with this mapping.
+ type: string
+ prefix:
+ description: |-
+ prefix is an optional field that configures the prefix that will be
+ applied to the cluster identity attribute during the process of mapping
+ JWT claims to cluster identity attributes.
+
+ When omitted (""), no prefix is applied to the cluster identity attribute.
+
+ Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ an array of strings "a", "b" and "c", the mapping will result in an
+ array of string "myoidc:a", "myoidc:b" and "myoidc:c".
+ type: string
+ required:
+ - claim
+ type: object
+ username:
+ description: |-
+ username is a required field that configures how the username of a cluster identity
+ should be constructed from the claims in a JWT token issued by the identity provider.
+ properties:
+ claim:
+ description: |-
+ claim is a required field that configures the JWT token
+ claim whose value is assigned to the cluster identity
+ field associated with this mapping.
+
+ claim must not be an empty string ("") and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ prefix:
+ description: |-
+ prefix configures the prefix that should be prepended to the value
+ of the JWT claim.
+
+ prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
+ properties:
+ prefixString:
+ description: |-
+ prefixString is a required field that configures the prefix that will
+ be applied to cluster identity username attribute
+ during the process of mapping JWT claims to cluster identity attributes.
+
+ prefixString must not be an empty string ("").
+ minLength: 1
+ type: string
+ required:
+ - prefixString
+ type: object
+ prefixPolicy:
+ description: |-
+ prefixPolicy is an optional field that configures how a prefix should be
+ applied to the value of the JWT claim specified in the 'claim' field.
+
+ Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
+
+ When set to 'Prefix', the value specified in the prefix field will be
+ prepended to the value of the JWT claim.
+ The prefix field must be set when prefixPolicy is 'Prefix'.
+
+ When set to 'NoPrefix', no prefix will be prepended to the value
+ of the JWT claim.
+
+ When omitted, this means no opinion and the platform is left to choose
+ any prefixes that are applied which is subject to change over time.
+ Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
+ when the claim is not 'email'.
+ As an example, consider the following scenario:
+ `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ - "username": the mapped value will be "https://myoidc.tld#userA"
+ - "email": the mapped value will be "userA@myoidc.tld"
+ enum:
+ - ""
+ - NoPrefix
+ - Prefix
+ type: string
+ required:
+ - claim
+ type: object
+ x-kubernetes-validations:
+ - message: prefix must be set if prefixPolicy is 'Prefix',
+ but must remain unset otherwise
+ rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
+ ''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
+ > 0) : !has(self.prefix)'
+ required:
+ - username
+ type: object
+ claimValidationRules:
+ description: |-
+ claimValidationRules is an optional field that configures the rules to
+ be used by the Kubernetes API server for validating the claims in a JWT
+ token issued by the identity provider.
+
+ Validation rules are joined via an AND operation.
+ items:
+ properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
+ requiredClaim:
+ description: |-
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
+ properties:
+ claim:
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
+ minLength: 1
+ type: string
+ requiredValue:
+ description: |-
+ requiredValue is a required field that configures the value that 'claim' must
+ have when taken from the incoming JWT claims.
+ If the value in the JWT claims does not match, the token
+ will be rejected for authentication.
+
+ requiredValue must not be an empty string ("").
+ minLength: 1
+ type: string
+ required:
+ - claim
+ - requiredValue
+ type: object
+ type:
+ default: RequiredClaim
+ description: |-
+ type is an optional field that configures the type of the validation rule.
+
+ Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
+
+ When set to 'RequiredClaim', the Kubernetes API server
+ will be configured to validate that the incoming JWT
+ contains the required claim and that its value matches
+ the required value.
+
+ Defaults to 'RequiredClaim'.
+ enum:
+ - RequiredClaim
+ - Expression
+ type: string
+ type: object
+ x-kubernetes-validations:
+ - message: expressionRule must be set when type is 'Expression',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''Expression'' ? has(self.expressionRule)
+ : !has(self.expressionRule)'
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
+ type: array
+ x-kubernetes-list-type: atomic
+ issuer:
+ description: |-
+ issuer is a required field that configures how the platform interacts
+ with the identity provider and how tokens issued from the identity provider
+ are evaluated by the Kubernetes API server.
+ properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
+ audiences:
+ description: |-
+ audiences is a required field that configures the acceptable audiences
+ the JWT token, issued by the identity provider, must be issued to.
+ At least one of the entries must match the 'aud' claim in the JWT token.
+
+ audiences must contain at least one entry and must not exceed ten entries.
+ items:
+ minLength: 1
+ type: string
+ maxItems: 20
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
+ issuerCertificateAuthority:
+ description: |-
+ issuerCertificateAuthority is an optional field that configures the
+ certificate authority, used by the Kubernetes API server, to validate
+ the connection to the identity provider when fetching discovery information.
+
+ When not specified, the system trust is used.
+
+ When specified, it must reference a ConfigMap in the openshift-config
+ namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
+ key in the data field of the ConfigMap.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced
+ config map
+ type: string
+ required:
+ - name
+ type: object
+ issuerURL:
+ description: |-
+ issuerURL is a required field that configures the URL used to issue tokens
+ by the identity provider.
+ The Kubernetes API server determines how authentication tokens should be handled
+ by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
+
+ Must be at least 1 character and must not exceed 512 characters in length.
+ Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
+ maxLength: 512
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must be a valid URL
+ rule: isURL(self)
+ - message: must use the 'https' scheme
+ rule: isURL(self) && url(self).getScheme() == 'https'
+ - message: must not have a query
+ rule: isURL(self) && url(self).getQuery() == {}
+ - message: must not have a fragment
+ rule: self.find('#(.+)$') == ''
+ - message: must not have user info
+ rule: self.find('@') == ''
+ required:
+ - audiences
+ - issuerURL
+ type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
+ name:
+ description: |-
+ name is a required field that configures the unique human-readable identifier
+ associated with the identity provider.
+ It is used to distinguish between multiple identity providers
+ and has no impact on token validation or authentication mechanics.
+
+ name must not be an empty string ("").
+ minLength: 1
+ type: string
+ oidcClients:
+ description: |-
+ oidcClients is an optional field that configures how on-cluster,
+ platform clients should request tokens from the identity provider.
+ oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ items:
+ description: |-
+ OIDCClientConfig configures how platform clients
+ interact with identity providers as an authentication
+ method
+ properties:
+ clientID:
+ description: |-
+ clientID is a required field that configures the client identifier, from
+ the identity provider, that the platform component uses for authentication
+ requests made to the identity provider.
+ The identity provider must accept this identifier for platform components
+ to be able to use the identity provider as an authentication mode.
+
+ clientID must not be an empty string ("").
+ minLength: 1
+ type: string
+ clientSecret:
+ description: |-
+ clientSecret is an optional field that configures the client secret used
+ by the platform component when making authentication requests to the identity provider.
+
+ When not specified, no client secret will be used when making authentication requests
+ to the identity provider.
+
+ When specified, clientSecret references a Secret in the 'openshift-config'
+ namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
+ The client secret will be used when making authentication requests to the identity provider.
+
+ Public clients do not require a client secret but private
+ clients do require a client secret to work with the identity provider.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced
+ secret
+ type: string
+ required:
+ - name
+ type: object
+ componentName:
+ description: |-
+ componentName is a required field that specifies the name of the platform
+ component being configured to use the identity provider as an authentication mode.
+ It is used in combination with componentNamespace as a unique identifier.
+
+ componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ maxLength: 256
+ minLength: 1
+ type: string
+ componentNamespace:
+ description: |-
+ componentNamespace is a required field that specifies the namespace in which the
+ platform component being configured to use the identity provider as an authentication
+ mode is running.
+ It is used in combination with componentName as a unique identifier.
+
+ componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ maxLength: 63
+ minLength: 1
+ type: string
+ extraScopes:
+ description: |-
+ extraScopes is an optional field that configures the extra scopes that should
+ be requested by the platform component when making authentication requests to the
+ identity provider.
+ This is useful if you have configured claim mappings that requires specific
+ scopes to be requested beyond the standard OIDC scopes.
+
+ When omitted, no additional scopes are requested.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ required:
+ - clientID
+ - componentName
+ - componentNamespace
+ type: object
+ maxItems: 20
+ type: array
+ x-kubernetes-list-map-keys:
+ - componentNamespace
+ - componentName
+ x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
+ maxItems: 64
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - claimMappings
+ - issuer
+ - name
+ type: object
+ maxItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ serviceAccountIssuer:
+ description: |-
+ serviceAccountIssuer is the identifier of the bound service account token
+ issuer.
+ The default is https://kubernetes.default.svc
+ WARNING: Updating this field will not result in immediate invalidation of all bound tokens with the
+ previous issuer value. Instead, the tokens issued by previous service account issuer will continue to
+ be trusted for a time period chosen by the platform (currently set to 24h).
+ This time period is subject to change over time.
+ This allows internal components to transition to use new service account issuer without service distruption.
+ type: string
+ type:
+ description: |-
+ type identifies the cluster managed, user facing authentication mode in use.
+ Specifically, it manages the component that responds to login attempts.
+ The default is IntegratedOAuth.
+ type: string
+ webhookTokenAuthenticator:
+ description: |-
+ webhookTokenAuthenticator configures a remote token reviewer.
+ These remote authentication webhooks can be used to verify bearer tokens
+ via the tokenreviews.authentication.k8s.io REST API. This is required to
+ honor bearer tokens that are provisioned by an external authentication service.
+
+ Can only be set if "Type" is set to "None".
+ properties:
+ kubeConfig:
+ description: |-
+ kubeConfig references a secret that contains kube config file data which
+ describes how to access the remote webhook service.
+ The namespace for the referenced secret is openshift-config.
+
+ For further details, see:
+
+ https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication
+
+ The key "kubeConfig" is used to locate the data.
+ If the secret or expected key is not found, the webhook is not honored.
+ If the specified kube config data is not valid, the webhook is not honored.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced secret
+ type: string
+ required:
+ - name
+ type: object
+ required:
+ - kubeConfig
+ type: object
+ webhookTokenAuthenticators:
+ description: webhookTokenAuthenticators is DEPRECATED, setting it
+ has no effect.
+ items:
+ description: |-
+ deprecatedWebhookTokenAuthenticator holds the necessary configuration options for a remote token authenticator.
+ It's the same as WebhookTokenAuthenticator but it's missing the 'required' validation on KubeConfig field.
+ properties:
+ kubeConfig:
+ description: |-
+ kubeConfig contains kube config file data which describes how to access the remote webhook service.
+ For further details, see:
+ https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication
+ The key "kubeConfig" is used to locate the data.
+ If the secret or expected key is not found, the webhook is not honored.
+ If the specified kube config data is not valid, the webhook is not honored.
+ The namespace for this secret is determined by the point of use.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced
+ secret
+ type: string
+ required:
+ - name
+ type: object
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ type: object
+ status:
+ description: status holds observed values from the cluster. They may not
+ be overridden.
+ properties:
+ integratedOAuthMetadata:
+ description: |-
+ integratedOAuthMetadata contains the discovery endpoint data for OAuth 2.0
+ Authorization Server Metadata for the in-cluster integrated OAuth server.
+ This discovery document can be viewed from its served location:
+ oc get --raw '/.well-known/oauth-authorization-server'
+ For further details, see the IETF Draft:
+ https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2
+ This contains the observed value based on cluster state.
+ An explicitly set value in spec.oauthMetadata has precedence over this field.
+ This field has no meaning if authentication spec.type is not set to IntegratedOAuth.
+ The key "oauthMetadata" is used to locate the data.
+ If the config map or expected key is not found, no metadata is served.
+ If the specified metadata is not valid, no metadata is served.
+ The namespace for this config map is openshift-config-managed.
+ properties:
+ name:
+ description: name is the metadata.name of the referenced config
+ map
+ type: string
+ required:
+ - name
+ type: object
+ type: object
+ required:
+ - spec
+ type: object
+ x-kubernetes-validations:
+ - message: all oidcClients in the oidcProviders must match their componentName
+ and componentNamespace to either a previously configured oidcClient or
+ they must exist in the status.oidcClients
+ rule: '!has(self.spec.oidcProviders) || self.spec.oidcProviders.all(p, !has(p.oidcClients)
+ || p.oidcClients.all(specC, self.status.oidcClients.exists(statusC, statusC.componentNamespace
+ == specC.componentNamespace && statusC.componentName == specC.componentName)
+ || (has(oldSelf.spec.oidcProviders) && oldSelf.spec.oidcProviders.exists(oldP,
+ oldP.name == p.name && has(oldP.oidcClients) && oldP.oidcClients.exists(oldC,
+ oldC.componentNamespace == specC.componentNamespace && oldC.componentName
+ == specC.componentName)))))'
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
index 34ed169f089..8094f4e6260 100644
--- a/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
+++ b/config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
@@ -349,18 +349,38 @@ spec:
Validation rules are joined via an AND operation.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
@@ -392,8 +412,14 @@ spec:
Defaults to 'RequiredClaim'.
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
@@ -412,7 +438,7 @@ spec:
items:
minLength: 1
type: string
- maxItems: 10
+ maxItems: 20
minItems: 1
type: array
x-kubernetes-list-type: set
@@ -561,6 +587,37 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
+ maxItems: 64
+ type: array
+ x-kubernetes-list-type: atomic
required:
- claimMappings
- issuer
diff --git a/config/v1/zz_generated.swagger_doc_generated.go b/config/v1/zz_generated.swagger_doc_generated.go
index e3494151c66..79b00d81e5c 100644
--- a/config/v1/zz_generated.swagger_doc_generated.go
+++ b/config/v1/zz_generated.swagger_doc_generated.go
@@ -495,18 +495,30 @@ func (TokenClaimOrExpressionMapping) SwaggerDoc() map[string]string {
}
var map_TokenClaimValidationRule = map[string]string{
- "type": "type is an optional field that configures the type of the validation rule.\n\nAllowed values are 'RequiredClaim' and omitted (not provided or an empty string).\n\nWhen set to 'RequiredClaim', the Kubernetes API server will be configured to validate that the incoming JWT contains the required claim and that its value matches the required value.\n\nDefaults to 'RequiredClaim'.",
- "requiredClaim": "requiredClaim is an optional field that configures the required claim and value that the Kubernetes API server will use to validate if an incoming JWT is valid for this identity provider.",
+ "type": "type is an optional field that configures the type of the validation rule.\n\nAllowed values are 'RequiredClaim' and omitted (not provided or an empty string).\n\nWhen set to 'RequiredClaim', the Kubernetes API server will be configured to validate that the incoming JWT contains the required claim and that its value matches the required value.\n\nDefaults to 'RequiredClaim'.",
+ "requiredClaim": "requiredClaim allows configuring a required claim name and its expected value. RequiredClaim is used when type is RequiredClaim.",
+ "expressionRule": "expressionRule contains the configuration for the \"Expression\" type. Must be set if type == \"Expression\".",
}
func (TokenClaimValidationRule) SwaggerDoc() map[string]string {
return map_TokenClaimValidationRule
}
+var map_TokenExpressionRule = map[string]string{
+ "expression": "expression is a CEL expression evaluated against token claims. The expression must be a non-empty string and no longer than 4096 characters. This field is required.",
+ "message": "message allows configuring the human-readable message that is returned from the Kubernetes API server when a token fails validation based on the CEL expression defined in 'expression'. This field is optional.",
+}
+
+func (TokenExpressionRule) SwaggerDoc() map[string]string {
+ return map_TokenExpressionRule
+}
+
var map_TokenIssuer = map[string]string{
"issuerURL": "issuerURL is a required field that configures the URL used to issue tokens by the identity provider. The Kubernetes API server determines how authentication tokens should be handled by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.\n\nMust be at least 1 character and must not exceed 512 characters in length. Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.",
"audiences": "audiences is a required field that configures the acceptable audiences the JWT token, issued by the identity provider, must be issued to. At least one of the entries must match the 'aud' claim in the JWT token.\n\naudiences must contain at least one entry and must not exceed ten entries.",
"issuerCertificateAuthority": "issuerCertificateAuthority is an optional field that configures the certificate authority, used by the Kubernetes API server, to validate the connection to the identity provider when fetching discovery information.\n\nWhen not specified, the system trust is used.\n\nWhen specified, it must reference a ConfigMap in the openshift-config namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt' key in the data field of the ConfigMap.",
+ "discoveryURL": "discoveryURL is an optional field that, if specified, overrides the default discovery endpoint used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url` as \"{url}/.well-known/openid-configuration\".\n\nThe discoveryURL must:\n - Be a valid absolute URL.\n - Use the HTTPS scheme.\n - Not contain query parameters, user info, or fragments.\n - Be different from the value of `url` (ignoring trailing slashes)",
+ "audienceMatchPolicy": "audienceMatchPolicy specifies how token audiences are matched. If omitted, the system applies a default policy. Valid values are: - \"MatchAny\": The token is accepted if any of its audiences match any of the configured audiences.",
}
func (TokenIssuer) SwaggerDoc() map[string]string {
@@ -514,7 +526,7 @@ func (TokenIssuer) SwaggerDoc() map[string]string {
}
var map_TokenRequiredClaim = map[string]string{
- "claim": "claim is a required field that configures the name of the required claim. When taken from the JWT claims, claim must be a string value.\n\nclaim must not be an empty string (\"\").",
+ "claim": "claim is a name of a required claim. Only claims with string values are supported.",
"requiredValue": "requiredValue is a required field that configures the value that 'claim' must have when taken from the incoming JWT claims. If the value in the JWT claims does not match, the token will be rejected for authentication.\n\nrequiredValue must not be an empty string (\"\").",
}
@@ -522,6 +534,16 @@ func (TokenRequiredClaim) SwaggerDoc() map[string]string {
return map_TokenRequiredClaim
}
+var map_TokenUserValidationRule = map[string]string{
+ "": "TokenUserValidationRule provides a CEL-based rule used to validate a token subject. Each rule contains a CEL expression that is evaluated against the token’s claims. If the expression evaluates to false, the token is rejected. See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax. At least one rule must evaluate to true for the token to be considered valid.",
+ "expression": "expression is a CEL expression that must evaluate to true for the token to be accepted. The expression is evaluated against the token's user information (e.g., username, groups). This field must be non-empty and may not exceed 4096 characters.",
+ "message": "message is an optional, human-readable message returned by the API server when this validation rule fails. It can help clarify why a token was rejected.",
+}
+
+func (TokenUserValidationRule) SwaggerDoc() map[string]string {
+ return map_TokenUserValidationRule
+}
+
var map_UsernameClaimMapping = map[string]string{
"claim": "claim is a required field that configures the JWT token claim whose value is assigned to the cluster identity field associated with this mapping.\n\nclaim must not be an empty string (\"\") and must not exceed 256 characters.",
"prefixPolicy": "prefixPolicy is an optional field that configures how a prefix should be applied to the value of the JWT claim specified in the 'claim' field.\n\nAllowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).\n\nWhen set to 'Prefix', the value specified in the prefix field will be prepended to the value of the JWT claim. The prefix field must be set when prefixPolicy is 'Prefix'.\n\nWhen set to 'NoPrefix', no prefix will be prepended to the value of the JWT claim.\n\nWhen omitted, this means no opinion and the platform is left to choose any prefixes that are applied which is subject to change over time. Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim when the claim is not 'email'. As an example, consider the following scenario:\n `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,\n the JWT claims include \"username\":\"userA\" and \"email\":\"userA@myoidc.tld\",\n and `claim` is set to:\n - \"username\": the mapped value will be \"https://myoidc.tld#userA\"\n - \"email\": the mapped value will be \"userA@myoidc.tld\"",
diff --git a/features.md b/features.md
index 05172942208..815291221a8 100644
--- a/features.md
+++ b/features.md
@@ -39,6 +39,7 @@
| DynamicResourceAllocation| | | Enabled | Enabled | Enabled | Enabled |
| EtcdBackendQuota| | | Enabled | Enabled | Enabled | Enabled |
| Example| | | Enabled | Enabled | Enabled | Enabled |
+| ExternalOIDCWithNewAuthConfigFields| | | Enabled | Enabled | Enabled | Enabled |
| ExternalOIDCWithUIDAndExtraClaimMappings| | | Enabled | Enabled | Enabled | Enabled |
| GCPClusterHostedDNS| | | Enabled | Enabled | Enabled | Enabled |
| GCPCustomAPIEndpoints| | | Enabled | Enabled | Enabled | Enabled |
diff --git a/features/features.go b/features/features.go
index 231bad62b67..e1e65eb4836 100644
--- a/features/features.go
+++ b/features/features.go
@@ -52,12 +52,12 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateMutatingAdmissionPolicy = newFeatureGate("MutatingAdmissionPolicy").
+ FeatureGateValidatingAdmissionPolicy = newFeatureGate("ValidatingAdmissionPolicy").
reportProblemsToJiraComponent("kube-apiserver").
contactPerson("benluddy").
productScope(kubernetes).
- enhancementPR("https://github.com/kubernetes/enhancements/issues/3962").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enhancementPR("https://github.com/kubernetes/enhancements/issues/3488").
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateGatewayAPI = newFeatureGate("GatewayAPI").
@@ -92,16 +92,22 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- // OpenShift and Node Team will keep this turned off until evictions and
- // disk provisioning are fixed even though upstream will take this GA.
FeatureGateNodeSwap = newFeatureGate("NodeSwap").
reportProblemsToJiraComponent("node").
- contactPerson("haircommander").
+ contactPerson("ehashman").
productScope(kubernetes).
enhancementPR("https://github.com/kubernetes/enhancements/issues/2400").
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateMachineAPIProviderOpenStack = newFeatureGate("MachineAPIProviderOpenStack").
+ reportProblemsToJiraComponent("openstack").
+ contactPerson("egarcia").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateInsightsConfigAPI = newFeatureGate("InsightsConfigAPI").
reportProblemsToJiraComponent("insights").
contactPerson("tremes").
@@ -110,6 +116,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateInsightsRuntimeExtractor = newFeatureGate("InsightsRuntimeExtractor").
+ reportProblemsToJiraComponent("insights").
+ contactPerson("jmesnil").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateDynamicResourceAllocation = newFeatureGate("DynamicResourceAllocation").
reportProblemsToJiraComponent("scheduling").
contactPerson("jchaloup").
@@ -126,14 +140,6 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateAzureDedicatedHosts = newFeatureGate("AzureDedicatedHosts").
- reportProblemsToJiraComponent("installer").
- contactPerson("rvanderp3").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1783").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
FeatureGateMaxUnavailableStatefulSet = newFeatureGate("MaxUnavailableStatefulSet").
reportProblemsToJiraComponent("apps").
contactPerson("atiratree").
@@ -149,12 +155,20 @@ var (
enhancementPR("https://github.com/kubernetes/enhancements/issues/3386").
mustRegister()
+ FeatureGatePrivateHostedZoneAWS = newFeatureGate("PrivateHostedZoneAWS").
+ reportProblemsToJiraComponent("Routing").
+ contactPerson("miciah").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateSigstoreImageVerification = newFeatureGate("SigstoreImageVerification").
reportProblemsToJiraComponent("node").
contactPerson("sgrunert").
productScope(ocpSpecific).
enhancementPR(legacyFeatureGateWithoutEnhancement).
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateSigstoreImageVerificationPKI = newFeatureGate("SigstoreImageVerificationPKI").
@@ -162,9 +176,17 @@ var (
contactPerson("QiWang").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1658").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade).
mustRegister()
+ FeatureGateGCPLabelsTags = newFeatureGate("GCPLabelsTags").
+ reportProblemsToJiraComponent("Installer").
+ contactPerson("bhb").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateAlibabaPlatform = newFeatureGate("AlibabaPlatform").
reportProblemsToJiraComponent("cloud-provider").
contactPerson("jspeed").
@@ -173,6 +195,14 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateCloudDualStackNodeIPs = newFeatureGate("CloudDualStackNodeIPs").
+ reportProblemsToJiraComponent("machine-config-operator/platform-baremetal").
+ contactPerson("mkowalsk").
+ productScope(kubernetes).
+ enhancementPR("https://github.com/kubernetes/enhancements/issues/3705").
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateVSphereHostVMGroupZonal = newFeatureGate("VSphereHostVMGroupZonal").
reportProblemsToJiraComponent("splat").
contactPerson("jcpowermac").
@@ -186,6 +216,14 @@ var (
contactPerson("vr4manta").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1709").
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
+ FeatureGateVSphereMultiVCenters = newFeatureGate("VSphereMultiVCenters").
+ reportProblemsToJiraComponent("splat").
+ contactPerson("vr4manta").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
@@ -234,7 +272,7 @@ var (
contactPerson("jcaamano").
productScope(ocpSpecific).
enhancementPR(legacyFeatureGateWithoutEnhancement).
- enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateNetworkLiveMigration = newFeatureGate("NetworkLiveMigration").
@@ -261,6 +299,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateHardwareSpeed = newFeatureGate("HardwareSpeed").
+ reportProblemsToJiraComponent("etcd").
+ contactPerson("hasbro17").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateBackendQuotaGiB = newFeatureGate("EtcdBackendQuota").
reportProblemsToJiraComponent("etcd").
contactPerson("hasbro17").
@@ -294,20 +340,12 @@ var (
FeatureGateMachineConfigNodes = newFeatureGate("MachineConfigNodes").
reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("ijanssen").
+ contactPerson("cdoern").
productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1765").
- enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateImageModeStatusReporting = newFeatureGate("ImageModeStatusReporting").
- reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("ijanssen").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1809").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
FeatureGateClusterAPIInstall = newFeatureGate("ClusterAPIInstall").
reportProblemsToJiraComponent("Installer").
contactPerson("vincepri").
@@ -331,14 +369,6 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateAzureClusterHostedDNSInstall = newFeatureGate("AzureClusterHostedDNSInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("sadasu").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1468").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
FeatureGateMixedCPUsAllocation = newFeatureGate("MixedCPUsAllocation").
reportProblemsToJiraComponent("NodeTuningOperator").
contactPerson("titzhak").
@@ -363,29 +393,21 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateManagedBootImagesvSphere = newFeatureGate("ManagedBootImagesvSphere").
- reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("rsaini").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1496").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateManagedBootImagesAzure = newFeatureGate("ManagedBootImagesAzure").
- reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("djoshy").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1761").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
+ FeatureGateDisableKubeletCloudCredentialProviders = newFeatureGate("DisableKubeletCloudCredentialProviders").
+ reportProblemsToJiraComponent("cloud-provider").
+ contactPerson("jspeed").
+ productScope(kubernetes).
+ enhancementPR("https://github.com/kubernetes/enhancements/issues/2395").
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
- FeatureGateBootImageSkewEnforcement = newFeatureGate("BootImageSkewEnforcement").
- reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("djoshy").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1761").
- enableIn(configv1.DevPreviewNoUpgrade).
- mustRegister()
+ FeatureGateOnClusterBuild = newFeatureGate("OnClusterBuild").
+ reportProblemsToJiraComponent("MachineConfigOperator").
+ contactPerson("cheesesashimi").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
FeatureGateBootcNodeManagement = newFeatureGate("BootcNodeManagement").
reportProblemsToJiraComponent("MachineConfigOperator").
@@ -413,10 +435,10 @@ var (
FeatureGatePinnedImages = newFeatureGate("PinnedImages").
reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("RishabhSaini").
+ contactPerson("jhernand").
productScope(ocpSpecific).
enhancementPR(legacyFeatureGateWithoutEnhancement).
- enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateUpgradeStatus = newFeatureGate("UpgradeStatus").
@@ -424,7 +446,7 @@ var (
contactPerson("pmuller").
productScope(ocpSpecific).
enhancementPR(legacyFeatureGateWithoutEnhancement).
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateTranslateStreamCloseWebsocketRequests = newFeatureGate("TranslateStreamCloseWebsocketRequests").
@@ -451,14 +473,6 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateExternalSnapshotMetadata = newFeatureGate("ExternalSnapshotMetadata").
- reportProblemsToJiraComponent("Storage / Kubernetes External Components").
- contactPerson("jdobson").
- productScope(kubernetes).
- enhancementPR("https://github.com/kubernetes/enhancements/issues/3314").
- enableIn(configv1.DevPreviewNoUpgrade).
- mustRegister()
-
FeatureGateExternalOIDC = newFeatureGate("ExternalOIDC").
reportProblemsToJiraComponent("authentication").
contactPerson("liouk").
@@ -477,6 +491,15 @@ var (
enableForClusterProfile(Hypershift, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateExternalOIDCWithNewAuthConfigFields = newFeatureGate("ExternalOIDCWithNewAuthConfigFields").
+ reportProblemsToJiraComponent("authentication").
+ contactPerson("saldawam").
+ productScope(ocpSpecific).
+ enhancementPR("https://github.com/openshift/enhancements/pull/1763").
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableForClusterProfile(Hypershift, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateExample = newFeatureGate("Example").
reportProblemsToJiraComponent("cluster-config").
contactPerson("deads").
@@ -493,6 +516,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade).
mustRegister()
+ FeatureGatePlatformOperators = newFeatureGate("PlatformOperators").
+ reportProblemsToJiraComponent("olm").
+ contactPerson("joe").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateNewOLM = newFeatureGate("NewOLM").
reportProblemsToJiraComponent("olm").
contactPerson("joe").
@@ -525,14 +556,6 @@ var (
enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateNewOLMWebhookProviderOpenshiftServiceCA = newFeatureGate("NewOLMWebhookProviderOpenshiftServiceCA").
- reportProblemsToJiraComponent("olm").
- contactPerson("pegoncal").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1799").
- enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
FeatureGateInsightsOnDemandDataGather = newFeatureGate("InsightsOnDemandDataGather").
reportProblemsToJiraComponent("insights").
contactPerson("tremes").
@@ -541,6 +564,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateBareMetalLoadBalancer = newFeatureGate("BareMetalLoadBalancer").
+ reportProblemsToJiraComponent("metal").
+ contactPerson("EmilienM").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateInsightsConfig = newFeatureGate("InsightsConfig").
reportProblemsToJiraComponent("insights").
contactPerson("tremes").
@@ -549,6 +580,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateNodeDisruptionPolicy = newFeatureGate("NodeDisruptionPolicy").
+ reportProblemsToJiraComponent("MachineConfigOperator").
+ contactPerson("jerzhang").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateMetricsCollectionProfiles = newFeatureGate("MetricsCollectionProfiles").
reportProblemsToJiraComponent("Monitoring").
contactPerson("rexagod").
@@ -557,6 +596,14 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateVSphereDriverConfiguration = newFeatureGate("VSphereDriverConfiguration").
+ reportProblemsToJiraComponent("Storage / Kubernetes External Components").
+ contactPerson("rbednar").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateClusterAPIInstallIBMCloud = newFeatureGate("ClusterAPIInstallIBMCloud").
reportProblemsToJiraComponent("Installer").
contactPerson("cjschaef").
@@ -565,6 +612,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateChunkSizeMiB = newFeatureGate("ChunkSizeMiB").
+ reportProblemsToJiraComponent("Image Registry").
+ contactPerson("flavianmissi").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateMachineAPIMigration = newFeatureGate("MachineAPIMigration").
reportProblemsToJiraComponent("OCPCLOUD").
contactPerson("jspeed").
@@ -573,12 +628,12 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- FeatureGateClusterAPIMachineManagementVSphere = newFeatureGate("ClusterAPIMachineManagementVSphere").
- reportProblemsToJiraComponent("SPLAT").
- contactPerson("jcpowermac").
+ FeatureGatePersistentIPsForVirtualization = newFeatureGate("PersistentIPsForVirtualization").
+ reportProblemsToJiraComponent("CNV Network").
+ contactPerson("mduarted").
productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1465").
- enableIn(configv1.DevPreviewNoUpgrade).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateClusterMonitoringConfig = newFeatureGate("ClusterMonitoringConfig").
@@ -589,6 +644,14 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateMultiArchInstallAWS = newFeatureGate("MultiArchInstallAWS").
+ reportProblemsToJiraComponent("Installer").
+ contactPerson("r4f4").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateMultiArchInstallAzure = newFeatureGate("MultiArchInstallAzure").
reportProblemsToJiraComponent("Installer").
contactPerson("r4f4").
@@ -596,6 +659,14 @@ var (
enhancementPR(legacyFeatureGateWithoutEnhancement).
mustRegister()
+ FeatureGateMultiArchInstallGCP = newFeatureGate("MultiArchInstallGCP").
+ reportProblemsToJiraComponent("Installer").
+ contactPerson("r4f4").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateIngressControllerLBSubnetsAWS = newFeatureGate("IngressControllerLBSubnetsAWS").
reportProblemsToJiraComponent("Routing").
contactPerson("miciah").
@@ -604,6 +675,14 @@ var (
enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateAWSEFSDriverVolumeMetrics = newFeatureGate("AWSEFSDriverVolumeMetrics").
+ reportProblemsToJiraComponent("Storage / Kubernetes External Components").
+ contactPerson("fbertina").
+ productScope(ocpSpecific).
+ enhancementPR(legacyFeatureGateWithoutEnhancement).
+ enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateImageStreamImportMode = newFeatureGate("ImageStreamImportMode").
reportProblemsToJiraComponent("Multi-Arch").
contactPerson("psundara").
@@ -617,18 +696,15 @@ var (
contactPerson("haircommander").
productScope(kubernetes).
enhancementPR("https://github.com/kubernetes/enhancements/issues/127").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
- // Note: this feature is perma-alpha, but it is safe and desireable to enable.
- // It was an oversight in upstream to not remove the feature gate after the version skew became safe in 1.33.
- // See https://github.com/kubernetes/enhancements/tree/d4226c42/keps/sig-node/127-user-namespaces#pod-security-standards-pss-integration
FeatureGateUserNamespacesPodSecurityStandards = newFeatureGate("UserNamespacesPodSecurityStandards").
reportProblemsToJiraComponent("Node").
contactPerson("haircommander").
productScope(kubernetes).
enhancementPR("https://github.com/kubernetes/enhancements/issues/127").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateProcMountType = newFeatureGate("ProcMountType").
@@ -636,7 +712,7 @@ var (
contactPerson("haircommander").
productScope(kubernetes).
enhancementPR("https://github.com/kubernetes/enhancements/issues/4265").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateVSphereMultiNetworks = newFeatureGate("VSphereMultiNetworks").
@@ -644,7 +720,7 @@ var (
contactPerson("rvanderp").
productScope(ocpSpecific).
enhancementPR(legacyFeatureGateWithoutEnhancement).
- enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
FeatureGateIngressControllerDynamicConfigurationManager = newFeatureGate("IngressControllerDynamicConfigurationManager").
@@ -684,15 +760,18 @@ var (
contactPerson("eggfoobar").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1674").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
- mustRegister()
+ // TODO: Do not go GA until jira issue is resolved: https://issues.redhat.com/browse/OCPEDGE-1637
+ // Annotations must correctly handle either DualReplica or HighlyAvailableArbiter going GA with
+ // the other still in TechPreview.
+ enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ mustRegister()
FeatureGateCVOConfiguration = newFeatureGate("ClusterVersionOperatorConfiguration").
reportProblemsToJiraComponent("Cluster Version Operator").
contactPerson("dhurta").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1492").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade).
mustRegister()
FeatureGateGCPCustomAPIEndpoints = newFeatureGate("GCPCustomAPIEndpoints").
@@ -711,12 +790,20 @@ var (
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
+ FeatureGateSELinuxChangePolicy = newFeatureGate("SELinuxChangePolicy").
+ reportProblemsToJiraComponent("Storage / Kubernetes").
+ contactPerson("jsafrane").
+ productScope(kubernetes).
+ enhancementPR("https://github.com/kubernetes/enhancements/issues/1710").
+ enableIn(configv1.DevPreviewNoUpgrade).
+ mustRegister()
+
FeatureGateSELinuxMount = newFeatureGate("SELinuxMount").
reportProblemsToJiraComponent("Storage / Kubernetes").
contactPerson("jsafrane").
productScope(kubernetes).
enhancementPR("https://github.com/kubernetes/enhancements/issues/1710").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
+ enableIn(configv1.DevPreviewNoUpgrade).
mustRegister()
FeatureGateDualReplica = newFeatureGate("DualReplica").
@@ -724,8 +811,11 @@ var (
contactPerson("jaypoulz").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1675").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
+ // TODO: Do not go GA until jira issue is resolved: https://issues.redhat.com/browse/OCPEDGE-1637
+ // Annotations must correctly handle either DualReplica or HighlyAvailableArbiter going GA with
+ // the other still in TechPreview.
+ enableIn(configv1.DevPreviewNoUpgrade).
+ mustRegister()
FeatureGateGatewayAPIController = newFeatureGate("GatewayAPIController").
reportProblemsToJiraComponent("Routing").
@@ -754,155 +844,4 @@ var (
enhancementPR("https://github.com/openshift/enhancements/pull/1748").
enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
mustRegister()
-
- FeatureGateAzureMultiDisk = newFeatureGate("AzureMultiDisk").
- reportProblemsToJiraComponent("splat").
- contactPerson("jcpowermac").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1779").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateStoragePerformantSecurityPolicy = newFeatureGate("StoragePerformantSecurityPolicy").
- reportProblemsToJiraComponent("Storage / Kubernetes External Components").
- contactPerson("hekumar").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1804").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
- mustRegister()
-
- FeatureGateMultiDiskSetup = newFeatureGate("MultiDiskSetup").
- reportProblemsToJiraComponent("splat").
- contactPerson("jcpowermac").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1805").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateAWSDedicatedHosts = newFeatureGate("AWSDedicatedHosts").
- reportProblemsToJiraComponent("Installer").
- contactPerson("faermanj").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1781").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateVSphereMixedNodeEnv = newFeatureGate("VSphereMixedNodeEnv").
- reportProblemsToJiraComponent("splat").
- contactPerson("vr4manta").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1772").
- enableIn(configv1.DevPreviewNoUpgrade).
- mustRegister()
-
- FeatureGatePreconfiguredUDNAddresses = newFeatureGate("PreconfiguredUDNAddresses").
- reportProblemsToJiraComponent("Networking/ovn-kubernetes").
- contactPerson("kyrtapz").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1793").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateAWSServiceLBNetworkSecurityGroup = newFeatureGate("AWSServiceLBNetworkSecurityGroup").
- reportProblemsToJiraComponent("Cloud Compute / Cloud Controller Manager").
- contactPerson("mtulio").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1802").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateImageVolume = newFeatureGate("ImageVolume").
- reportProblemsToJiraComponent("Node").
- contactPerson("haircommander").
- productScope(kubernetes).
- enhancementPR("https://github.com/openshift/enhancements/pull/1792").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default).
- mustRegister()
-
- FeatureGateNoRegistryClusterOperations = newFeatureGate("NoRegistryClusterOperations").
- reportProblemsToJiraComponent("Installer / Agent based installation").
- contactPerson("andfasano").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1821").
- enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateGCPClusterHostedDNSInstall = newFeatureGate("GCPClusterHostedDNSInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("barbacbd").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1468").
- enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateAWSClusterHostedDNSInstall = newFeatureGate("AWSClusterHostedDNSInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("barbacbd").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1468").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateGCPCustomAPIEndpointsInstall = newFeatureGate("GCPCustomAPIEndpointsInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("barbacbd").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1492").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateIrreconcilableMachineConfig = newFeatureGate("IrreconcilableMachineConfig").
- reportProblemsToJiraComponent("MachineConfigOperator").
- contactPerson("pabrodri").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1785").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
- FeatureGateAWSDualStackInstall = newFeatureGate("AWSDualStackInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("sadasu").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1806").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateAzureDualStackInstall = newFeatureGate("AzureDualStackInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("jhixson74").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1806").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureGateGCPDualStackInstall = newFeatureGate("GCPDualStackInstall").
- reportProblemsToJiraComponent("Installer").
- contactPerson("barbacbd").
- productScope(ocpSpecific).
- enhancementPR("https://github.com/openshift/enhancements/pull/1806").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureCBORServingAndStorage = newFeatureGate("CBORServingAndStorage").
- reportProblemsToJiraComponent("kube-apiserver").
- contactPerson("benluddy").
- productScope(kubernetes).
- enhancementPR("https://github.com/kubernetes/enhancements/issues/4222").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureCBORClientsAllowCBOR = newFeatureGate("ClientsAllowCBOR").
- reportProblemsToJiraComponent("kube-apiserver").
- contactPerson("benluddy").
- productScope(kubernetes).
- enhancementPR("https://github.com/kubernetes/enhancements/issues/4222").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
-
- FeatureClientsPreferCBOR = newFeatureGate("ClientsPreferCBOR").
- reportProblemsToJiraComponent("kube-apiserver").
- contactPerson("benluddy").
- productScope(kubernetes).
- enhancementPR("https://github.com/kubernetes/enhancements/issues/4222").
- enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade).
- mustRegister()
)
diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go
index 77124efe23c..88069fe5aca 100644
--- a/openapi/generated_openapi/zz_generated.openapi.go
+++ b/openapi/generated_openapi/zz_generated.openapi.go
@@ -404,8 +404,10 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/openshift/api/config/v1.TokenClaimOrExpressionMapping": schema_openshift_api_config_v1_TokenClaimOrExpressionMapping(ref),
"github.com/openshift/api/config/v1.TokenClaimValidationRule": schema_openshift_api_config_v1_TokenClaimValidationRule(ref),
"github.com/openshift/api/config/v1.TokenConfig": schema_openshift_api_config_v1_TokenConfig(ref),
+ "github.com/openshift/api/config/v1.TokenExpressionRule": schema_openshift_api_config_v1_TokenExpressionRule(ref),
"github.com/openshift/api/config/v1.TokenIssuer": schema_openshift_api_config_v1_TokenIssuer(ref),
"github.com/openshift/api/config/v1.TokenRequiredClaim": schema_openshift_api_config_v1_TokenRequiredClaim(ref),
+ "github.com/openshift/api/config/v1.TokenUserValidationRule": schema_openshift_api_config_v1_TokenUserValidationRule(ref),
"github.com/openshift/api/config/v1.Update": schema_openshift_api_config_v1_Update(ref),
"github.com/openshift/api/config/v1.UpdateHistory": schema_openshift_api_config_v1_UpdateHistory(ref),
"github.com/openshift/api/config/v1.UsernameClaimMapping": schema_openshift_api_config_v1_UsernameClaimMapping(ref),
@@ -17141,12 +17143,30 @@ func schema_openshift_api_config_v1_OIDCProvider(ref common.ReferenceCallback) c
},
},
},
+ "userValidationRules": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/openshift/api/config/v1.TokenUserValidationRule"),
+ },
+ },
+ },
+ },
+ },
},
Required: []string{"name", "issuer", "claimMappings"},
},
},
Dependencies: []string{
- "github.com/openshift/api/config/v1.OIDCClientConfig", "github.com/openshift/api/config/v1.TokenClaimMappings", "github.com/openshift/api/config/v1.TokenClaimValidationRule", "github.com/openshift/api/config/v1.TokenIssuer"},
+ "github.com/openshift/api/config/v1.OIDCClientConfig", "github.com/openshift/api/config/v1.TokenClaimMappings", "github.com/openshift/api/config/v1.TokenClaimValidationRule", "github.com/openshift/api/config/v1.TokenIssuer", "github.com/openshift/api/config/v1.TokenUserValidationRule"},
}
}
@@ -20192,21 +20212,26 @@ func schema_openshift_api_config_v1_TokenClaimValidationRule(ref common.Referenc
Default: "",
Type: []string{"string"},
Format: "",
- Enum: []interface{}{},
},
},
"requiredClaim": {
SchemaProps: spec.SchemaProps{
- Description: "requiredClaim is an optional field that configures the required claim and value that the Kubernetes API server will use to validate if an incoming JWT is valid for this identity provider.",
+ Description: "requiredClaim allows configuring a required claim name and its expected value. RequiredClaim is used when type is RequiredClaim.",
Ref: ref("github.com/openshift/api/config/v1.TokenRequiredClaim"),
},
},
+ "expressionRule": {
+ SchemaProps: spec.SchemaProps{
+ Description: "expressionRule contains the configuration for the \"Expression\" type. Must be set if type == \"Expression\".",
+ Ref: ref("github.com/openshift/api/config/v1.TokenExpressionRule"),
+ },
+ },
},
Required: []string{"type"},
},
},
Dependencies: []string{
- "github.com/openshift/api/config/v1.TokenRequiredClaim"},
+ "github.com/openshift/api/config/v1.TokenExpressionRule", "github.com/openshift/api/config/v1.TokenRequiredClaim"},
}
}
@@ -20245,6 +20270,33 @@ func schema_openshift_api_config_v1_TokenConfig(ref common.ReferenceCallback) co
}
}
+func schema_openshift_api_config_v1_TokenExpressionRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "expression": {
+ SchemaProps: spec.SchemaProps{
+ Description: "expression is a CEL expression evaluated against token claims. The expression must be a non-empty string and no longer than 4096 characters. This field is required.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "message": {
+ SchemaProps: spec.SchemaProps{
+ Description: "message allows configuring the human-readable message that is returned from the Kubernetes API server when a token fails validation based on the CEL expression defined in 'expression'. This field is optional.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"expression"},
+ },
+ },
+ }
+}
+
func schema_openshift_api_config_v1_TokenIssuer(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -20286,6 +20338,20 @@ func schema_openshift_api_config_v1_TokenIssuer(ref common.ReferenceCallback) co
Ref: ref("github.com/openshift/api/config/v1.ConfigMapNameReference"),
},
},
+ "discoveryURL": {
+ SchemaProps: spec.SchemaProps{
+ Description: "discoveryURL is an optional field that, if specified, overrides the default discovery endpoint used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url` as \"{url}/.well-known/openid-configuration\".\n\nThe discoveryURL must:\n - Be a valid absolute URL.\n - Use the HTTPS scheme.\n - Not contain query parameters, user info, or fragments.\n - Be different from the value of `url` (ignoring trailing slashes)",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "audienceMatchPolicy": {
+ SchemaProps: spec.SchemaProps{
+ Description: "audienceMatchPolicy specifies how token audiences are matched. If omitted, the system applies a default policy. Valid values are: - \"MatchAny\": The token is accepted if any of its audiences match any of the configured audiences.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
},
Required: []string{"issuerURL", "audiences"},
},
@@ -20303,7 +20369,7 @@ func schema_openshift_api_config_v1_TokenRequiredClaim(ref common.ReferenceCallb
Properties: map[string]spec.Schema{
"claim": {
SchemaProps: spec.SchemaProps{
- Description: "claim is a required field that configures the name of the required claim. When taken from the JWT claims, claim must be a string value.\n\nclaim must not be an empty string (\"\").",
+ Description: "claim is a name of a required claim. Only claims with string values are supported.",
Default: "",
Type: []string{"string"},
Format: "",
@@ -20324,6 +20390,34 @@ func schema_openshift_api_config_v1_TokenRequiredClaim(ref common.ReferenceCallb
}
}
+func schema_openshift_api_config_v1_TokenUserValidationRule(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "TokenUserValidationRule provides a CEL-based rule used to validate a token subject. Each rule contains a CEL expression that is evaluated against the token’s claims. If the expression evaluates to false, the token is rejected. See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax. At least one rule must evaluate to true for the token to be considered valid.",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "expression": {
+ SchemaProps: spec.SchemaProps{
+ Description: "expression is a CEL expression that must evaluate to true for the token to be accepted. The expression is evaluated against the token's user information (e.g., username, groups). This field must be non-empty and may not exceed 4096 characters.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "message": {
+ SchemaProps: spec.SchemaProps{
+ Description: "message is an optional, human-readable message returned by the API server when this validation rule fails. It can help clarify why a token was rejected.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"expression"},
+ },
+ },
+ }
+}
+
func schema_openshift_api_config_v1_Update(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
diff --git a/openapi/openapi.json b/openapi/openapi.json
index 169d0ceac1c..3c5241ac060 100644
--- a/openapi/openapi.json
+++ b/openapi/openapi.json
@@ -9152,6 +9152,14 @@
"componentName"
],
"x-kubernetes-list-type": "map"
+ },
+ "userValidationRules": {
+ "type": "array",
+ "items": {
+ "default": {},
+ "$ref": "#/definitions/com.github.openshift.api.config.v1.TokenUserValidationRule"
+ },
+ "x-kubernetes-list-type": "atomic"
}
}
},
@@ -10942,8 +10950,12 @@
"type"
],
"properties": {
+ "expressionRule": {
+ "description": "expressionRule contains the configuration for the \"Expression\" type. Must be set if type == \"Expression\".",
+ "$ref": "#/definitions/com.github.openshift.api.config.v1.TokenExpressionRule"
+ },
"requiredClaim": {
- "description": "requiredClaim is an optional field that configures the required claim and value that the Kubernetes API server will use to validate if an incoming JWT is valid for this identity provider.",
+ "description": "requiredClaim allows configuring a required claim name and its expected value. RequiredClaim is used when type is RequiredClaim.",
"$ref": "#/definitions/com.github.openshift.api.config.v1.TokenRequiredClaim"
},
"type": {
@@ -10973,6 +10985,22 @@
}
}
},
+ "com.github.openshift.api.config.v1.TokenExpressionRule": {
+ "type": "object",
+ "required": [
+ "expression"
+ ],
+ "properties": {
+ "expression": {
+ "description": "expression is a CEL expression evaluated against token claims. The expression must be a non-empty string and no longer than 4096 characters. This field is required.",
+ "type": "string"
+ },
+ "message": {
+ "description": "message allows configuring the human-readable message that is returned from the Kubernetes API server when a token fails validation based on the CEL expression defined in 'expression'. This field is optional.",
+ "type": "string"
+ }
+ }
+ },
"com.github.openshift.api.config.v1.TokenIssuer": {
"type": "object",
"required": [
@@ -10980,6 +11008,10 @@
"audiences"
],
"properties": {
+ "audienceMatchPolicy": {
+ "description": "audienceMatchPolicy specifies how token audiences are matched. If omitted, the system applies a default policy. Valid values are: - \"MatchAny\": The token is accepted if any of its audiences match any of the configured audiences.",
+ "type": "string"
+ },
"audiences": {
"description": "audiences is a required field that configures the acceptable audiences the JWT token, issued by the identity provider, must be issued to. At least one of the entries must match the 'aud' claim in the JWT token.\n\naudiences must contain at least one entry and must not exceed ten entries.",
"type": "array",
@@ -10989,6 +11021,10 @@
},
"x-kubernetes-list-type": "set"
},
+ "discoveryURL": {
+ "description": "discoveryURL is an optional field that, if specified, overrides the default discovery endpoint used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url` as \"{url}/.well-known/openid-configuration\".\n\nThe discoveryURL must:\n - Be a valid absolute URL.\n - Use the HTTPS scheme.\n - Not contain query parameters, user info, or fragments.\n - Be different from the value of `url` (ignoring trailing slashes)",
+ "type": "string"
+ },
"issuerCertificateAuthority": {
"description": "issuerCertificateAuthority is an optional field that configures the certificate authority, used by the Kubernetes API server, to validate the connection to the identity provider when fetching discovery information.\n\nWhen not specified, the system trust is used.\n\nWhen specified, it must reference a ConfigMap in the openshift-config namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt' key in the data field of the ConfigMap.",
"default": {},
@@ -11009,7 +11045,7 @@
],
"properties": {
"claim": {
- "description": "claim is a required field that configures the name of the required claim. When taken from the JWT claims, claim must be a string value.\n\nclaim must not be an empty string (\"\").",
+ "description": "claim is a name of a required claim. Only claims with string values are supported.",
"type": "string",
"default": ""
},
@@ -11020,6 +11056,23 @@
}
}
},
+ "com.github.openshift.api.config.v1.TokenUserValidationRule": {
+ "description": "TokenUserValidationRule provides a CEL-based rule used to validate a token subject. Each rule contains a CEL expression that is evaluated against the token’s claims. If the expression evaluates to false, the token is rejected. See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax. At least one rule must evaluate to true for the token to be considered valid.",
+ "type": "object",
+ "required": [
+ "expression"
+ ],
+ "properties": {
+ "expression": {
+ "description": "expression is a CEL expression that must evaluate to true for the token to be accepted. The expression is evaluated against the token's user information (e.g., username, groups). This field must be non-empty and may not exceed 4096 characters.",
+ "type": "string"
+ },
+ "message": {
+ "description": "message is an optional, human-readable message returned by the API server when this validation rule fails. It can help clarify why a token was rejected.",
+ "type": "string"
+ }
+ }
+ },
"com.github.openshift.api.config.v1.Update": {
"description": "Update represents an administrator update request.",
"type": "object",
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
index 4f67bf9e0ca..631a60ecd8b 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-CustomNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
index 2a3b60571cb..c52342acd39 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-Default.crd.yaml
@@ -79,34 +79,27 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -115,33 +108,18 @@ spec:
type: object
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -149,28 +127,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -185,40 +160,25 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -227,36 +187,28 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -266,15 +218,10 @@ spec:
x-kubernetes-list-type: set
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -285,77 +232,33 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -366,34 +269,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -409,8 +299,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -534,29 +451,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -630,10 +534,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -645,37 +547,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
index 195efce400b..35a93ad959c 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-DevPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
index 4e8c79c3201..8f7ca9b741c 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
index 72c798fae70..3a12add701f 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-CustomNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
index 998e804191f..e6df57e4854 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-DevPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
index 75446be6cca..f7c5674b54b 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-SelfManagedHA-TechPreviewNoUpgrade.crd.yaml
@@ -79,9 +79,8 @@ spec:
properties:
claimMappings:
description: |-
- claimMappings is a required field that configures the rules to be used by
- the Kubernetes API server for translating claims in a JWT token, issued
- by the identity provider, to a cluster identity.
+ claimMappings describes rules on how to transform information from an
+ ID token into a cluster identity
properties:
extra:
description: |-
@@ -89,7 +88,7 @@ spec:
used to construct the extra attribute for the cluster identity.
When omitted, no extra attributes will be present on the cluster identity.
key values for extra mappings must be unique.
- A maximum of 32 extra attribute mappings may be provided.
+ A maximum of 64 extra attribute mappings may be provided.
items:
description: |-
ExtraMapping allows specifying a key and CEL expression
@@ -170,44 +169,38 @@ spec:
For example, the 'sub' claim value can be accessed as 'claims.sub'.
Nested claims can be accessed using dot notation ('claims.foo.bar').
- valueExpression must not exceed 1024 characters in length.
+ valueExpression must not exceed 4096 characters in length.
valueExpression must not be empty.
- maxLength: 1024
+ maxLength: 4096
minLength: 1
type: string
required:
- key
- valueExpression
type: object
- maxItems: 32
+ maxItems: 64
type: array
x-kubernetes-list-map-keys:
- key
x-kubernetes-list-type: map
groups:
description: |-
- groups is an optional field that configures how the groups of a cluster identity
- should be constructed from the claims in a JWT token issued
- by the identity provider.
- When referencing a claim, if the claim is present in the JWT
- token, its value must be a list of groups separated by a comma (',').
- For example - '"example"' and '"exampleOne", "exampleTwo", "exampleThree"' are valid claim values.
+ groups is a name of the claim that should be used to construct
+ groups for the cluster identity.
+ The referenced claim must use array of strings values.
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
description: |-
- prefix is an optional field that configures the prefix that will be
- applied to the cluster identity attribute during the process of mapping
- JWT claims to cluster identity attributes.
+ prefix is a string to prefix the value from the token in the result of the
+ claim mapping.
- When omitted (""), no prefix is applied to the cluster identity attribute.
+ By default, no prefixing occurs.
- Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains
+ Example: if `prefix` is set to "myoidc:"" and the `claim` in JWT contains
an array of strings "a", "b" and "c", the mapping will result in an
array of string "myoidc:a", "myoidc:b" and "myoidc:c".
type: string
@@ -255,8 +248,8 @@ spec:
Precisely one of claim or expression must be set.
expression must not be specified when claim is set.
When specified, expression must be at least 1 character in length
- and must not exceed 1024 characters in length.
- maxLength: 1024
+ and must not exceed 4096 characters in length.
+ maxLength: 4096
minLength: 1
type: string
type: object
@@ -266,33 +259,18 @@ spec:
rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
username:
description: |-
- username is a required field that configures how the username of a cluster identity
- should be constructed from the claims in a JWT token issued by the identity provider.
+ username is a name of the claim that should be used to construct
+ usernames for the cluster identity.
+
+ Default value: "sub"
properties:
claim:
- description: |-
- claim is a required field that configures the JWT token
- claim whose value is assigned to the cluster identity
- field associated with this mapping.
-
- claim must not be an empty string ("") and must not exceed 256 characters.
- maxLength: 256
- minLength: 1
+ description: claim is a JWT token claim to be used in
+ the mapping
type: string
prefix:
- description: |-
- prefix configures the prefix that should be prepended to the value
- of the JWT claim.
-
- prefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.
properties:
prefixString:
- description: |-
- prefixString is a required field that configures the prefix that will
- be applied to cluster identity username attribute
- during the process of mapping JWT claims to cluster identity attributes.
-
- prefixString must not be an empty string ("").
minLength: 1
type: string
required:
@@ -300,28 +278,25 @@ spec:
type: object
prefixPolicy:
description: |-
- prefixPolicy is an optional field that configures how a prefix should be
- applied to the value of the JWT claim specified in the 'claim' field.
-
- Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).
-
- When set to 'Prefix', the value specified in the prefix field will be
- prepended to the value of the JWT claim.
- The prefix field must be set when prefixPolicy is 'Prefix'.
-
- When set to 'NoPrefix', no prefix will be prepended to the value
- of the JWT claim.
-
- When omitted, this means no opinion and the platform is left to choose
- any prefixes that are applied which is subject to change over time.
- Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim
- when the claim is not 'email'.
- As an example, consider the following scenario:
- `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
- the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
- and `claim` is set to:
- - "username": the mapped value will be "https://myoidc.tld#userA"
- - "email": the mapped value will be "userA@myoidc.tld"
+ prefixPolicy specifies how a prefix should apply.
+
+ By default, claims other than `email` will be prefixed with the issuer URL to
+ prevent naming clashes with other plugins.
+
+ Set to "NoPrefix" to disable prefixing.
+
+ Example:
+ (1) `prefix` is set to "myoidc:" and `claim` is set to "username".
+ If the JWT claim `username` contains value `userA`, the resulting
+ mapped value will be "myoidc:userA".
+ (2) `prefix` is set to "myoidc:" and `claim` is set to "email". If the
+ JWT `email` claim contains value "userA@myoidc.tld", the resulting
+ mapped value will be "myoidc:userA@myoidc.tld".
+ (3) `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,
+ the JWT claims include "username":"userA" and "email":"userA@myoidc.tld",
+ and `claim` is set to:
+ (a) "username": the mapped value will be "https://myoidc.tld#userA"
+ (b) "email": the mapped value will be "userA@myoidc.tld"
enum:
- ""
- NoPrefix
@@ -336,40 +311,49 @@ spec:
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
''Prefix'' ? (has(self.prefix) && size(self.prefix.prefixString)
> 0) : !has(self.prefix)'
- required:
- - username
type: object
claimValidationRules:
- description: |-
- claimValidationRules is an optional field that configures the rules to
- be used by the Kubernetes API server for validating the claims in a JWT
- token issued by the identity provider.
-
- Validation rules are joined via an AND operation.
+ description: claimValidationRules are rules that are applied
+ to validate token claims to authenticate users.
items:
properties:
+ expressionRule:
+ description: |-
+ expressionRule contains the configuration for the "Expression" type.
+ Must be set if type == "Expression".
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression evaluated against token claims.
+ The expression must be a non-empty string and no longer than 4096 characters.
+ This field is required.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message allows configuring the human-readable message that is returned
+ from the Kubernetes API server when a token fails validation based on
+ the CEL expression defined in 'expression'. This field is optional.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ type: object
requiredClaim:
description: |-
- requiredClaim is an optional field that configures the required claim
- and value that the Kubernetes API server will use to validate if an incoming
- JWT is valid for this identity provider.
+ requiredClaim allows configuring a required claim name and its expected value.
+ RequiredClaim is used when type is RequiredClaim.
properties:
claim:
- description: |-
- claim is a required field that configures the name of the required claim.
- When taken from the JWT claims, claim must be a string value.
-
- claim must not be an empty string ("").
+ description: claim is a name of a required claim.
+ Only claims with string values are supported.
minLength: 1
type: string
requiredValue:
- description: |-
- requiredValue is a required field that configures the value that 'claim' must
- have when taken from the incoming JWT claims.
- If the value in the JWT claims does not match, the token
- will be rejected for authentication.
-
- requiredValue must not be an empty string ("").
+ description: requiredValue is the required value for
+ the claim.
minLength: 1
type: string
required:
@@ -378,36 +362,38 @@ spec:
type: object
type:
default: RequiredClaim
- description: |-
- type is an optional field that configures the type of the validation rule.
-
- Allowed values are 'RequiredClaim' and omitted (not provided or an empty string).
-
- When set to 'RequiredClaim', the Kubernetes API server
- will be configured to validate that the incoming JWT
- contains the required claim and that its value matches
- the required value.
-
- Defaults to 'RequiredClaim'.
+ description: type sets the type of the validation rule
enum:
- RequiredClaim
+ - Expression
type: string
type: object
+ x-kubernetes-validations:
+ - message: requiredClaim must be set when type is 'RequiredClaim',
+ and forbidden otherwise
+ rule: 'has(self.type) && self.type == ''RequiredClaim''
+ ? has(self.requiredClaim) : !has(self.requiredClaim)'
type: array
x-kubernetes-list-type: atomic
issuer:
- description: |-
- issuer is a required field that configures how the platform interacts
- with the identity provider and how tokens issued from the identity provider
- are evaluated by the Kubernetes API server.
+ description: issuer describes atributes of the OIDC token issuer
properties:
+ audienceMatchPolicy:
+ description: |-
+ audienceMatchPolicy specifies how token audiences are matched.
+ If omitted, the system applies a default policy.
+ Valid values are:
+ - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences.
+ enum:
+ - MatchAny
+ - ""
+ type: string
audiences:
description: |-
- audiences is a required field that configures the acceptable audiences
- the JWT token, issued by the identity provider, must be issued to.
- At least one of the entries must match the 'aud' claim in the JWT token.
-
- audiences must contain at least one entry and must not exceed ten entries.
+ audiences is an array of audiences that the token was issued for.
+ Valid tokens must include at least one of these values in their
+ "aud" claim.
+ Must be set to exactly one value.
items:
minLength: 1
type: string
@@ -415,17 +401,37 @@ spec:
minItems: 1
type: array
x-kubernetes-list-type: set
+ discoveryURL:
+ description: |-
+ discoveryURL is an optional field that, if specified, overrides the default discovery endpoint
+ used to retrieve OIDC configuration metadata. By default, the discovery URL is derived from `url`
+ as "{url}/.well-known/openid-configuration".
+
+ The discoveryURL must:
+ - Be a valid absolute URL.
+ - Use the HTTPS scheme.
+ - Not contain query parameters, user info, or fragments.
+ - Be different from the value of `url` (ignoring trailing slashes)
+ maxLength: 2048
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: 'self.size() > 0 ? isURL(self) : true'
+ - message: discoveryURL must be a valid https URL
+ rule: 'self.size() > 0 ? (isURL(self) && url(self).getScheme()
+ == ''https'') : true'
+ - message: discoveryURL must not contain query parameters
+ rule: self.matches('^[^?]*$')
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: self.matches('^[^@]*$')
issuerCertificateAuthority:
description: |-
- issuerCertificateAuthority is an optional field that configures the
- certificate authority, used by the Kubernetes API server, to validate
- the connection to the identity provider when fetching discovery information.
-
- When not specified, the system trust is used.
-
- When specified, it must reference a ConfigMap in the openshift-config
- namespace containing the PEM-encoded CA certificates under the 'ca-bundle.crt'
- key in the data field of the ConfigMap.
+ CertificateAuthority is a reference to a config map in the
+ configuration namespace. The .data of the configMap must contain
+ the "ca-bundle.crt" key.
+ If unset, system trust is used instead.
properties:
name:
description: name is the metadata.name of the referenced
@@ -436,77 +442,38 @@ spec:
type: object
issuerURL:
description: |-
- issuerURL is a required field that configures the URL used to issue tokens
- by the identity provider.
- The Kubernetes API server determines how authentication tokens should be handled
- by matching the 'iss' claim in the JWT to the issuerURL of configured identity providers.
-
- Must be at least 1 character and must not exceed 512 characters in length.
- Must be a valid URL that uses the 'https' scheme and does not contain a query, fragment or user.
- maxLength: 512
- minLength: 1
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
+ pattern: ^https:\/\/[^\s]
type: string
- x-kubernetes-validations:
- - message: must be a valid URL
- rule: isURL(self)
- - message: must use the 'https' scheme
- rule: isURL(self) && url(self).getScheme() == 'https'
- - message: must not have a query
- rule: isURL(self) && url(self).getQuery() == {}
- - message: must not have a fragment
- rule: self.find('#(.+)$') == ''
- - message: must not have user info
- rule: self.find('@') == ''
required:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size()
+ == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]''))
+ : true'
name:
- description: |-
- name is a required field that configures the unique human-readable identifier
- associated with the identity provider.
- It is used to distinguish between multiple identity providers
- and has no impact on token validation or authentication mechanics.
-
- name must not be an empty string ("").
+ description: name of the OIDC provider
minLength: 1
type: string
oidcClients:
description: |-
- oidcClients is an optional field that configures how on-cluster,
- platform clients should request tokens from the identity provider.
- oidcClients must not exceed 20 entries and entries must have unique namespace/name pairs.
+ oidcClients contains configuration for the platform's clients that
+ need to request tokens from the issuer
items:
- description: |-
- OIDCClientConfig configures how platform clients
- interact with identity providers as an authentication
- method
properties:
clientID:
- description: |-
- clientID is a required field that configures the client identifier, from
- the identity provider, that the platform component uses for authentication
- requests made to the identity provider.
- The identity provider must accept this identifier for platform components
- to be able to use the identity provider as an authentication mode.
-
- clientID must not be an empty string ("").
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
clientSecret:
description: |-
- clientSecret is an optional field that configures the client secret used
- by the platform component when making authentication requests to the identity provider.
-
- When not specified, no client secret will be used when making authentication requests
- to the identity provider.
-
- When specified, clientSecret references a Secret in the 'openshift-config'
- namespace that contains the client secret in the 'clientSecret' key of the '.data' field.
- The client secret will be used when making authentication requests to the identity provider.
-
- Public clients do not require a client secret but private
- clients do require a client secret to work with the identity provider.
+ clientSecret refers to a secret in the `openshift-config` namespace that
+ contains the client secret in the `clientSecret` key of the `.data` field
properties:
name:
description: name is the metadata.name of the referenced
@@ -517,34 +484,21 @@ spec:
type: object
componentName:
description: |-
- componentName is a required field that specifies the name of the platform
- component being configured to use the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ componentName is the name of the component that is supposed to consume this
+ client configuration
maxLength: 256
minLength: 1
type: string
componentNamespace:
description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component being configured to use the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ componentNamespace is the namespace of the component that is supposed to consume this
+ client configuration
maxLength: 63
minLength: 1
type: string
extraScopes:
- description: |-
- extraScopes is an optional field that configures the extra scopes that should
- be requested by the platform component when making authentication requests to the
- identity provider.
- This is useful if you have configured claim mappings that requires specific
- scopes to be requested beyond the standard OIDC scopes.
-
- When omitted, no additional scopes are requested.
+ description: extraScopes is an optional set of scopes
+ to request tokens with.
items:
type: string
type: array
@@ -560,8 +514,35 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ items:
+ description: |-
+ TokenUserValidationRule provides a CEL-based rule used to validate a token subject.
+ Each rule contains a CEL expression that is evaluated against the token’s claims.
+ If the expression evaluates to false, the token is rejected.
+ See https://kubernetes.io/docs/reference/using-api/cel/ for CEL syntax.
+ At least one rule must evaluate to true for the token to be considered valid.
+ properties:
+ expression:
+ description: |-
+ Expression is a CEL expression that must evaluate
+ to true for the token to be accepted. The expression is evaluated against the token's
+ user information (e.g., username, groups). This field must be non-empty and may not
+ exceed 4096 characters.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ Message is an optional, human-readable message returned by the API server when
+ this validation rule fails. It can help clarify why a token was rejected.
+ type: string
+ required:
+ - expression
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
required:
- - claimMappings
- issuer
- name
type: object
@@ -685,29 +666,16 @@ spec:
oidcClients is where participating operators place the current OIDC client status
for OIDC clients that can be customized by the cluster-admin.
items:
- description: |-
- OIDCClientStatus represents the current state
- of platform components and how they interact with
- the configured identity providers.
properties:
componentName:
- description: |-
- componentName is a required field that specifies the name of the platform
- component using the identity provider as an authentication mode.
- It is used in combination with componentNamespace as a unique identifier.
-
- componentName must not be an empty string ("") and must not exceed 256 characters in length.
+ description: componentName is the name of the component that
+ will consume a client configuration.
maxLength: 256
minLength: 1
type: string
componentNamespace:
- description: |-
- componentNamespace is a required field that specifies the namespace in which the
- platform component using the identity provider as an authentication
- mode is running.
- It is used in combination with componentName as a unique identifier.
-
- componentNamespace must not be an empty string ("") and must not exceed 63 characters in length.
+ description: componentNamespace is the namespace of the component
+ that will consume a client configuration.
maxLength: 63
minLength: 1
type: string
@@ -781,10 +749,8 @@ spec:
x-kubernetes-list-type: map
consumingUsers:
description: |-
- consumingUsers is an optional list of ServiceAccounts requiring
- read permissions on the `clientSecret` secret.
-
- consumingUsers must not exceed 5 entries.
+ consumingUsers is a slice of ServiceAccounts that need to have read
+ permission on the `clientSecret` secret.
items:
description: ConsumingUser is an alias for string which we
add validation to. Currently only service accounts are supported.
@@ -796,37 +762,24 @@ spec:
type: array
x-kubernetes-list-type: set
currentOIDCClients:
- description: |-
- currentOIDCClients is an optional list of clients that the component is currently using.
- Entries must have unique issuerURL/clientID pairs.
+ description: currentOIDCClients is a list of clients that the
+ component is currently using.
items:
- description: |-
- OIDCClientReference is a reference to a platform component
- client configuration.
properties:
clientID:
- description: |-
- clientID is a required field that specifies the client identifier, from
- the identity provider, that the platform component is using for authentication
- requests made to the identity provider.
-
- clientID must not be empty.
+ description: clientID is the identifier of the OIDC client
+ from the OIDC provider
minLength: 1
type: string
issuerURL:
description: |-
- issuerURL is a required field that specifies the URL of the identity
- provider that this client is configured to make requests against.
-
- issuerURL must use the 'https' scheme.
+ URL is the serving URL of the token issuer.
+ Must use the https:// scheme.
pattern: ^https:\/\/[^\s]
type: string
oidcProviderName:
- description: |-
- oidcProviderName is a required reference to the 'name' of the identity provider
- configured in 'oidcProviders' that this client is associated with.
-
- oidcProviderName must not be an empty string ("").
+ description: OIDCName refers to the `name` of the provider
+ from `oidcProviders`
minLength: 1
type: string
required:
diff --git a/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml b/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml
index a807ed9434d..7cf987c8c62 100644
--- a/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml
@@ -97,6 +97,9 @@
{
"name": "Example2"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
diff --git a/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml
index 60b0c1407f9..ec1cf4c84c0 100644
--- a/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml
+++ b/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml
@@ -152,6 +152,9 @@
{
"name": "ExternalOIDC"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
diff --git a/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml
index 4b16de057ba..f0ea5ba5af4 100644
--- a/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml
+++ b/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml
@@ -158,6 +158,9 @@
{
"name": "ExternalOIDC"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml
index 2b94acf2bbe..45bdf40a017 100644
--- a/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml
@@ -100,6 +100,9 @@
{
"name": "ExternalOIDC"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml
index 37477a73dfe..f7929ebfb99 100644
--- a/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml
+++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml
@@ -134,6 +134,9 @@
{
"name": "ExternalOIDC"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml
index 4b73d1e8062..d7de931dd7c 100644
--- a/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml
+++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml
@@ -140,6 +140,9 @@
{
"name": "ExternalOIDC"
},
+ {
+ "name": "ExternalOIDCWithNewAuthConfigFields"
+ },
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},