From 9da6c1fbff238b629a67d0496f6b33292f9289c5 Mon Sep 17 00:00:00 2001 From: Shaza Aldawamneh Date: Fri, 19 Sep 2025 12:23:28 +0200 Subject: [PATCH 1/5] adding auth config missing fields Signed-off-by: Shaza Aldawamneh --- .../ExternalOIDCWithNewAuthConfigFields.yaml | 364 ++++++++++ config/v1/types_authentication.go | 132 +++- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 113 ++- ...uthentications-Hypershift-Default.crd.yaml | 73 +- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 113 ++- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 113 ++- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 113 ++- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 113 ++- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 113 ++- config/v1/zz_generated.deepcopy.go | 52 ++ ..._generated.featuregated-crd-manifests.yaml | 1 + .../ExternalOIDC.yaml | 73 +- .../ExternalOIDCWithNewAuthConfigFields.yaml | 647 ++++++++++++++++++ ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 73 +- .../v1/zz_generated.swagger_doc_generated.go | 28 +- features.md | 1 + features/features.go | 9 + .../generated_openapi/zz_generated.openapi.go | 104 ++- openapi/openapi.json | 57 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 113 ++- ...uthentications-Hypershift-Default.crd.yaml | 73 +- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 113 ++- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 113 ++- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 113 ++- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 113 ++- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 113 ++- .../featureGate-Hypershift-Default.yaml | 3 + ...reGate-Hypershift-DevPreviewNoUpgrade.yaml | 3 + ...eGate-Hypershift-TechPreviewNoUpgrade.yaml | 3 + .../featureGate-SelfManagedHA-Default.yaml | 3 + ...ate-SelfManagedHA-DevPreviewNoUpgrade.yaml | 3 + ...te-SelfManagedHA-TechPreviewNoUpgrade.yaml | 3 + 32 files changed, 2909 insertions(+), 152 deletions(-) create mode 100644 config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml create mode 100644 config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml new file mode 100644 index 00000000000..4052e2f25f1 --- /dev/null +++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml @@ -0,0 +1,364 @@ + +apiVersion: apiextensions.k8s.io/v1 +name: "Authentication" +crdName: authentications.config.openshift.io +featureGates: +- ExternalOIDCWithNewAuthConfigFields +tests: + onCreate: + - name: Valid discoveryURL + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + 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: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/ + error: "discoveryURL must be different from URL" + + - name: Valid AudienceMatchPolicy + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld + audiences: ['openshift-aud'] + audienceMatchPolicy: MatchAny + + - name: Invalid AudienceMatchPolicy + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld + audiences: ['openshift-aud'] + audienceMatchPolicy: InvalidPolicy + error: "audienceMatchPolicy: Unsupported value" + + - name: Valid RequiredClaim rule + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld + 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://meh.tld + 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" + + - 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..cf67e8f9712 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,6 +91,7 @@ type AuthenticationSpec struct { // +kubebuilder:validation:MaxItems=1 // +openshift:enable:FeatureGate=ExternalOIDC // +openshift:enable:FeatureGate=ExternalOIDCWithUIDAndExtraClaimMappings + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields // +optional OIDCProviders []OIDCProvider `json:"oidcProviders,omitempty"` } @@ -243,11 +244,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. @@ -291,8 +303,46 @@ 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..59a22b65c35 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..700f65791b9 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 @@ -197,18 +197,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: @@ -240,8 +260,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: @@ -409,6 +435,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.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..15d2449fd5a 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..63a9ecc7e03 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..bc19750862e 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..2ea7e63644a 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..5c431052d16 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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.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..7de7a11342d 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: @@ -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..c2eee958e3e --- /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: 10 + 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..e086cfca367 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: @@ -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..69bb40cbbc7 100644 --- a/features/features.go +++ b/features/features.go @@ -477,6 +477,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"). 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..59a22b65c35 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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..700f65791b9 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 @@ -197,18 +197,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: @@ -240,8 +260,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: @@ -409,6 +435,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/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..15d2449fd5a 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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..63a9ecc7e03 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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..bc19750862e 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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..2ea7e63644a 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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..5c431052d16 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 @@ -348,18 +348,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: @@ -391,8 +411,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: @@ -401,6 +427,16 @@ spec: 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 @@ -415,6 +451,31 @@ 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 @@ -461,6 +522,11 @@ spec: - 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 @@ -560,6 +626,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/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" }, From 8e0ef94e47714cd8bf890c85b387f5996164cd76 Mon Sep 17 00:00:00 2001 From: Shaza Aldawamneh Date: Tue, 23 Sep 2025 13:31:02 +0200 Subject: [PATCH 2/5] adding auth config missing fields Signed-off-by: Shaza Aldawamneh --- .../ExternalOIDCWithNewAuthConfigFields.yaml | 239 ++++++++++++++++-- config/v1/types_authentication.go | 21 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 14 +- ...uthentications-Hypershift-Default.crd.yaml | 50 ---- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 14 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 14 +- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 14 +- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 14 +- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 14 +- .../ExternalOIDC.yaml | 50 ---- .../ExternalOIDCWithNewAuthConfigFields.yaml | 14 +- ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 50 ---- .../v1/zz_generated.swagger_doc_generated.go | 4 +- .../generated_openapi/zz_generated.openapi.go | 4 +- openapi/openapi.json | 4 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 14 +- ...uthentications-Hypershift-Default.crd.yaml | 50 ---- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 14 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 14 +- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 14 +- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 14 +- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 14 +- 22 files changed, 342 insertions(+), 312 deletions(-) diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml index 4052e2f25f1..29347572f1a 100644 --- a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml +++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml @@ -12,12 +12,35 @@ tests: kind: Authentication spec: type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: https://auth.example.com/.well-known/openid-configuration + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/.well-known/openid-configuration + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expected: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/.well-known/openid-configuration + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" - name: discoveryURL must be a valid URL initial: | @@ -25,13 +48,19 @@ tests: kind: Authentication spec: type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: not-a-valid-url - error: "discoveryURL must be a valid URL" + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: not-a-valid-url + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"not-a-valid-url\": discoveryURL must not contain user info" - name: discoveryURL must not contain user info initial: | @@ -45,7 +74,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: https://user:pass@auth.example.com/ - error: "discoveryURL must not contain user info" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"https://user:pass@auth.example.com/\": discoveryURL must not contain user info" - name: discoveryURL exceeds max length initial: | @@ -59,7 +94,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: "https://auth.example.com/$(printf 'a%.0s' {1..2050})" - error: "discoveryURL: Too long" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value§: discoveryURL: Too long" - name: discoveryURL must not contain fragment initial: | @@ -73,7 +114,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: https://auth.example.com/#fragment - error: "discoveryURL must not contain a fragment" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must not contain a fragment" - name: discoveryURL must use https initial: | @@ -87,7 +134,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: http://auth.example.com/invalid - error: "discoveryURL must use https scheme" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must use https scheme" - name: discoveryURL must not contain query initial: | @@ -101,7 +154,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: https://auth.example.com/path?foo=bar - error: "discoveryURL must not contain query parameters" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must not contain query parameters" - name: discoveryURL must be different from URL initial: | @@ -115,7 +174,13 @@ tests: issuerURL: https://meh.tld/ audiences: ['openshift-aud'] discoveryURL: https://auth.example.com/ - error: "discoveryURL must be different from URL" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value:discoveryURL must be different from URL" - name: Valid AudienceMatchPolicy initial: | @@ -129,6 +194,29 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] audienceMatchPolicy: MatchAny + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expected: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld + audiences: ['openshift-aud'] + audienceMatchPolicy: MatchAny + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" - name: Invalid AudienceMatchPolicy initial: | @@ -142,7 +230,13 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] audienceMatchPolicy: InvalidPolicy - error: "audienceMatchPolicy: Unsupported value" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "audienceMatchPolicy: Unsupported value" - name: Valid RequiredClaim rule initial: | @@ -160,6 +254,33 @@ tests: requiredClaim: claim: "role" requiredValue: "admin" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expected: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld + audiences: ['openshift-aud'] + claimValidationRules: + - type: RequiredClaim + requiredClaim: + claim: "role" + requiredValue: "admin" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" - name: Missing requiredClaim when type is RequiredClaim initial: | @@ -174,6 +295,12 @@ tests: audiences: ['openshift-aud'] claimValidationRules: - type: RequiredClaim + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" expectedError: "requiredClaim must be set when type is 'RequiredClaim'" - name: Valid ExpressionRule configuration @@ -187,6 +314,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" claimValidationRules: - type: Expression expressionRule: @@ -207,6 +340,12 @@ tests: expressionRule: expression: "claims.email.endsWith('@example.com')" message: "email must be from example.com" + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" - name: Missing expressionRule for Expression type initial: | @@ -219,6 +358,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" claimValidationRules: - type: Expression expectedError: "expressionRule must be set when type is 'Expression', and forbidden otherwise" @@ -234,6 +379,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" claimValidationRules: - type: Expression expressionRule: @@ -253,6 +404,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" claimValidationRules: - type: Expression expressionRule: @@ -271,6 +428,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.username.startsWith('admin')" message: "Only admin users are allowed" @@ -284,6 +447,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.username.startsWith('admin')" message: "Only admin users are allowed" @@ -299,6 +468,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - message: "Should never reach here" expectedError: "expression: Required value" @@ -314,6 +489,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "{{longExpression}}" message: "This expression is too long" @@ -332,6 +513,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "" message: "Empty expressions are invalid" @@ -348,6 +535,12 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.groups.exists(g, g == 'admins')" expected: | @@ -360,5 +553,11 @@ tests: issuer: issuerURL: https://meh.tld audiences: ['openshift-aud'] + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.groups.exists(g, g == 'admins')" diff --git a/config/v1/types_authentication.go b/config/v1/types_authentication.go index cf67e8f9712..99431b7c4a8 100644 --- a/config/v1/types_authentication.go +++ b/config/v1/types_authentication.go @@ -253,13 +253,14 @@ type OIDCProvider struct { // +listType=atomic // +kubebuilder:validation:MaxItems=64 // +optional + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields 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" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithNewAuthConfigFields,rule="self.?discoveryURL.orValue(\"\").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. @@ -830,7 +831,6 @@ type TokenRequiredClaim struct { 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. @@ -839,6 +839,7 @@ type TokenExpressionRule struct { // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 // +required + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields Expression string `json:"expression,omitempty"` // message allows configuring the human-readable message that is returned @@ -848,24 +849,27 @@ type TokenExpressionRule struct { // +optional // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=256 + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields 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. + // user information (e.g., username, groups). + // + // 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. + // + // This field must be non-empty and may not exceed 4096 characters. // // +required // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields 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. @@ -873,5 +877,6 @@ type TokenUserValidationRule struct { // +optional // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=256 + // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields 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 59a22b65c35..4ff6522353c 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 700f65791b9..11e930117e1 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 @@ -201,25 +201,6 @@ spec: 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: |- @@ -435,37 +416,6 @@ 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.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 15d2449fd5a..f68aee697c9 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 63a9ecc7e03..128f31c48c5 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 bc19750862e..cff15143a77 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 2ea7e63644a..9f755048da8 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 5c431052d16..cfd8a85b458 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 7de7a11342d..f099efebd41 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 @@ -202,25 +202,6 @@ spec: 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: |- @@ -436,37 +417,6 @@ 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 index c2eee958e3e..2ad64941ce0 100644 --- 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 @@ -378,7 +378,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -485,16 +485,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 e086cfca367..89f49a7a4a2 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 @@ -353,25 +353,6 @@ spec: 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: |- @@ -587,37 +568,6 @@ 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 79b00d81e5c..513efa21721 100644 --- a/config/v1/zz_generated.swagger_doc_generated.go +++ b/config/v1/zz_generated.swagger_doc_generated.go @@ -535,8 +535,8 @@ func (TokenRequiredClaim) SwaggerDoc() map[string]string { } 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.", + "": "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.", + "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).\n\nIf 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.\n\nThis 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.", } diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 88069fe5aca..0b2a691d280 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -20394,12 +20394,12 @@ func schema_openshift_api_config_v1_TokenUserValidationRule(ref common.Reference 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.", + 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.", 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.", + 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).\n\nIf 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.\n\nThis field must be non-empty and may not exceed 4096 characters.", Type: []string{"string"}, Format: "", }, diff --git a/openapi/openapi.json b/openapi/openapi.json index 3c5241ac060..4aa702f65b0 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -11057,14 +11057,14 @@ } }, "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.", + "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.", "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.", + "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).\n\nIf 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.\n\nThis field must be non-empty and may not exceed 4096 characters.", "type": "string" }, "message": { 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 59a22b65c35..4ff6522353c 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 700f65791b9..11e930117e1 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 @@ -201,25 +201,6 @@ spec: 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: |- @@ -435,37 +416,6 @@ 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/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 15d2449fd5a..f68aee697c9 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 63a9ecc7e03..128f31c48c5 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 bc19750862e..cff15143a77 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 2ea7e63644a..9f755048da8 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string 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 5c431052d16..cfd8a85b458 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 @@ -524,7 +524,7 @@ spec: type: object x-kubernetes-validations: - message: discoveryURL must be different from issuerURL - rule: 'self.discoveryURL.size() > 0 ? (self.issuerURL.size() + rule: 'self.?discoveryURL.orValue("").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find(''^.+[^/]'') != self.issuerURL.find(''^.+[^/]'')) : true' name: @@ -631,16 +631,18 @@ spec: 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. + user information (e.g., username, groups). + + 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. + + This field must be non-empty and may not exceed 4096 characters. maxLength: 4096 minLength: 1 type: string From 1fa3639ba229d2c51fb72dde473a8522933666d3 Mon Sep 17 00:00:00 2001 From: Shaza Aldawamneh Date: Fri, 26 Sep 2025 15:10:36 +0200 Subject: [PATCH 3/5] fixing tests Signed-off-by: Shaza Aldawamneh --- .../ExternalOIDCWithNewAuthConfigFields.yaml | 300 ++++++++++-------- config/v1/types_authentication.go | 22 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 37 ++- ...uthentications-Hypershift-Default.crd.yaml | 32 +- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 37 ++- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 37 ++- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 37 ++- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 37 ++- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 37 ++- .../ExternalOIDC.yaml | 32 +- .../ExternalOIDCWithNewAuthConfigFields.yaml | 41 ++- ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 32 +- .../v1/zz_generated.swagger_doc_generated.go | 4 +- .../generated_openapi/zz_generated.openapi.go | 8 +- openapi/openapi.json | 4 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 37 ++- ...uthentications-Hypershift-Default.crd.yaml | 32 +- ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 37 ++- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 37 ++- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 37 ++- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 37 ++- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 37 ++- 22 files changed, 650 insertions(+), 301 deletions(-) diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml index 29347572f1a..d35996d088b 100644 --- a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml +++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml @@ -42,146 +42,174 @@ tests: prefix: prefixString: "myoidc:" - - name: discoveryURL must be a valid URL - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: not-a-valid-url - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"not-a-valid-url\": discoveryURL must not contain user info" - - - name: discoveryURL must not contain user info - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: https://user:pass@auth.example.com/ - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"https://user:pass@auth.example.com/\": discoveryURL must not contain user info" - - - name: discoveryURL exceeds max length - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: "https://auth.example.com/$(printf 'a%.0s' {1..2050})" - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value§: discoveryURL: Too long" - - - name: discoveryURL must not contain fragment - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: https://auth.example.com/#fragment - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must not contain a fragment" + # - name: discoveryURL must be a valid URL + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: not-a-valid-url + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid URL, spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" - - name: discoveryURL must use https - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: http://auth.example.com/invalid - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must use https scheme" + # - name: discoveryURL must not contain user info + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: https://user:pass@auth.example.com/ + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain user info" + + # - name: discoveryURL at max length (2048 chars, should pass) + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa + # claimMappings: + # username: + # claim: "preferred_username" + # expected: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa + # claimMappings: + # username: + # claim: "preferred_username" - - name: discoveryURL must not contain query - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: https://auth.example.com/path?foo=bar - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: discoveryURL must not contain query parameters" + # - name: discoveryURL exceeds max length by one (2049 chars, should fail) + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: | + # https://auth.example.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + # claimMappings: + # username: + # claim: "preferred_username" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Too long" + + # - name: discoveryURL must not contain fragment + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: https://auth.example.com/#fragment + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain fragments" - - name: discoveryURL must be different from URL - initial: | - apiVersion: config.openshift.io/v1 - kind: Authentication - spec: - type: OIDC - oidcProviders: - - name: myoidc - issuer: - issuerURL: https://meh.tld/ - audiences: ['openshift-aud'] - discoveryURL: https://auth.example.com/ - claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" - expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value:discoveryURL must be different from URL" + # - name: discoveryURL must use https + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: http://auth.example.com/invalid + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" + # - name: discoveryURL must not contain query + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://meh.tld/ + # audiences: ['openshift-aud'] + # discoveryURL: https://auth.example.com/path?foo=bar + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain query parameters" + + # - name: discoveryURL must be different from URL + # initial: | + # apiVersion: config.openshift.io/v1 + # kind: Authentication + # spec: + # type: OIDC + # oidcProviders: + # - name: myoidc + # issuer: + # issuerURL: https://auth.example.com/.well-known/openid-configuration + # audiences: ['openshift-aud'] + # discoveryURL: https://auth.example.com/.well-known/openid-configuration + # claimMappings: + # username: + # claim: "preferred_username" + # prefixPolicy: Prefix + # prefix: + # prefixString: "myoidc:" + # expectedError: "spec.oidcProviders[0].issuer: Invalid value: \"object\": discoveryURL must be different from issuerURL" + - name: Valid AudienceMatchPolicy initial: | apiVersion: config.openshift.io/v1 diff --git a/config/v1/types_authentication.go b/config/v1/types_authentication.go index 99431b7c4a8..a2f4e7c25b6 100644 --- a/config/v1/types_authentication.go +++ b/config/v1/types_authentication.go @@ -249,7 +249,6 @@ type OIDCProvider struct { // 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 @@ -785,19 +784,28 @@ const ( // +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" +// 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. // - // Allowed values are 'RequiredClaim' and omitted (not provided or an empty string). + // Allowed values are "RequiredClaim" and "Expression". + // + // 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. // - // 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. + // When set to 'Expression', the Kubernetes API server will be configured + // to validate the incoming JWT against the configured CEL expression. // - // Defaults to 'RequiredClaim'. + // Defaults to "RequiredClaim". // // +kubebuilder:default="RequiredClaim" + // +kubebuilder:validation:Enum=RequiredClaim;Expression Type TokenValidationRuleType `json:"type"` // requiredClaim allows configuring a required claim name and its expected value. 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 4ff6522353c..37cff2d9136 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 11e930117e1..7af18df63b4 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 @@ -196,6 +196,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -227,21 +231,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -249,6 +259,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: 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 f68aee697c9..c629a6adbea 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 128f31c48c5..1481935a588 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 cff15143a77..6f642139030 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 9f755048da8..05e1b5e7d53 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 cfd8a85b458..3a8bc8ad0bd 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 f099efebd41..028875200e7 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 @@ -197,6 +197,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -228,21 +232,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -250,6 +260,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic 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 index 2ad64941ce0..5cf72460b67 100644 --- 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 @@ -197,6 +197,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -247,24 +251,34 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". + + 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. - 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. + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. - Defaults to 'RequiredClaim'. - enum: - - RequiredClaim - - Expression + Defaults to "RequiredClaim". 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: expressionRule must be set when type is 'Expression', and forbidden otherwise rule: 'has(self.type) && self.type == ''Expression'' ? has(self.expressionRule) @@ -273,6 +287,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -481,6 +499,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 89f49a7a4a2..e7f277e18ee 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 @@ -348,6 +348,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -379,21 +383,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -401,6 +411,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: diff --git a/config/v1/zz_generated.swagger_doc_generated.go b/config/v1/zz_generated.swagger_doc_generated.go index 513efa21721..2066dabc911 100644 --- a/config/v1/zz_generated.swagger_doc_generated.go +++ b/config/v1/zz_generated.swagger_doc_generated.go @@ -449,6 +449,7 @@ var map_OIDCProvider = map[string]string{ "oidcClients": "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.", "claimMappings": "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.", "claimValidationRules": "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.\n\nValidation rules are joined via an AND operation.", + "userValidationRules": "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.", } func (OIDCProvider) SwaggerDoc() map[string]string { @@ -495,7 +496,8 @@ 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'.", + "": "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.", + "type": "type is an optional field that configures the type of the validation rule.\n\nAllowed values are \"RequiredClaim\" and \"Expression\".\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\nWhen set to 'Expression', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.\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\".", } diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 0b2a691d280..89bb27e3757 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -17150,7 +17150,8 @@ func schema_openshift_api_config_v1_OIDCProvider(ref common.ReferenceCallback) c }, }, SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "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.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -20204,11 +20205,12 @@ func schema_openshift_api_config_v1_TokenClaimValidationRule(ref common.Referenc return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "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.", + Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { SchemaProps: spec.SchemaProps{ - Description: "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'.", + Description: "type is an optional field that configures the type of the validation rule.\n\nAllowed values are \"RequiredClaim\" and \"Expression\".\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\nWhen set to 'Expression', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.\n\nDefaults to \"RequiredClaim\".", Default: "", Type: []string{"string"}, Format: "", diff --git a/openapi/openapi.json b/openapi/openapi.json index 4aa702f65b0..0305ed562bb 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -9154,6 +9154,7 @@ "x-kubernetes-list-type": "map" }, "userValidationRules": { + "description": "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.", "type": "array", "items": { "default": {}, @@ -10945,6 +10946,7 @@ } }, "com.github.openshift.api.config.v1.TokenClaimValidationRule": { + "description": "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.", "type": "object", "required": [ "type" @@ -10959,7 +10961,7 @@ "$ref": "#/definitions/com.github.openshift.api.config.v1.TokenRequiredClaim" }, "type": { - "description": "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'.", + "description": "type is an optional field that configures the type of the validation rule.\n\nAllowed values are \"RequiredClaim\" and \"Expression\".\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\nWhen set to 'Expression', the Kubernetes API server will be configured to validate the incoming JWT against the configured CEL expression.\n\nDefaults to \"RequiredClaim\".", "type": "string", "default": "" } 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 4ff6522353c..37cff2d9136 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 11e930117e1..7af18df63b4 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 @@ -196,6 +196,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -227,21 +231,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -249,6 +259,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: 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 f68aee697c9..c629a6adbea 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 128f31c48c5..1481935a588 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 cff15143a77..6f642139030 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 9f755048da8..05e1b5e7d53 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. 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 cfd8a85b458..3a8bc8ad0bd 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 @@ -347,6 +347,10 @@ spec: Validation rules are joined via an AND operation. items: + description: |- + 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. properties: expressionRule: description: |- @@ -397,21 +401,27 @@ spec: - requiredValue type: object type: + allOf: + - enum: + - RequiredClaim + - Expression + - enum: + - RequiredClaim + - Expression 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). + Allowed values are "RequiredClaim" and "Expression". - 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. + 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 + When set to 'Expression', the Kubernetes API server will be configured + to validate the incoming JWT against the configured CEL expression. + + Defaults to "RequiredClaim". type: string type: object x-kubernetes-validations: @@ -419,6 +429,10 @@ spec: and forbidden otherwise 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 + rule: 'has(self.type) && self.type == ''RequiredClaim'' + ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: @@ -627,6 +641,11 @@ spec: - componentName x-kubernetes-list-type: map userValidationRules: + description: |- + 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. items: description: |- TokenUserValidationRule provides a CEL-based rule used to validate a token subject. From e12527d25bb02f3b4b9c80cfe347dde3e358bf56 Mon Sep 17 00:00:00 2001 From: Shaza Aldawamneh Date: Mon, 29 Sep 2025 11:16:00 +0200 Subject: [PATCH 4/5] fixing tests Signed-off-by: Shaza Aldawamneh --- .../ExternalOIDCWithNewAuthConfigFields.yaml | 320 +++++++++--------- 1 file changed, 160 insertions(+), 160 deletions(-) diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml index d35996d088b..e15ff8d44db 100644 --- a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml +++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml @@ -42,173 +42,173 @@ tests: prefix: prefixString: "myoidc:" - # - name: discoveryURL must be a valid URL - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: not-a-valid-url - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid URL, spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" + - name: discoveryURL must be a valid URL + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: not-a-valid-url + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid URL, spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" - # - name: discoveryURL must not contain user info - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: https://user:pass@auth.example.com/ - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain user info" + - name: discoveryURL must not contain user info + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://user:pass@auth.example.com/ + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain user info" - # - name: discoveryURL at max length (2048 chars, should pass) - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa - # claimMappings: - # username: - # claim: "preferred_username" - # expected: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa - # claimMappings: - # username: - # claim: "preferred_username" + - name: discoveryURL at max length (2048 chars, should pass) + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa + claimMappings: + username: + claim: "preferred_username" + expected: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/aaaaaaaaaaaaaaa + claimMappings: + username: + claim: "preferred_username" - # - name: discoveryURL exceeds max length by one (2049 chars, should fail) - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: | - # https://auth.example.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - # claimMappings: - # username: - # claim: "preferred_username" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Too long" + - name: discoveryURL exceeds max length by one (2049 chars, should fail) + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: | + https://auth.example.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + claimMappings: + username: + claim: "preferred_username" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Too long" - # - name: discoveryURL must not contain fragment - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: https://auth.example.com/#fragment - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain fragments" + - name: discoveryURL must not contain fragment + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/#fragment + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain fragments" - # - name: discoveryURL must use https - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: http://auth.example.com/invalid - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" + - name: discoveryURL must use https + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: http://auth.example.com/invalid + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must be a valid https URL" - # - name: discoveryURL must not contain query - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://meh.tld/ - # audiences: ['openshift-aud'] - # discoveryURL: https://auth.example.com/path?foo=bar - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain query parameters" + - name: discoveryURL must not contain query + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://meh.tld/ + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/path?foo=bar + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer.discoveryURL: Invalid value: \"string\": discoveryURL must not contain query parameters" - # - name: discoveryURL must be different from URL - # initial: | - # apiVersion: config.openshift.io/v1 - # kind: Authentication - # spec: - # type: OIDC - # oidcProviders: - # - name: myoidc - # issuer: - # issuerURL: https://auth.example.com/.well-known/openid-configuration - # audiences: ['openshift-aud'] - # discoveryURL: https://auth.example.com/.well-known/openid-configuration - # claimMappings: - # username: - # claim: "preferred_username" - # prefixPolicy: Prefix - # prefix: - # prefixString: "myoidc:" - # expectedError: "spec.oidcProviders[0].issuer: Invalid value: \"object\": discoveryURL must be different from issuerURL" + - name: discoveryURL must be different from URL + initial: | + apiVersion: config.openshift.io/v1 + kind: Authentication + spec: + type: OIDC + oidcProviders: + - name: myoidc + issuer: + issuerURL: https://auth.example.com/.well-known/openid-configuration + audiences: ['openshift-aud'] + discoveryURL: https://auth.example.com/.well-known/openid-configuration + claimMappings: + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" + expectedError: "spec.oidcProviders[0].issuer: Invalid value: \"object\": discoveryURL must be different from issuerURL" - name: Valid AudienceMatchPolicy initial: | From 582db23071222598cbd19bda6daa055aed49d285 Mon Sep 17 00:00:00 2001 From: Shaza Aldawamneh Date: Wed, 1 Oct 2025 15:29:58 +0200 Subject: [PATCH 5/5] fixing tests Signed-off-by: Shaza Aldawamneh --- ...ml => ExternalOIDCWithUpstreamParity.yaml} | 94 +++++++++---------- config/v1/types_authentication.go | 29 +++--- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 6 +- ...uthentications-Hypershift-Default.crd.yaml | 4 - ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 6 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 6 +- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 6 +- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 6 +- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 6 +- ..._generated.featuregated-crd-manifests.yaml | 2 +- .../ExternalOIDC.yaml | 4 - ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 4 - ...ml => ExternalOIDCWithUpstreamParity.yaml} | 10 +- features.md | 2 +- features/features.go | 2 +- ...ations-Hypershift-CustomNoUpgrade.crd.yaml | 6 +- ...uthentications-Hypershift-Default.crd.yaml | 4 - ...ns-Hypershift-DevPreviewNoUpgrade.crd.yaml | 6 +- ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 6 +- ...ons-SelfManagedHA-CustomNoUpgrade.crd.yaml | 6 +- ...SelfManagedHA-DevPreviewNoUpgrade.crd.yaml | 6 +- ...elfManagedHA-TechPreviewNoUpgrade.crd.yaml | 6 +- .../featureGate-Hypershift-Default.yaml | 4 +- ...reGate-Hypershift-DevPreviewNoUpgrade.yaml | 4 +- ...eGate-Hypershift-TechPreviewNoUpgrade.yaml | 4 +- .../featureGate-SelfManagedHA-Default.yaml | 4 +- ...ate-SelfManagedHA-DevPreviewNoUpgrade.yaml | 4 +- ...te-SelfManagedHA-TechPreviewNoUpgrade.yaml | 4 +- 28 files changed, 109 insertions(+), 142 deletions(-) rename config/v1/tests/authentications.config.openshift.io/{ExternalOIDCWithNewAuthConfigFields.yaml => ExternalOIDCWithUpstreamParity.yaml} (75%) rename config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/{ExternalOIDCWithNewAuthConfigFields.yaml => ExternalOIDCWithUpstreamParity.yaml} (98%) diff --git a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithUpstreamParity.yaml similarity index 75% rename from config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml rename to config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithUpstreamParity.yaml index e15ff8d44db..b04943822c0 100644 --- a/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml +++ b/config/v1/tests/authentications.config.openshift.io/ExternalOIDCWithUpstreamParity.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 name: "Authentication" crdName: authentications.config.openshift.io featureGates: -- ExternalOIDCWithNewAuthConfigFields +- ExternalOIDCWithUpstreamParity tests: onCreate: - name: Valid discoveryURL @@ -416,11 +416,10 @@ tests: claimValidationRules: - type: Expression expressionRule: - expression: "{{longExpression}}" - replacements: - longExpression: "{{'x' * 5000}}" - expectedError: "expression: Too long: must have at most 4096 characters" + expression: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + expectedError: "spec.oidcProviders[0].claimValidationRules[0].expressionRule.expression: Too long" + - name: Empty expression in expressionRule initial: | apiVersion: config.openshift.io/v1 @@ -441,10 +440,10 @@ tests: claimValidationRules: - type: Expression expressionRule: - expression: "" + sexpression: "" message: "must not be empty" - expectedError: "expression: Invalid value: \"\": validation failed: value length must be at least 1" - + expectedError: "spec.oidcProviders[0].claimValidationRules[0].expressionRule.expression: Required value" + - name: Valid TokenUserValidationRule with expression and message initial: | apiVersion: config.openshift.io/v1 @@ -457,11 +456,11 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.username.startsWith('admin')" message: "Only admin users are allowed" @@ -476,11 +475,11 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.username.startsWith('admin')" message: "Only admin users are allowed" @@ -497,11 +496,11 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - message: "Should never reach here" expectedError: "expression: Required value" @@ -518,17 +517,15 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - - expression: "{{longExpression}}" + - expression: "aaaaaaaaaabhdgbshfghdfklgfdlhsfghfdsgdfusurghughurhghrgushgelurhglurhgukshjfdhjghfdughdfuhgushrgjhrgjhulhruhgurhgusrhughrughrsuhrughsughuhlgiusrhruighluirshguhrguhrluighlugihlrughruhgurhgurlhgrujhgurhsurhlughuisrhurhgurhegushguhseughreughruhguhreughrseuhlrushlghlruhglhur" message: "This expression is too long" - replacements: - longExpression: "{{'x' * 5000}}" - expectedError: "expression: Too long: must have at most 4096 characters" + expectedError: "expression: Too long" - name: Empty expression in TokenUserValidationRule initial: | @@ -542,15 +539,16 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "" message: "Empty expressions are invalid" - expectedError: "expression: Invalid value: \"\": validation failed: value length must be at least 1" + expectedError: "spec.oidcProviders[0].userValidationRules[0].expression: Invalid value: \"\": spec.oidcProviders[0].userValidationRules[0].expression in body should be at least 1 chars long" + - name: Valid TokenUserValidationRule with expression only initial: | @@ -564,11 +562,11 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.groups.exists(g, g == 'admins')" expected: | @@ -582,10 +580,10 @@ tests: issuerURL: https://meh.tld audiences: ['openshift-aud'] claimMappings: - username: - claim: "preferred_username" - prefixPolicy: Prefix - prefix: - prefixString: "myoidc:" + username: + claim: "preferred_username" + prefixPolicy: Prefix + prefix: + prefixString: "myoidc:" userValidationRules: - expression: "user.groups.exists(g, g == 'admins')" diff --git a/config/v1/types_authentication.go b/config/v1/types_authentication.go index a2f4e7c25b6..b4e54314dfe 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;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" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDC;ExternalOIDCWithUIDAndExtraClaimMappings;ExternalOIDCWithUpstreamParity,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 - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity // +optional OIDCProviders []OIDCProvider `json:"oidcProviders,omitempty"` } @@ -252,14 +252,14 @@ type OIDCProvider struct { // +listType=atomic // +kubebuilder:validation:MaxItems=64 // +optional - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity UserValidationRules []TokenUserValidationRule `json:"userValidationRules,omitempty"` } // +kubebuilder:validation:MinLength=1 type TokenAudience string -// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithNewAuthConfigFields,rule="self.?discoveryURL.orValue(\"\").size() > 0 ? (self.issuerURL.size() == 0 || self.discoveryURL.find('^.+[^/]') != self.issuerURL.find('^.+[^/]')) : true",message="discoveryURL must be different from issuerURL" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUpstreamParity,rule="self.?discoveryURL.orValue(\"\").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. @@ -314,7 +314,7 @@ type TokenIssuer struct { // - Be different from the value of `url` (ignoring trailing slashes) // // +optional - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity // +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" @@ -329,7 +329,7 @@ type TokenIssuer struct { // - "MatchAny": The token is accepted if any of its audiences match any of the configured audiences. // // +optional - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity AudienceMatchPolicy *AudienceMatchPolicy `json:"audienceMatchPolicy,omitempty"` } @@ -782,14 +782,7 @@ const ( // 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" - -// 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" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUpstreamParity,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. // @@ -847,7 +840,7 @@ type TokenExpressionRule struct { // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 // +required - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity Expression string `json:"expression,omitempty"` // message allows configuring the human-readable message that is returned @@ -857,7 +850,7 @@ type TokenExpressionRule struct { // +optional // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=256 - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity Message string `json:"message,omitempty"` } @@ -877,7 +870,7 @@ type TokenUserValidationRule struct { // +required // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=4096 - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity 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. @@ -885,6 +878,6 @@ type TokenUserValidationRule struct { // +optional // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=256 - // +openshift:enable:FeatureGate=ExternalOIDCWithNewAuthConfigFields + // +openshift:enable:FeatureGate=ExternalOIDCWithUpstreamParity 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 37cff2d9136..eff7329eeff 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 7af18df63b4..12189002007 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 @@ -259,10 +259,6 @@ spec: and forbidden otherwise 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 - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: 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 c629a6adbea..373dbfac764 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 1481935a588..2723a655104 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 6f642139030..91b11806a68 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 05e1b5e7d53..ecb533f94de 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 3a8bc8ad0bd..95ddd24093e 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' diff --git a/config/v1/zz_generated.featuregated-crd-manifests.yaml b/config/v1/zz_generated.featuregated-crd-manifests.yaml index 09d83050102..d8c2e2fd289 100644 --- a/config/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/config/v1/zz_generated.featuregated-crd-manifests.yaml @@ -30,8 +30,8 @@ authentications.config.openshift.io: Category: "" FeatureGates: - ExternalOIDC - - ExternalOIDCWithNewAuthConfigFields - ExternalOIDCWithUIDAndExtraClaimMappings + - ExternalOIDCWithUpstreamParity FilenameOperatorName: config-operator FilenameOperatorOrdering: "01" FilenameRunLevel: "0000_10" 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 028875200e7..2ed9bb1f668 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 @@ -260,10 +260,6 @@ spec: and forbidden otherwise 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 - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: 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 e7f277e18ee..7892245c482 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 @@ -411,10 +411,6 @@ spec: and forbidden otherwise 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 - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic 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/ExternalOIDCWithUpstreamParity.yaml similarity index 98% rename from config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithNewAuthConfigFields.yaml rename to config/v1/zz_generated.featuregated-crd-manifests/authentications.config.openshift.io/ExternalOIDCWithUpstreamParity.yaml index 5cf72460b67..258ac5b6b19 100644 --- 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/ExternalOIDCWithUpstreamParity.yaml @@ -6,7 +6,7 @@ metadata: 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" + feature-gate.release.openshift.io/ExternalOIDCWithUpstreamParity: "true" release.openshift.io/bootstrap-required: "true" name: authentications.config.openshift.io spec: @@ -279,14 +279,6 @@ spec: and forbidden otherwise 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 - 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)' - message: requiredClaim must be set when type is 'RequiredClaim', and forbidden otherwise rule: 'has(self.type) && self.type == ''RequiredClaim'' diff --git a/features.md b/features.md index 815291221a8..81d9212c68e 100644 --- a/features.md +++ b/features.md @@ -39,8 +39,8 @@ | 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 | +| ExternalOIDCWithUpstreamParity| | | Enabled | Enabled | Enabled | Enabled | | GCPClusterHostedDNS| | | Enabled | Enabled | Enabled | Enabled | | GCPCustomAPIEndpoints| | | Enabled | Enabled | Enabled | Enabled | | GCPCustomAPIEndpointsInstall| | | Enabled | Enabled | Enabled | Enabled | diff --git a/features/features.go b/features/features.go index 69bb40cbbc7..50bfaa0f014 100644 --- a/features/features.go +++ b/features/features.go @@ -477,7 +477,7 @@ var ( enableForClusterProfile(Hypershift, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() - FeatureGateExternalOIDCWithNewAuthConfigFields = newFeatureGate("ExternalOIDCWithNewAuthConfigFields"). + FeatureGateExternalOIDCWithUpstreamParity = newFeatureGate("ExternalOIDCWithUpstreamParity"). reportProblemsToJiraComponent("authentication"). contactPerson("saldawam"). productScope(ocpSpecific). 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 37cff2d9136..eff7329eeff 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 7af18df63b4..12189002007 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 @@ -259,10 +259,6 @@ spec: and forbidden otherwise 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 - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' type: array x-kubernetes-list-type: atomic issuer: 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 c629a6adbea..373dbfac764 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 1481935a588..2723a655104 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 6f642139030..91b11806a68 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 05e1b5e7d53..ecb533f94de 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' 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 3a8bc8ad0bd..95ddd24093e 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 @@ -425,10 +425,10 @@ spec: type: string type: object x-kubernetes-validations: - - message: requiredClaim must be set when type is 'RequiredClaim', + - message: expressionRule must be set when type is 'Expression', and forbidden otherwise - rule: 'has(self.type) && self.type == ''RequiredClaim'' - ? has(self.requiredClaim) : !has(self.requiredClaim)' + 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'' diff --git a/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml b/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml index 7cf987c8c62..7f6c1d96620 100644 --- a/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml +++ b/payload-manifests/featuregates/featureGate-Hypershift-Default.yaml @@ -98,10 +98,10 @@ "name": "Example2" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "ExternalSnapshotMetadata" diff --git a/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml index ec1cf4c84c0..d02e528dad8 100644 --- a/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml +++ b/payload-manifests/featuregates/featureGate-Hypershift-DevPreviewNoUpgrade.yaml @@ -153,10 +153,10 @@ "name": "ExternalOIDC" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "ExternalSnapshotMetadata" diff --git a/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml index f0ea5ba5af4..2708e9dc44e 100644 --- a/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml +++ b/payload-manifests/featuregates/featureGate-Hypershift-TechPreviewNoUpgrade.yaml @@ -159,10 +159,10 @@ "name": "ExternalOIDC" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "GCPClusterHostedDNS" diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml index 45bdf40a017..779714a5d26 100644 --- a/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml +++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-Default.yaml @@ -101,10 +101,10 @@ "name": "ExternalOIDC" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "ExternalSnapshotMetadata" diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml index f7929ebfb99..10848e23c59 100644 --- a/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml +++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-DevPreviewNoUpgrade.yaml @@ -135,10 +135,10 @@ "name": "ExternalOIDC" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "ExternalSnapshotMetadata" diff --git a/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml b/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml index d7de931dd7c..bfb0310e483 100644 --- a/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml +++ b/payload-manifests/featuregates/featureGate-SelfManagedHA-TechPreviewNoUpgrade.yaml @@ -141,10 +141,10 @@ "name": "ExternalOIDC" }, { - "name": "ExternalOIDCWithNewAuthConfigFields" + "name": "ExternalOIDCWithUIDAndExtraClaimMappings" }, { - "name": "ExternalOIDCWithUIDAndExtraClaimMappings" + "name": "ExternalOIDCWithUpstreamParity" }, { "name": "GCPClusterHostedDNS"