diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Default.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Default.crd.yaml
index 5e6be8db9f1..3bdc57e0839 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Default.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-Default.crd.yaml
@@ -195,6 +195,19 @@ spec:
claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled.
maxLength: 256
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ group values from JWT claims.
+
+ CEL expressions have access to the token claims through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length .
+
+ When specified, claim must not be set or be explicitly set to the empty string (`""`).
+ maxLength: 1024
+ minLength: 1
+ 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.
@@ -206,8 +219,15 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: prefix must not be set to a non-empty value when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? (!has(self.prefix) || size(self.prefix) == 0) :
+ true'
+ - message: expression must not be set if claim is specified
+ and is not an empty string
+ rule: '(size(self.?claim.orValue("")) > 0) ? !has(self.expression)
+ : true'
uid:
description: |-
uid is an optional field for configuring the claim mapping used to construct the uid for the cluster identity.
@@ -266,6 +286,19 @@ spec:
maxLength: 256
minLength: 1
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ the username from JWT claims.
+
+ CEL expressions have access to the token claims
+ through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length.
+ expression must not be set when claim is set.
+ maxLength: 1024
+ minLength: 1
+ type: string
prefix:
description: |-
prefix configures the prefix that should be prepended to the value of the JWT claim.
@@ -309,8 +342,14 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: precisely one of claim or expression must be
+ set
+ rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
+ - message: prefixPolicy must not be set to 'Prefix' when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? !has(self.prefixPolicy) || self.prefixPolicy !=
+ ''Prefix'' : true'
- message: prefix must be set if prefixPolicy is 'Prefix',
but must remain unset otherwise
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
@@ -330,6 +369,30 @@ spec:
If type is RequiredClaim, requiredClaim must be set.
If Type is CEL, CEL must be set and RequiredClaim must be omitted.
properties:
+ cel:
+ description: |-
+ cel holds the CEL expression and message for validation.
+ Must be set when Type is "CEL", and forbidden otherwise.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ expression is required, must be at least 1 character in length and must not exceed 1024 characters.
+ The expression must return a boolean value where 'true' signals a valid token and 'false' an invalid one.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
requiredClaim:
description: |-
requiredClaim allows configuring a required claim name and its expected value.
@@ -367,11 +430,16 @@ spec:
When set to 'CEL', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.
enum:
- RequiredClaim
+ - CEL
type: string
required:
- type
type: object
x-kubernetes-validations:
+ - message: cel must be set when type is 'CEL', and forbidden
+ otherwise
+ rule: 'has(self.type) && self.type == ''CEL'' ? has(self.cel)
+ : !has(self.cel)'
- message: requiredClaim must be set when type is 'RequiredClaim',
and forbidden otherwise
rule: 'has(self.type) && self.type == ''RequiredClaim''
@@ -397,6 +465,29 @@ 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 `issuerURL` as "{issuerURL}/.well-known/openid-configuration".
+
+ The discoveryURL must be a valid absolute HTTPS URL.
+ It must not contain query parameters, user information, or fragments.
+ Additionally, it must differ from the value of `issuerURL` (ignoring trailing slashes).
+ The discoveryURL value must be at least 1 character long and no longer than 2048 characters.
+ maxLength: 2048
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: isURL(self)
+ - message: discoveryURL must be a valid https URL
+ rule: url(self).getScheme() == 'https'
+ - message: discoveryURL must not contain query parameters
+ rule: url(self).getQuery().size() == 0
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: '!self.matches(''^https://.+:.+@.+/.*$'')'
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.
@@ -437,6 +528,11 @@ spec:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.?discoveryURL.orValue("").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.
@@ -521,6 +617,45 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ description: |-
+ userValidationRules is an optional field that configures the set of rules used to validate the cluster user identity that was constructed via mapping token claims to user identity attributes.
+ Rules are CEL expressions that must evaluate to 'true' for authentication to succeed.
+ If any rule in the chain of rules evaluates to 'false', authentication will fail.
+ When specified, at least one rule must be specified and no more than 64 rules may be specified.
+ 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.
+ properties:
+ expression:
+ description: |-
+ expression is a required CEL expression that performs a validation on cluster user identity attributes like username, groups, etc.
+
+ The expression must evaluate to a boolean value.
+ When the expression evaluates to 'true', the cluster user identity is considered valid.
+ When the expression evaluates to 'false', the cluster user identity is not considered valid.
+ expression must be at least 1 character in length and must not exceed 1024 characters.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - expression
+ x-kubernetes-list-type: map
required:
- claimMappings
- issuer
diff --git a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-OKD.crd.yaml b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-OKD.crd.yaml
index dcfe61e693b..ea16c6b5c91 100644
--- a/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-OKD.crd.yaml
+++ b/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_authentications-OKD.crd.yaml
@@ -195,6 +195,19 @@ spec:
claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled.
maxLength: 256
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ group values from JWT claims.
+
+ CEL expressions have access to the token claims through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length .
+
+ When specified, claim must not be set or be explicitly set to the empty string (`""`).
+ maxLength: 1024
+ minLength: 1
+ 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.
@@ -206,8 +219,15 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: prefix must not be set to a non-empty value when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? (!has(self.prefix) || size(self.prefix) == 0) :
+ true'
+ - message: expression must not be set if claim is specified
+ and is not an empty string
+ rule: '(size(self.?claim.orValue("")) > 0) ? !has(self.expression)
+ : true'
uid:
description: |-
uid is an optional field for configuring the claim mapping used to construct the uid for the cluster identity.
@@ -266,6 +286,19 @@ spec:
maxLength: 256
minLength: 1
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ the username from JWT claims.
+
+ CEL expressions have access to the token claims
+ through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length.
+ expression must not be set when claim is set.
+ maxLength: 1024
+ minLength: 1
+ type: string
prefix:
description: |-
prefix configures the prefix that should be prepended to the value of the JWT claim.
@@ -309,8 +342,14 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: precisely one of claim or expression must be
+ set
+ rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
+ - message: prefixPolicy must not be set to 'Prefix' when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? !has(self.prefixPolicy) || self.prefixPolicy !=
+ ''Prefix'' : true'
- message: prefix must be set if prefixPolicy is 'Prefix',
but must remain unset otherwise
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
@@ -330,6 +369,30 @@ spec:
If type is RequiredClaim, requiredClaim must be set.
If Type is CEL, CEL must be set and RequiredClaim must be omitted.
properties:
+ cel:
+ description: |-
+ cel holds the CEL expression and message for validation.
+ Must be set when Type is "CEL", and forbidden otherwise.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ expression is required, must be at least 1 character in length and must not exceed 1024 characters.
+ The expression must return a boolean value where 'true' signals a valid token and 'false' an invalid one.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
requiredClaim:
description: |-
requiredClaim allows configuring a required claim name and its expected value.
@@ -367,11 +430,16 @@ spec:
When set to 'CEL', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.
enum:
- RequiredClaim
+ - CEL
type: string
required:
- type
type: object
x-kubernetes-validations:
+ - message: cel must be set when type is 'CEL', and forbidden
+ otherwise
+ rule: 'has(self.type) && self.type == ''CEL'' ? has(self.cel)
+ : !has(self.cel)'
- message: requiredClaim must be set when type is 'RequiredClaim',
and forbidden otherwise
rule: 'has(self.type) && self.type == ''RequiredClaim''
@@ -397,6 +465,29 @@ 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 `issuerURL` as "{issuerURL}/.well-known/openid-configuration".
+
+ The discoveryURL must be a valid absolute HTTPS URL.
+ It must not contain query parameters, user information, or fragments.
+ Additionally, it must differ from the value of `issuerURL` (ignoring trailing slashes).
+ The discoveryURL value must be at least 1 character long and no longer than 2048 characters.
+ maxLength: 2048
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: isURL(self)
+ - message: discoveryURL must be a valid https URL
+ rule: url(self).getScheme() == 'https'
+ - message: discoveryURL must not contain query parameters
+ rule: url(self).getQuery().size() == 0
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: '!self.matches(''^https://.+:.+@.+/.*$'')'
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.
@@ -437,6 +528,11 @@ spec:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.?discoveryURL.orValue("").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.
@@ -521,6 +617,45 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ description: |-
+ userValidationRules is an optional field that configures the set of rules used to validate the cluster user identity that was constructed via mapping token claims to user identity attributes.
+ Rules are CEL expressions that must evaluate to 'true' for authentication to succeed.
+ If any rule in the chain of rules evaluates to 'false', authentication will fail.
+ When specified, at least one rule must be specified and no more than 64 rules may be specified.
+ 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.
+ properties:
+ expression:
+ description: |-
+ expression is a required CEL expression that performs a validation on cluster user identity attributes like username, groups, etc.
+
+ The expression must evaluate to a boolean value.
+ When the expression evaluates to 'true', the cluster user identity is considered valid.
+ When the expression evaluates to 'false', the cluster user identity is not considered valid.
+ expression must be at least 1 character in length and must not exceed 1024 characters.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - expression
+ x-kubernetes-list-type: map
required:
- claimMappings
- issuer
diff --git a/features.md b/features.md
index 9f8357fec1b..6cda064ed87 100644
--- a/features.md
+++ b/features.md
@@ -60,7 +60,6 @@
| EtcdBackendQuota| | | Enabled | Enabled | | | Enabled | Enabled |
| Example| | | Enabled | Enabled | | | Enabled | Enabled |
| ExternalOIDCExternalClaimsSourcing| | | Enabled | Enabled | | | Enabled | Enabled |
-| ExternalOIDCWithUpstreamParity| | | Enabled | Enabled | | | Enabled | Enabled |
| ExternalSnapshotMetadata| | | Enabled | Enabled | | | Enabled | Enabled |
| GCPCustomAPIEndpoints| | | Enabled | Enabled | | | Enabled | Enabled |
| GCPCustomAPIEndpointsInstall| | | Enabled | Enabled | | | Enabled | Enabled |
@@ -105,6 +104,7 @@
| EventTTL| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| ExternalOIDC| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| ExternalOIDCWithUIDAndExtraClaimMappings| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
+| ExternalOIDCWithUpstreamParity| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| GatewayAPIWithoutOLM| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| ImageStreamImportMode| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
| InsightsConfig| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | Enabled |
diff --git a/features/features.go b/features/features.go
index 547be2a7b33..c0bda653636 100644
--- a/features/features.go
+++ b/features/features.go
@@ -389,7 +389,7 @@ var (
contactPerson("saldawam").
productScope(ocpSpecific).
enhancementPR("https://github.com/openshift/enhancements/pull/1763").
- enable(inDevPreviewNoUpgrade(), inTechPreviewNoUpgrade()).
+ enable(inDefault(), inOKD(), inTechPreviewNoUpgrade(), inDevPreviewNoUpgrade()).
mustRegister()
FeatureGateExternalOIDCExternalClaimsSourcing = newFeatureGate("ExternalOIDCExternalClaimsSourcing").
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-Default.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-Default.crd.yaml
index 5e6be8db9f1..3bdc57e0839 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-Default.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-Default.crd.yaml
@@ -195,6 +195,19 @@ spec:
claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled.
maxLength: 256
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ group values from JWT claims.
+
+ CEL expressions have access to the token claims through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length .
+
+ When specified, claim must not be set or be explicitly set to the empty string (`""`).
+ maxLength: 1024
+ minLength: 1
+ 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.
@@ -206,8 +219,15 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: prefix must not be set to a non-empty value when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? (!has(self.prefix) || size(self.prefix) == 0) :
+ true'
+ - message: expression must not be set if claim is specified
+ and is not an empty string
+ rule: '(size(self.?claim.orValue("")) > 0) ? !has(self.expression)
+ : true'
uid:
description: |-
uid is an optional field for configuring the claim mapping used to construct the uid for the cluster identity.
@@ -266,6 +286,19 @@ spec:
maxLength: 256
minLength: 1
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ the username from JWT claims.
+
+ CEL expressions have access to the token claims
+ through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length.
+ expression must not be set when claim is set.
+ maxLength: 1024
+ minLength: 1
+ type: string
prefix:
description: |-
prefix configures the prefix that should be prepended to the value of the JWT claim.
@@ -309,8 +342,14 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: precisely one of claim or expression must be
+ set
+ rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
+ - message: prefixPolicy must not be set to 'Prefix' when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? !has(self.prefixPolicy) || self.prefixPolicy !=
+ ''Prefix'' : true'
- message: prefix must be set if prefixPolicy is 'Prefix',
but must remain unset otherwise
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
@@ -330,6 +369,30 @@ spec:
If type is RequiredClaim, requiredClaim must be set.
If Type is CEL, CEL must be set and RequiredClaim must be omitted.
properties:
+ cel:
+ description: |-
+ cel holds the CEL expression and message for validation.
+ Must be set when Type is "CEL", and forbidden otherwise.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ expression is required, must be at least 1 character in length and must not exceed 1024 characters.
+ The expression must return a boolean value where 'true' signals a valid token and 'false' an invalid one.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
requiredClaim:
description: |-
requiredClaim allows configuring a required claim name and its expected value.
@@ -367,11 +430,16 @@ spec:
When set to 'CEL', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.
enum:
- RequiredClaim
+ - CEL
type: string
required:
- type
type: object
x-kubernetes-validations:
+ - message: cel must be set when type is 'CEL', and forbidden
+ otherwise
+ rule: 'has(self.type) && self.type == ''CEL'' ? has(self.cel)
+ : !has(self.cel)'
- message: requiredClaim must be set when type is 'RequiredClaim',
and forbidden otherwise
rule: 'has(self.type) && self.type == ''RequiredClaim''
@@ -397,6 +465,29 @@ 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 `issuerURL` as "{issuerURL}/.well-known/openid-configuration".
+
+ The discoveryURL must be a valid absolute HTTPS URL.
+ It must not contain query parameters, user information, or fragments.
+ Additionally, it must differ from the value of `issuerURL` (ignoring trailing slashes).
+ The discoveryURL value must be at least 1 character long and no longer than 2048 characters.
+ maxLength: 2048
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: isURL(self)
+ - message: discoveryURL must be a valid https URL
+ rule: url(self).getScheme() == 'https'
+ - message: discoveryURL must not contain query parameters
+ rule: url(self).getQuery().size() == 0
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: '!self.matches(''^https://.+:.+@.+/.*$'')'
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.
@@ -437,6 +528,11 @@ spec:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.?discoveryURL.orValue("").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.
@@ -521,6 +617,45 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ description: |-
+ userValidationRules is an optional field that configures the set of rules used to validate the cluster user identity that was constructed via mapping token claims to user identity attributes.
+ Rules are CEL expressions that must evaluate to 'true' for authentication to succeed.
+ If any rule in the chain of rules evaluates to 'false', authentication will fail.
+ When specified, at least one rule must be specified and no more than 64 rules may be specified.
+ 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.
+ properties:
+ expression:
+ description: |-
+ expression is a required CEL expression that performs a validation on cluster user identity attributes like username, groups, etc.
+
+ The expression must evaluate to a boolean value.
+ When the expression evaluates to 'true', the cluster user identity is considered valid.
+ When the expression evaluates to 'false', the cluster user identity is not considered valid.
+ expression must be at least 1 character in length and must not exceed 1024 characters.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - expression
+ x-kubernetes-list-type: map
required:
- claimMappings
- issuer
diff --git a/payload-manifests/crds/0000_10_config-operator_01_authentications-OKD.crd.yaml b/payload-manifests/crds/0000_10_config-operator_01_authentications-OKD.crd.yaml
index dcfe61e693b..ea16c6b5c91 100644
--- a/payload-manifests/crds/0000_10_config-operator_01_authentications-OKD.crd.yaml
+++ b/payload-manifests/crds/0000_10_config-operator_01_authentications-OKD.crd.yaml
@@ -195,6 +195,19 @@ spec:
claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled.
maxLength: 256
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ group values from JWT claims.
+
+ CEL expressions have access to the token claims through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length .
+
+ When specified, claim must not be set or be explicitly set to the empty string (`""`).
+ maxLength: 1024
+ minLength: 1
+ 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.
@@ -206,8 +219,15 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: prefix must not be set to a non-empty value when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? (!has(self.prefix) || size(self.prefix) == 0) :
+ true'
+ - message: expression must not be set if claim is specified
+ and is not an empty string
+ rule: '(size(self.?claim.orValue("")) > 0) ? !has(self.expression)
+ : true'
uid:
description: |-
uid is an optional field for configuring the claim mapping used to construct the uid for the cluster identity.
@@ -266,6 +286,19 @@ spec:
maxLength: 256
minLength: 1
type: string
+ expression:
+ description: |-
+ expression is an optional CEL expression used to derive
+ the username from JWT claims.
+
+ CEL expressions have access to the token claims
+ through a CEL variable, 'claims'.
+
+ expression must be at least 1 character and must not exceed 1024 characters in length.
+ expression must not be set when claim is set.
+ maxLength: 1024
+ minLength: 1
+ type: string
prefix:
description: |-
prefix configures the prefix that should be prepended to the value of the JWT claim.
@@ -309,8 +342,14 @@ spec:
type: string
type: object
x-kubernetes-validations:
- - message: claim is required
- rule: has(self.claim)
+ - message: precisely one of claim or expression must be
+ set
+ rule: 'has(self.claim) ? !has(self.expression) : has(self.expression)'
+ - message: prefixPolicy must not be set to 'Prefix' when
+ expression is set
+ rule: 'has(self.expression) && size(self.expression) >
+ 0 ? !has(self.prefixPolicy) || self.prefixPolicy !=
+ ''Prefix'' : true'
- message: prefix must be set if prefixPolicy is 'Prefix',
but must remain unset otherwise
rule: 'has(self.prefixPolicy) && self.prefixPolicy ==
@@ -330,6 +369,30 @@ spec:
If type is RequiredClaim, requiredClaim must be set.
If Type is CEL, CEL must be set and RequiredClaim must be omitted.
properties:
+ cel:
+ description: |-
+ cel holds the CEL expression and message for validation.
+ Must be set when Type is "CEL", and forbidden otherwise.
+ properties:
+ expression:
+ description: |-
+ expression is a CEL expression evaluated against token claims.
+ expression is required, must be at least 1 character in length and must not exceed 1024 characters.
+ The expression must return a boolean value where 'true' signals a valid token and 'false' an invalid one.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
requiredClaim:
description: |-
requiredClaim allows configuring a required claim name and its expected value.
@@ -367,11 +430,16 @@ spec:
When set to 'CEL', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.
enum:
- RequiredClaim
+ - CEL
type: string
required:
- type
type: object
x-kubernetes-validations:
+ - message: cel must be set when type is 'CEL', and forbidden
+ otherwise
+ rule: 'has(self.type) && self.type == ''CEL'' ? has(self.cel)
+ : !has(self.cel)'
- message: requiredClaim must be set when type is 'RequiredClaim',
and forbidden otherwise
rule: 'has(self.type) && self.type == ''RequiredClaim''
@@ -397,6 +465,29 @@ 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 `issuerURL` as "{issuerURL}/.well-known/openid-configuration".
+
+ The discoveryURL must be a valid absolute HTTPS URL.
+ It must not contain query parameters, user information, or fragments.
+ Additionally, it must differ from the value of `issuerURL` (ignoring trailing slashes).
+ The discoveryURL value must be at least 1 character long and no longer than 2048 characters.
+ maxLength: 2048
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: discoveryURL must be a valid URL
+ rule: isURL(self)
+ - message: discoveryURL must be a valid https URL
+ rule: url(self).getScheme() == 'https'
+ - message: discoveryURL must not contain query parameters
+ rule: url(self).getQuery().size() == 0
+ - message: discoveryURL must not contain fragments
+ rule: self.matches('^[^#]*$')
+ - message: discoveryURL must not contain user info
+ rule: '!self.matches(''^https://.+:.+@.+/.*$'')'
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.
@@ -437,6 +528,11 @@ spec:
- audiences
- issuerURL
type: object
+ x-kubernetes-validations:
+ - message: discoveryURL must be different from issuerURL
+ rule: 'self.?discoveryURL.orValue("").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.
@@ -521,6 +617,45 @@ spec:
- componentNamespace
- componentName
x-kubernetes-list-type: map
+ userValidationRules:
+ description: |-
+ userValidationRules is an optional field that configures the set of rules used to validate the cluster user identity that was constructed via mapping token claims to user identity attributes.
+ Rules are CEL expressions that must evaluate to 'true' for authentication to succeed.
+ If any rule in the chain of rules evaluates to 'false', authentication will fail.
+ When specified, at least one rule must be specified and no more than 64 rules may be specified.
+ 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.
+ properties:
+ expression:
+ description: |-
+ expression is a required CEL expression that performs a validation on cluster user identity attributes like username, groups, etc.
+
+ The expression must evaluate to a boolean value.
+ When the expression evaluates to 'true', the cluster user identity is considered valid.
+ When the expression evaluates to 'false', the cluster user identity is not considered valid.
+ expression must be at least 1 character in length and must not exceed 1024 characters.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ message:
+ description: |-
+ message is a required human-readable message to be logged by the Kubernetes API server if the CEL expression defined in 'expression' fails.
+ message must be at least 1 character in length and must not exceed 256 characters.
+ maxLength: 256
+ minLength: 1
+ type: string
+ required:
+ - expression
+ - message
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - expression
+ x-kubernetes-list-type: map
required:
- claimMappings
- issuer
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
index b4f5f9c92e9..0aa929b2a7b 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-Default.yaml
@@ -137,9 +137,6 @@
{
"name": "ExternalOIDCExternalClaimsSourcing"
},
- {
- "name": "ExternalOIDCWithUpstreamParity"
- },
{
"name": "ExternalSnapshotMetadata"
},
@@ -328,6 +325,9 @@
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
+ {
+ "name": "ExternalOIDCWithUpstreamParity"
+ },
{
"name": "GatewayAPIWithoutOLM"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
index f3c9029ab79..4fa4582eac8 100644
--- a/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-Hypershift-OKD.yaml
@@ -139,9 +139,6 @@
{
"name": "ExternalOIDCExternalClaimsSourcing"
},
- {
- "name": "ExternalOIDCWithUpstreamParity"
- },
{
"name": "ExternalSnapshotMetadata"
},
@@ -330,6 +327,9 @@
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
+ {
+ "name": "ExternalOIDCWithUpstreamParity"
+ },
{
"name": "GatewayAPIWithoutOLM"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
index a4b39b8eaf2..039059d2b1d 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
@@ -137,9 +137,6 @@
{
"name": "ExternalOIDCExternalClaimsSourcing"
},
- {
- "name": "ExternalOIDCWithUpstreamParity"
- },
{
"name": "ExternalSnapshotMetadata"
},
@@ -322,6 +319,9 @@
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
+ {
+ "name": "ExternalOIDCWithUpstreamParity"
+ },
{
"name": "GatewayAPIWithoutOLM"
},
diff --git a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
index ed62b6d0e99..585084f22ae 100644
--- a/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
+++ b/payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
@@ -139,9 +139,6 @@
{
"name": "ExternalOIDCExternalClaimsSourcing"
},
- {
- "name": "ExternalOIDCWithUpstreamParity"
- },
{
"name": "ExternalSnapshotMetadata"
},
@@ -324,6 +321,9 @@
{
"name": "ExternalOIDCWithUIDAndExtraClaimMappings"
},
+ {
+ "name": "ExternalOIDCWithUpstreamParity"
+ },
{
"name": "GatewayAPIWithoutOLM"
},