Skip to content

[WIP]: CNTRLPLANE-311: Add missing fields to auth config #2304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 80 additions & 5 deletions config/v1/types_authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ type OIDCProvider struct {
//
// +listType=atomic
ClaimValidationRules []TokenClaimValidationRule `json:"claimValidationRules,omitempty"`

// +optional
// userValidationRules provides the configuration for a single user validation rule.
UserValidationRules []TokenUserValidationRule `json:"userValidationRules,omitempty"`
}

// +kubebuilder:validation:MinLength=1
Expand Down Expand Up @@ -251,8 +255,40 @@ type TokenIssuer struct {
// the "ca-bundle.crt" key.
// If unset, system trust is used instead.
CertificateAuthority ConfigMapNameReference `json:"issuerCertificateAuthority"`

// discoveryURL, if specified, overrides the URL used to fetch discovery
// information instead of using "{url}/.well-known/openid-configuration".
// The exact value specified is used, so "/.well-known/openid-configuration"
// must be included in discoveryURL if needed. Must be a valid https URL
// without query parameters, user info, or fragments.
//
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? isURL(self) : true",message="discoveryURL must be a valid URL"
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).scheme == 'https' : true",message="discoveryURL must use https scheme"
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).query == '' : true",message="discoveryURL must not contain query parameters"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would need to be:

Suggested change
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).query == '' : true",message="discoveryURL must not contain query parameters"
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).getQuery() == '' : true",message="discoveryURL must not contain query parameters"

// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).user == '' : true",message="discoveryURL must not contain user info"
// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? url(self).fragment == '' : true",message="discoveryURL must not contain a fragment"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't appear to be a helper for user or fragment pieces of the URL - we should try to implement a Regular Expression that gets us the same validation we are looking for.

// +kubebuilder:validation:XValidation:rule="self.size() > 0 ? (issuer.url.size() == 0 || self.find('^.+[^/]') != issuer.url.find('^.+[^/]')) : true",message="discoveryURL must be different from URL"
//
// +optional
DiscoveryURL string `json:"discoveryURL,omitempty"`

// audienceMatchPolicy specifies how token audiences are matched.
// If omitted, the system applies a default policy.
//
// +optional
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 name of the claim that should be used to construct
// usernames for the cluster identity.
Expand Down Expand Up @@ -565,27 +601,44 @@ type PrefixedClaimMapping struct {
Prefix string `json:"prefix"`
}

// TokenValidationRuleType defines the type of token validation rule.
//
// +kubebuilder:validation:Enum=RequiredClaim;Expression
type TokenValidationRuleType string

const (
TokenValidationRuleTypeRequiredClaim = "RequiredClaim"
TokenValidationRuleRequiredClaim TokenValidationRuleType = "RequiredClaim"
TokenValidationRuleExpression TokenValidationRuleType = "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="self.type != 'RequiredClaim' || has(self.requiredClaim)",message="requiredClaim must be set when type is 'RequiredClaim'"
// +kubebuilder:validation:XValidation:rule="self.type != 'Expression' || has(self.expressionRule)",message="expressionRule must be set when type is 'Expression'"

type TokenClaimValidationRule struct {
// type sets the type of the validation rule
//
// +kubebuilder:validation:Enum={"RequiredClaim"}
// +kubebuilder:default="RequiredClaim"
Type TokenValidationRuleType `json:"type"`

// requiredClaim allows configuring a required claim name and its expected
// value
// requiredClaim allows configuring a required claim name and its expected value.
// RequiredClaim is used when type is RequiredClaim.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if type: RequiredClaim and requiredClaim == nil today?

// +optional
RequiredClaim *TokenRequiredClaim `json:"requiredClaim"`

// 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 name of a required claim. Only claims with string values are
// supported.
// claim is a name of a required claim. Only claims with string values are supported.
//
// +kubebuilder:validation:MinLength=1
// +required
Expand All @@ -597,3 +650,25 @@ type TokenRequiredClaim struct {
// +required
RequiredValue string `json:"requiredValue"`
}

type TokenExpressionRule struct {
// CEL expression to evaluate against token claims.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=4096
Expression string `json:"expression"`

// Optional message shown when the validation fails.
// +optional
Message string `json:"message,omitempty"`
}

// UserValidationRule provides the configuration for a single user validation rule.
type TokenUserValidationRule struct {
// Expression must not exceed 4096 characters in length.
// Expression must not be empty.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=4096
Expression string `json:"expression,omitempty"`
Message string `json:"message,omitempty"`
}