feat: kubesphere 4.0 (#6115)

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -43,6 +43,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
)
scheme.AddKnownTypes(SchemeGroupVersion,
&AdmissionConfiguration{},
&AuthenticationConfiguration{},
&AuthorizationConfiguration{},
&EgressSelectorConfiguration{},
&TracingConfiguration{},
)

View File

@@ -19,6 +19,7 @@ package apiserver
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
tracingapi "k8s.io/component-base/tracing/api/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -153,16 +154,191 @@ type TLSConfig struct {
type TracingConfiguration struct {
metav1.TypeMeta
// +optional
// Endpoint of the collector that's running on the control-plane node.
// The APIServer uses the egressType ControlPlane when sending data to the collector.
// The syntax is defined in https://github.com/grpc/grpc/blob/master/doc/naming.md.
// Defaults to the otlp grpc default, localhost:4317
// The connection is insecure, and does not currently support TLS.
Endpoint *string
// +optional
// SamplingRatePerMillion is the number of samples to collect per million spans.
// Defaults to 0.
SamplingRatePerMillion *int32
// Embed the component config tracing configuration struct
tracingapi.TracingConfiguration
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AuthenticationConfiguration provides versioned configuration for authentication.
type AuthenticationConfiguration struct {
metav1.TypeMeta
JWT []JWTAuthenticator
}
// JWTAuthenticator provides the configuration for a single JWT authenticator.
type JWTAuthenticator struct {
Issuer Issuer
ClaimValidationRules []ClaimValidationRule
ClaimMappings ClaimMappings
UserValidationRules []UserValidationRule
}
// Issuer provides the configuration for a external provider specific settings.
type Issuer struct {
URL string
CertificateAuthority string
Audiences []string
}
// ClaimValidationRule provides the configuration for a single claim validation rule.
type ClaimValidationRule struct {
Claim string
RequiredValue string
Expression string
Message string
}
// ClaimMappings provides the configuration for claim mapping
type ClaimMappings struct {
Username PrefixedClaimOrExpression
Groups PrefixedClaimOrExpression
UID ClaimOrExpression
Extra []ExtraMapping
}
// PrefixedClaimOrExpression provides the configuration for a single prefixed claim or expression.
type PrefixedClaimOrExpression struct {
Claim string
Prefix *string
Expression string
}
// ClaimOrExpression provides the configuration for a single claim or expression.
type ClaimOrExpression struct {
Claim string
Expression string
}
// ExtraMapping provides the configuration for a single extra mapping.
type ExtraMapping struct {
Key string
ValueExpression string
}
// UserValidationRule provides the configuration for a single user validation rule.
type UserValidationRule struct {
Expression string
Message string
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AuthorizationConfiguration struct {
metav1.TypeMeta
// Authorizers is an ordered list of authorizers to
// authorize requests against.
// This is similar to the --authorization-modes kube-apiserver flag
// Must be at least one.
Authorizers []AuthorizerConfiguration `json:"authorizers"`
}
const (
TypeWebhook AuthorizerType = "Webhook"
FailurePolicyNoOpinion string = "NoOpinion"
FailurePolicyDeny string = "Deny"
AuthorizationWebhookConnectionInfoTypeKubeConfigFile string = "KubeConfigFile"
AuthorizationWebhookConnectionInfoTypeInCluster string = "InClusterConfig"
)
type AuthorizerType string
type AuthorizerConfiguration struct {
// Type refers to the type of the authorizer
// "Webhook" is supported in the generic API server
// Other API servers may support additional authorizer
// types like Node, RBAC, ABAC, etc.
Type AuthorizerType
// Name used to describe the webhook
// This is explicitly used in monitoring machinery for metrics
// Note: Names must be DNS1123 labels like `myauthorizername` or
// subdomains like `myauthorizer.example.domain`
// Required, with no default
Name string
// Webhook defines the configuration for a Webhook authorizer
// Must be defined when Type=Webhook
Webhook *WebhookConfiguration
}
type WebhookConfiguration struct {
// The duration to cache 'authorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.
Timeout metav1.Duration
// The API version of the authorization.k8s.io SubjectAccessReview to
// send to and expect from the webhook.
// Same as setting `--authorization-webhook-version` flag
// Valid values: v1beta1, v1
// Required, no default value
SubjectAccessReviewVersion string
// MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
// version the CEL expressions are evaluated against
// Valid values: v1
// Required, no default value
MatchConditionSubjectAccessReviewVersion string
// Controls the authorization decision when a webhook request fails to
// complete or returns a malformed response or errors evaluating
// matchConditions.
// Valid values:
// - NoOpinion: continue to subsequent authorizers to see if one of
// them allows the request
// - Deny: reject the request without consulting subsequent authorizers
// Required, with no default.
FailurePolicy string
// ConnectionInfo defines how we talk to the webhook
ConnectionInfo WebhookConnectionInfo
// matchConditions is a list of conditions that must be met for a request to be sent to this
// webhook. An empty list of matchConditions matches all requests.
// There are a maximum of 64 match conditions allowed.
//
// The exact matching logic is (in order):
// 1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
// 2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
// 3. If at least one matchCondition evaluates to an error (but none are FALSE):
// - If failurePolicy=Deny, then the webhook rejects the request
// - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
MatchConditions []WebhookMatchCondition
}
type WebhookConnectionInfo struct {
// Controls how the webhook should communicate with the server.
// Valid values:
// - KubeConfigFile: use the file specified in kubeConfigFile to locate the
// server.
// - InClusterConfig: use the in-cluster configuration to call the
// SubjectAccessReview API hosted by kube-apiserver. This mode is not
// allowed for kube-apiserver.
Type string
// Path to KubeConfigFile for connection info
// Required, if connectionInfo.Type is KubeConfig
KubeConfigFile *string
}
type WebhookMatchCondition struct {
// expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
// CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
// If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
// the contents would be converted to the v1 version before evaluating the CEL expression.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
Expression string
}

View File

@@ -0,0 +1,36 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"time"
"k8s.io/apimachinery/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}
func SetDefaults_WebhookConfiguration(obj *WebhookConfiguration) {
if obj.AuthorizedTTL.Duration == 0 {
obj.AuthorizedTTL.Duration = 5 * time.Minute
}
if obj.UnauthorizedTTL.Duration == 0 {
obj.UnauthorizedTTL.Duration = 30 * time.Second
}
}

View File

@@ -43,7 +43,7 @@ func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
}
// Adds the list of known types to the given scheme.
@@ -53,6 +53,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&EgressSelectorConfiguration{},
)
scheme.AddKnownTypes(ConfigSchemeGroupVersion,
&AuthenticationConfiguration{},
&AuthorizationConfiguration{},
&TracingConfiguration{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)

View File

@@ -19,6 +19,7 @@ package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
tracingapi "k8s.io/component-base/tracing/api/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -154,16 +155,382 @@ type TLSConfig struct {
type TracingConfiguration struct {
metav1.TypeMeta `json:",inline"`
// +optional
// Endpoint of the collector that's running on the control-plane node.
// The APIServer uses the egressType ControlPlane when sending data to the collector.
// The syntax is defined in https://github.com/grpc/grpc/blob/master/doc/naming.md.
// Defaults to the otlpgrpc default, localhost:4317
// The connection is insecure, and does not support TLS.
Endpoint *string `json:"endpoint,omitempty" protobuf:"bytes,1,opt,name=endpoint"`
// +optional
// SamplingRatePerMillion is the number of samples to collect per million spans.
// Defaults to 0.
SamplingRatePerMillion *int32 `json:"samplingRatePerMillion,omitempty" protobuf:"varint,2,opt,name=samplingRatePerMillion"`
// Embed the component config tracing configuration struct
tracingapi.TracingConfiguration `json:",inline"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AuthenticationConfiguration provides versioned configuration for authentication.
type AuthenticationConfiguration struct {
metav1.TypeMeta
// jwt is a list of authenticator to authenticate Kubernetes users using
// JWT compliant tokens. The authenticator will attempt to parse a raw ID token,
// verify it's been signed by the configured issuer. The public key to verify the
// signature is discovered from the issuer's public endpoint using OIDC discovery.
// For an incoming token, each JWT authenticator will be attempted in
// the order in which it is specified in this list. Note however that
// other authenticators may run before or after the JWT authenticators.
// The specific position of JWT authenticators in relation to other
// authenticators is neither defined nor stable across releases. Since
// each JWT authenticator must have a unique issuer URL, at most one
// JWT authenticator will attempt to cryptographically validate the token.
JWT []JWTAuthenticator `json:"jwt"`
}
// JWTAuthenticator provides the configuration for a single JWT authenticator.
type JWTAuthenticator struct {
// issuer contains the basic OIDC provider connection options.
// +required
Issuer Issuer `json:"issuer"`
// claimValidationRules are rules that are applied to validate token claims to authenticate users.
// +optional
ClaimValidationRules []ClaimValidationRule `json:"claimValidationRules,omitempty"`
// claimMappings points claims of a token to be treated as user attributes.
// +required
ClaimMappings ClaimMappings `json:"claimMappings"`
// userValidationRules are rules that are applied to final user before completing authentication.
// These allow invariants to be applied to incoming identities such as preventing the
// use of the system: prefix that is commonly used by Kubernetes components.
// The validation rules are logically ANDed together and must all return true for the validation to pass.
// +optional
UserValidationRules []UserValidationRule `json:"userValidationRules,omitempty"`
}
// Issuer provides the configuration for a external provider specific settings.
type Issuer struct {
// url points to the issuer URL in a format https://url or https://url/path.
// This must match the "iss" claim in the presented JWT, and the issuer returned from discovery.
// Same value as the --oidc-issuer-url flag.
// Used to fetch discovery information unless overridden by discoveryURL.
// Required to be unique.
// Note that egress selection configuration is not used for this network connection.
// +required
URL string `json:"url"`
// certificateAuthority contains PEM-encoded certificate authority certificates
// used to validate the connection when fetching discovery information.
// If unset, the system verifier is used.
// Same value as the content of the file referenced by the --oidc-ca-file flag.
// +optional
CertificateAuthority string `json:"certificateAuthority,omitempty"`
// audiences is the set of acceptable audiences the JWT must be issued to.
// At least one of the entries must match the "aud" claim in presented JWTs.
// Same value as the --oidc-client-id flag (though this field supports an array).
// Required to be non-empty.
// +required
Audiences []string `json:"audiences"`
}
// ClaimValidationRule provides the configuration for a single claim validation rule.
type ClaimValidationRule struct {
// claim is the name of a required claim.
// Same as --oidc-required-claim flag.
// Only string claim keys are supported.
// Mutually exclusive with expression and message.
// +optional
Claim string `json:"claim,omitempty"`
// requiredValue is the value of a required claim.
// Same as --oidc-required-claim flag.
// Only string claim values are supported.
// If claim is set and requiredValue is not set, the claim must be present with a value set to the empty string.
// Mutually exclusive with expression and message.
// +optional
RequiredValue string `json:"requiredValue,omitempty"`
// expression represents the expression which will be evaluated by CEL.
// Must produce a boolean.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
// Must return true for the validation to pass.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim and requiredValue.
// +optional
Expression string `json:"expression,omitempty"`
// message customizes the returned error message when expression returns false.
// message is a literal string.
// Mutually exclusive with claim and requiredValue.
// +optional
Message string `json:"message,omitempty"`
}
// ClaimMappings provides the configuration for claim mapping
type ClaimMappings struct {
// username represents an option for the username attribute.
// The claim's value must be a singular string.
// Same as the --oidc-username-claim and --oidc-username-prefix flags.
// If username.expression is set, the expression must produce a string value.
//
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
// For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config.
// For prefix:
// (1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config,
// set username.prefix=""
// (2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "<value of --oidc-issuer-url>#". For the same
// behavior using authentication config, set username.prefix="<value of issuer.url>#"
// (3) --oidc-username-prefix="<value>". For the same behavior using authentication config, set username.prefix="<value>"
// +required
Username PrefixedClaimOrExpression `json:"username"`
// groups represents an option for the groups attribute.
// The claim's value must be a string or string array claim.
// If groups.claim is set, the prefix must be specified (and can be the empty string).
// If groups.expression is set, the expression must produce a string or string array value.
// "", [], and null values are treated as the group mapping not being present.
// +optional
Groups PrefixedClaimOrExpression `json:"groups,omitempty"`
// uid represents an option for the uid attribute.
// Claim must be a singular string claim.
// If uid.expression is set, the expression must produce a string value.
// +optional
UID ClaimOrExpression `json:"uid"`
// extra represents an option for the extra attribute.
// expression must produce a string or string array value.
// If the value is empty, the extra mapping will not be present.
//
// hard-coded extra key/value
// - key: "foo"
// valueExpression: "'bar'"
// This will result in an extra attribute - foo: ["bar"]
//
// hard-coded key, value copying claim value
// - key: "foo"
// valueExpression: "claims.some_claim"
// This will result in an extra attribute - foo: [value of some_claim]
//
// hard-coded key, value derived from claim value
// - key: "admin"
// valueExpression: '(has(claims.is_admin) && claims.is_admin) ? "true":""'
// This will result in:
// - if is_admin claim is present and true, extra attribute - admin: ["true"]
// - if is_admin claim is present and false or is_admin claim is not present, no extra attribute will be added
//
// +optional
Extra []ExtraMapping `json:"extra,omitempty"`
}
// PrefixedClaimOrExpression provides the configuration for a single prefixed claim or expression.
type PrefixedClaimOrExpression struct {
// claim is the JWT claim to use.
// Mutually exclusive with expression.
// +optional
Claim string `json:"claim,omitempty"`
// prefix is prepended to claim's value to prevent clashes with existing names.
// prefix needs to be set if claim is set and can be the empty string.
// Mutually exclusive with expression.
// +optional
Prefix *string `json:"prefix,omitempty"`
// expression represents the expression which will be evaluated by CEL.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim and prefix.
// +optional
Expression string `json:"expression,omitempty"`
}
// ClaimOrExpression provides the configuration for a single claim or expression.
type ClaimOrExpression struct {
// claim is the JWT claim to use.
// Either claim or expression must be set.
// Mutually exclusive with expression.
// +optional
Claim string `json:"claim,omitempty"`
// expression represents the expression which will be evaluated by CEL.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// Mutually exclusive with claim.
// +optional
Expression string `json:"expression,omitempty"`
}
// ExtraMapping provides the configuration for a single extra mapping.
type ExtraMapping struct {
// key is a string to use as the extra attribute key.
// key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid
// subdomain as defined by RFC 1123. All characters trailing the first "/" must
// be valid HTTP Path characters as defined by RFC 3986.
// key must be lowercase.
// +required
Key string `json:"key"`
// valueExpression is a CEL expression to extract extra attribute value.
// valueExpression must produce a string or string array value.
// "", [], and null values are treated as the extra mapping not being present.
// Empty string values contained within a string array are filtered out.
//
// CEL expressions have access to the contents of the token claims, organized into CEL variable:
// - 'claims' is a map of claim names to claim values.
// For example, a variable named 'sub' can be accessed as 'claims.sub'.
// Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// +required
ValueExpression string `json:"valueExpression"`
}
// UserValidationRule provides the configuration for a single user info validation rule.
type UserValidationRule struct {
// expression represents the expression which will be evaluated by CEL.
// Must return true for the validation to pass.
//
// CEL expressions have access to the contents of UserInfo, organized into CEL variable:
// - 'user' - authentication.k8s.io/v1, Kind=UserInfo object
// Refer to https://github.com/kubernetes/api/blob/release-1.28/authentication/v1/types.go#L105-L122 for the definition.
// API documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#userinfo-v1-authentication-k8s-io
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
//
// +required
Expression string `json:"expression"`
// message customizes the returned error message when rule returns false.
// message is a literal string.
// +optional
Message string `json:"message,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type AuthorizationConfiguration struct {
metav1.TypeMeta
// Authorizers is an ordered list of authorizers to
// authorize requests against.
// This is similar to the --authorization-modes kube-apiserver flag
// Must be at least one.
Authorizers []AuthorizerConfiguration `json:"authorizers"`
}
const (
TypeWebhook AuthorizerType = "Webhook"
FailurePolicyNoOpinion string = "NoOpinion"
FailurePolicyDeny string = "Deny"
AuthorizationWebhookConnectionInfoTypeKubeConfigFile string = "KubeConfigFile"
AuthorizationWebhookConnectionInfoTypeInCluster string = "InClusterConfig"
)
type AuthorizerType string
type AuthorizerConfiguration struct {
// Type refers to the type of the authorizer
// "Webhook" is supported in the generic API server
// Other API servers may support additional authorizer
// types like Node, RBAC, ABAC, etc.
Type string `json:"type"`
// Name used to describe the webhook
// This is explicitly used in monitoring machinery for metrics
// Note: Names must be DNS1123 labels like `myauthorizername` or
// subdomains like `myauthorizer.example.domain`
// Required, with no default
Name string `json:"name"`
// Webhook defines the configuration for a Webhook authorizer
// Must be defined when Type=Webhook
// Must not be defined when Type!=Webhook
Webhook *WebhookConfiguration `json:"webhook,omitempty"`
}
type WebhookConfiguration struct {
// The duration to cache 'authorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
// Default: 5m0s
AuthorizedTTL metav1.Duration `json:"authorizedTTL"`
// The duration to cache 'unauthorized' responses from the webhook
// authorizer.
// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
// Default: 30s
UnauthorizedTTL metav1.Duration `json:"unauthorizedTTL"`
// Timeout for the webhook request
// Maximum allowed value is 30s.
// Required, no default value.
Timeout metav1.Duration `json:"timeout"`
// The API version of the authorization.k8s.io SubjectAccessReview to
// send to and expect from the webhook.
// Same as setting `--authorization-webhook-version` flag
// Valid values: v1beta1, v1
// Required, no default value
SubjectAccessReviewVersion string `json:"subjectAccessReviewVersion"`
// MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
// version the CEL expressions are evaluated against
// Valid values: v1
// Required, no default value
MatchConditionSubjectAccessReviewVersion string `json:"matchConditionSubjectAccessReviewVersion"`
// Controls the authorization decision when a webhook request fails to
// complete or returns a malformed response or errors evaluating
// matchConditions.
// Valid values:
// - NoOpinion: continue to subsequent authorizers to see if one of
// them allows the request
// - Deny: reject the request without consulting subsequent authorizers
// Required, with no default.
FailurePolicy string `json:"failurePolicy"`
// ConnectionInfo defines how we talk to the webhook
ConnectionInfo WebhookConnectionInfo `json:"connectionInfo"`
// matchConditions is a list of conditions that must be met for a request to be sent to this
// webhook. An empty list of matchConditions matches all requests.
// There are a maximum of 64 match conditions allowed.
//
// The exact matching logic is (in order):
// 1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
// 2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
// 3. If at least one matchCondition evaluates to an error (but none are FALSE):
// - If failurePolicy=Deny, then the webhook rejects the request
// - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
MatchConditions []WebhookMatchCondition `json:"matchConditions"`
}
type WebhookConnectionInfo struct {
// Controls how the webhook should communicate with the server.
// Valid values:
// - KubeConfigFile: use the file specified in kubeConfigFile to locate the
// server.
// - InClusterConfig: use the in-cluster configuration to call the
// SubjectAccessReview API hosted by kube-apiserver. This mode is not
// allowed for kube-apiserver.
Type string `json:"type"`
// Path to KubeConfigFile for connection info
// Required, if connectionInfo.Type is KubeConfig
KubeConfigFile *string `json:"kubeConfigFile"`
}
type WebhookMatchCondition struct {
// expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
// CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
// If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
// the contents would be converted to the v1 version before evaluating the CEL expression.
//
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
Expression string `json:"expression"`
}

View File

@@ -56,6 +56,66 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthenticationConfiguration)(nil), (*apiserver.AuthenticationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(a.(*AuthenticationConfiguration), b.(*apiserver.AuthenticationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AuthenticationConfiguration)(nil), (*AuthenticationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(a.(*apiserver.AuthenticationConfiguration), b.(*AuthenticationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthorizationConfiguration)(nil), (*apiserver.AuthorizationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(a.(*AuthorizationConfiguration), b.(*apiserver.AuthorizationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AuthorizationConfiguration)(nil), (*AuthorizationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(a.(*apiserver.AuthorizationConfiguration), b.(*AuthorizationConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*AuthorizerConfiguration)(nil), (*apiserver.AuthorizerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(a.(*AuthorizerConfiguration), b.(*apiserver.AuthorizerConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.AuthorizerConfiguration)(nil), (*AuthorizerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(a.(*apiserver.AuthorizerConfiguration), b.(*AuthorizerConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimMappings)(nil), (*apiserver.ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(a.(*ClaimMappings), b.(*apiserver.ClaimMappings), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimMappings)(nil), (*ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings(a.(*apiserver.ClaimMappings), b.(*ClaimMappings), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimOrExpression)(nil), (*apiserver.ClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression(a.(*ClaimOrExpression), b.(*apiserver.ClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimOrExpression)(nil), (*ClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression(a.(*apiserver.ClaimOrExpression), b.(*ClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClaimValidationRule)(nil), (*apiserver.ClaimValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ClaimValidationRule_To_apiserver_ClaimValidationRule(a.(*ClaimValidationRule), b.(*apiserver.ClaimValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ClaimValidationRule)(nil), (*ClaimValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ClaimValidationRule_To_v1alpha1_ClaimValidationRule(a.(*apiserver.ClaimValidationRule), b.(*ClaimValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Connection)(nil), (*apiserver.Connection)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Connection_To_apiserver_Connection(a.(*Connection), b.(*apiserver.Connection), scope)
}); err != nil {
@@ -81,6 +141,46 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExtraMapping)(nil), (*apiserver.ExtraMapping)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ExtraMapping_To_apiserver_ExtraMapping(a.(*ExtraMapping), b.(*apiserver.ExtraMapping), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.ExtraMapping)(nil), (*ExtraMapping)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping(a.(*apiserver.ExtraMapping), b.(*ExtraMapping), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Issuer)(nil), (*apiserver.Issuer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Issuer_To_apiserver_Issuer(a.(*Issuer), b.(*apiserver.Issuer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.Issuer)(nil), (*Issuer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_Issuer_To_v1alpha1_Issuer(a.(*apiserver.Issuer), b.(*Issuer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*JWTAuthenticator)(nil), (*apiserver.JWTAuthenticator)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator(a.(*JWTAuthenticator), b.(*apiserver.JWTAuthenticator), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.JWTAuthenticator)(nil), (*JWTAuthenticator)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator(a.(*apiserver.JWTAuthenticator), b.(*JWTAuthenticator), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*PrefixedClaimOrExpression)(nil), (*apiserver.PrefixedClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(a.(*PrefixedClaimOrExpression), b.(*apiserver.PrefixedClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.PrefixedClaimOrExpression)(nil), (*PrefixedClaimOrExpression)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(a.(*apiserver.PrefixedClaimOrExpression), b.(*PrefixedClaimOrExpression), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*TCPTransport)(nil), (*apiserver.TCPTransport)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(a.(*TCPTransport), b.(*apiserver.TCPTransport), scope)
}); err != nil {
@@ -131,6 +231,46 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*UserValidationRule)(nil), (*apiserver.UserValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_UserValidationRule_To_apiserver_UserValidationRule(a.(*UserValidationRule), b.(*apiserver.UserValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.UserValidationRule)(nil), (*UserValidationRule)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule(a.(*apiserver.UserValidationRule), b.(*UserValidationRule), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*WebhookConfiguration)(nil), (*apiserver.WebhookConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(a.(*WebhookConfiguration), b.(*apiserver.WebhookConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.WebhookConfiguration)(nil), (*WebhookConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(a.(*apiserver.WebhookConfiguration), b.(*WebhookConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*WebhookConnectionInfo)(nil), (*apiserver.WebhookConnectionInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(a.(*WebhookConnectionInfo), b.(*apiserver.WebhookConnectionInfo), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.WebhookConnectionInfo)(nil), (*WebhookConnectionInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(a.(*apiserver.WebhookConnectionInfo), b.(*WebhookConnectionInfo), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*WebhookMatchCondition)(nil), (*apiserver.WebhookMatchCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(a.(*WebhookMatchCondition), b.(*apiserver.WebhookMatchCondition), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.WebhookMatchCondition)(nil), (*WebhookMatchCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(a.(*apiserver.WebhookMatchCondition), b.(*WebhookMatchCondition), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*EgressSelection)(nil), (*apiserver.EgressSelection)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_EgressSelection_To_apiserver_EgressSelection(a.(*EgressSelection), b.(*apiserver.EgressSelection), scope)
}); err != nil {
@@ -183,6 +323,156 @@ func Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginC
return autoConvert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginConfiguration(in, out, s)
}
func autoConvert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
out.JWT = *(*[]apiserver.JWTAuthenticator)(unsafe.Pointer(&in.JWT))
return nil
}
// Convert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in, out, s)
}
func autoConvert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
out.JWT = *(*[]JWTAuthenticator)(unsafe.Pointer(&in.JWT))
return nil
}
// Convert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration is an autogenerated conversion function.
func Convert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in, out, s)
}
func autoConvert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
return nil
}
// Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in, out, s)
}
func autoConvert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
return nil
}
// Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration is an autogenerated conversion function.
func Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in, out, s)
}
func autoConvert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
out.Type = apiserver.AuthorizerType(in.Type)
out.Name = in.Name
out.Webhook = (*apiserver.WebhookConfiguration)(unsafe.Pointer(in.Webhook))
return nil
}
// Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in, out, s)
}
func autoConvert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
out.Type = string(in.Type)
out.Name = in.Name
out.Webhook = (*WebhookConfiguration)(unsafe.Pointer(in.Webhook))
return nil
}
// Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration is an autogenerated conversion function.
func Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in, out, s)
}
func autoConvert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
if err := Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
return err
}
if err := Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
return err
}
if err := Convert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
return err
}
out.Extra = *(*[]apiserver.ExtraMapping)(unsafe.Pointer(&in.Extra))
return nil
}
// Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings is an autogenerated conversion function.
func Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
return autoConvert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(in, out, s)
}
func autoConvert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
return err
}
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
return err
}
if err := Convert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
return err
}
out.Extra = *(*[]ExtraMapping)(unsafe.Pointer(&in.Extra))
return nil
}
// Convert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings is an autogenerated conversion function.
func Convert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
return autoConvert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings(in, out, s)
}
func autoConvert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Expression = in.Expression
return nil
}
// Convert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression is an autogenerated conversion function.
func Convert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
return autoConvert_v1alpha1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in, out, s)
}
func autoConvert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Expression = in.Expression
return nil
}
// Convert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression is an autogenerated conversion function.
func Convert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
return autoConvert_apiserver_ClaimOrExpression_To_v1alpha1_ClaimOrExpression(in, out, s)
}
func autoConvert_v1alpha1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in *ClaimValidationRule, out *apiserver.ClaimValidationRule, s conversion.Scope) error {
out.Claim = in.Claim
out.RequiredValue = in.RequiredValue
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_v1alpha1_ClaimValidationRule_To_apiserver_ClaimValidationRule is an autogenerated conversion function.
func Convert_v1alpha1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in *ClaimValidationRule, out *apiserver.ClaimValidationRule, s conversion.Scope) error {
return autoConvert_v1alpha1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in, out, s)
}
func autoConvert_apiserver_ClaimValidationRule_To_v1alpha1_ClaimValidationRule(in *apiserver.ClaimValidationRule, out *ClaimValidationRule, s conversion.Scope) error {
out.Claim = in.Claim
out.RequiredValue = in.RequiredValue
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_apiserver_ClaimValidationRule_To_v1alpha1_ClaimValidationRule is an autogenerated conversion function.
func Convert_apiserver_ClaimValidationRule_To_v1alpha1_ClaimValidationRule(in *apiserver.ClaimValidationRule, out *ClaimValidationRule, s conversion.Scope) error {
return autoConvert_apiserver_ClaimValidationRule_To_v1alpha1_ClaimValidationRule(in, out, s)
}
func autoConvert_v1alpha1_Connection_To_apiserver_Connection(in *Connection, out *apiserver.Connection, s conversion.Scope) error {
out.ProxyProtocol = apiserver.ProtocolType(in.ProxyProtocol)
out.Transport = (*apiserver.Transport)(unsafe.Pointer(in.Transport))
@@ -266,6 +556,110 @@ func Convert_apiserver_EgressSelectorConfiguration_To_v1alpha1_EgressSelectorCon
return autoConvert_apiserver_EgressSelectorConfiguration_To_v1alpha1_EgressSelectorConfiguration(in, out, s)
}
func autoConvert_v1alpha1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
out.Key = in.Key
out.ValueExpression = in.ValueExpression
return nil
}
// Convert_v1alpha1_ExtraMapping_To_apiserver_ExtraMapping is an autogenerated conversion function.
func Convert_v1alpha1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
return autoConvert_v1alpha1_ExtraMapping_To_apiserver_ExtraMapping(in, out, s)
}
func autoConvert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
out.Key = in.Key
out.ValueExpression = in.ValueExpression
return nil
}
// Convert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping is an autogenerated conversion function.
func Convert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
return autoConvert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping(in, out, s)
}
func autoConvert_v1alpha1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
out.URL = in.URL
out.CertificateAuthority = in.CertificateAuthority
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
return nil
}
// Convert_v1alpha1_Issuer_To_apiserver_Issuer is an autogenerated conversion function.
func Convert_v1alpha1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
return autoConvert_v1alpha1_Issuer_To_apiserver_Issuer(in, out, s)
}
func autoConvert_apiserver_Issuer_To_v1alpha1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
out.URL = in.URL
out.CertificateAuthority = in.CertificateAuthority
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
return nil
}
// Convert_apiserver_Issuer_To_v1alpha1_Issuer is an autogenerated conversion function.
func Convert_apiserver_Issuer_To_v1alpha1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
return autoConvert_apiserver_Issuer_To_v1alpha1_Issuer(in, out, s)
}
func autoConvert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
if err := Convert_v1alpha1_Issuer_To_apiserver_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
return err
}
out.ClaimValidationRules = *(*[]apiserver.ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
if err := Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
return err
}
out.UserValidationRules = *(*[]apiserver.UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
return nil
}
// Convert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator is an autogenerated conversion function.
func Convert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
return autoConvert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in, out, s)
}
func autoConvert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
if err := Convert_apiserver_Issuer_To_v1alpha1_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
return err
}
out.ClaimValidationRules = *(*[]ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
if err := Convert_apiserver_ClaimMappings_To_v1alpha1_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
return err
}
out.UserValidationRules = *(*[]UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
return nil
}
// Convert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator is an autogenerated conversion function.
func Convert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
return autoConvert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator(in, out, s)
}
func autoConvert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in *PrefixedClaimOrExpression, out *apiserver.PrefixedClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Prefix = (*string)(unsafe.Pointer(in.Prefix))
out.Expression = in.Expression
return nil
}
// Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression is an autogenerated conversion function.
func Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in *PrefixedClaimOrExpression, out *apiserver.PrefixedClaimOrExpression, s conversion.Scope) error {
return autoConvert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in, out, s)
}
func autoConvert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(in *apiserver.PrefixedClaimOrExpression, out *PrefixedClaimOrExpression, s conversion.Scope) error {
out.Claim = in.Claim
out.Prefix = (*string)(unsafe.Pointer(in.Prefix))
out.Expression = in.Expression
return nil
}
// Convert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression is an autogenerated conversion function.
func Convert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(in *apiserver.PrefixedClaimOrExpression, out *PrefixedClaimOrExpression, s conversion.Scope) error {
return autoConvert_apiserver_PrefixedClaimOrExpression_To_v1alpha1_PrefixedClaimOrExpression(in, out, s)
}
func autoConvert_v1alpha1_TCPTransport_To_apiserver_TCPTransport(in *TCPTransport, out *apiserver.TCPTransport, s conversion.Scope) error {
out.URL = in.URL
out.TLSConfig = (*apiserver.TLSConfig)(unsafe.Pointer(in.TLSConfig))
@@ -313,8 +707,7 @@ func Convert_apiserver_TLSConfig_To_v1alpha1_TLSConfig(in *apiserver.TLSConfig,
}
func autoConvert_v1alpha1_TracingConfiguration_To_apiserver_TracingConfiguration(in *TracingConfiguration, out *apiserver.TracingConfiguration, s conversion.Scope) error {
out.Endpoint = (*string)(unsafe.Pointer(in.Endpoint))
out.SamplingRatePerMillion = (*int32)(unsafe.Pointer(in.SamplingRatePerMillion))
out.TracingConfiguration = in.TracingConfiguration
return nil
}
@@ -324,8 +717,7 @@ func Convert_v1alpha1_TracingConfiguration_To_apiserver_TracingConfiguration(in
}
func autoConvert_apiserver_TracingConfiguration_To_v1alpha1_TracingConfiguration(in *apiserver.TracingConfiguration, out *TracingConfiguration, s conversion.Scope) error {
out.Endpoint = (*string)(unsafe.Pointer(in.Endpoint))
out.SamplingRatePerMillion = (*int32)(unsafe.Pointer(in.SamplingRatePerMillion))
out.TracingConfiguration = in.TracingConfiguration
return nil
}
@@ -375,3 +767,105 @@ func autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.U
func Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
return autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in, out, s)
}
func autoConvert_v1alpha1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_v1alpha1_UserValidationRule_To_apiserver_UserValidationRule is an autogenerated conversion function.
func Convert_v1alpha1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
return autoConvert_v1alpha1_UserValidationRule_To_apiserver_UserValidationRule(in, out, s)
}
func autoConvert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
out.Expression = in.Expression
out.Message = in.Message
return nil
}
// Convert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule is an autogenerated conversion function.
func Convert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
return autoConvert_apiserver_UserValidationRule_To_v1alpha1_UserValidationRule(in, out, s)
}
func autoConvert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
out.UnauthorizedTTL = in.UnauthorizedTTL
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
out.FailurePolicy = in.FailurePolicy
if err := Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
return err
}
out.MatchConditions = *(*[]apiserver.WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
return nil
}
// Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in, out, s)
}
func autoConvert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
out.AuthorizedTTL = in.AuthorizedTTL
out.UnauthorizedTTL = in.UnauthorizedTTL
out.Timeout = in.Timeout
out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
out.FailurePolicy = in.FailurePolicy
if err := Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
return err
}
out.MatchConditions = *(*[]WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
return nil
}
// Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration is an autogenerated conversion function.
func Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in, out, s)
}
func autoConvert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in *WebhookConnectionInfo, out *apiserver.WebhookConnectionInfo, s conversion.Scope) error {
out.Type = in.Type
out.KubeConfigFile = (*string)(unsafe.Pointer(in.KubeConfigFile))
return nil
}
// Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo is an autogenerated conversion function.
func Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in *WebhookConnectionInfo, out *apiserver.WebhookConnectionInfo, s conversion.Scope) error {
return autoConvert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in, out, s)
}
func autoConvert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in *apiserver.WebhookConnectionInfo, out *WebhookConnectionInfo, s conversion.Scope) error {
out.Type = in.Type
out.KubeConfigFile = (*string)(unsafe.Pointer(in.KubeConfigFile))
return nil
}
// Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo is an autogenerated conversion function.
func Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in *apiserver.WebhookConnectionInfo, out *WebhookConnectionInfo, s conversion.Scope) error {
return autoConvert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in, out, s)
}
func autoConvert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
out.Expression = in.Expression
return nil
}
// Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition is an autogenerated conversion function.
func Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
return autoConvert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in, out, s)
}
func autoConvert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
out.Expression = in.Expression
return nil
}
// Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition is an autogenerated conversion function.
func Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
return autoConvert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in, out, s)
}

View File

@@ -78,6 +78,147 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthenticationConfiguration) DeepCopyInto(out *AuthenticationConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.JWT != nil {
in, out := &in.JWT, &out.JWT
*out = make([]JWTAuthenticator, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationConfiguration.
func (in *AuthenticationConfiguration) DeepCopy() *AuthenticationConfiguration {
if in == nil {
return nil
}
out := new(AuthenticationConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AuthenticationConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthorizationConfiguration) DeepCopyInto(out *AuthorizationConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]AuthorizerConfiguration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationConfiguration.
func (in *AuthorizationConfiguration) DeepCopy() *AuthorizationConfiguration {
if in == nil {
return nil
}
out := new(AuthorizationConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AuthorizationConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthorizerConfiguration) DeepCopyInto(out *AuthorizerConfiguration) {
*out = *in
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(WebhookConfiguration)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizerConfiguration.
func (in *AuthorizerConfiguration) DeepCopy() *AuthorizerConfiguration {
if in == nil {
return nil
}
out := new(AuthorizerConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
*out = *in
in.Username.DeepCopyInto(&out.Username)
in.Groups.DeepCopyInto(&out.Groups)
out.UID = in.UID
if in.Extra != nil {
in, out := &in.Extra, &out.Extra
*out = make([]ExtraMapping, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimMappings.
func (in *ClaimMappings) DeepCopy() *ClaimMappings {
if in == nil {
return nil
}
out := new(ClaimMappings)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimOrExpression) DeepCopyInto(out *ClaimOrExpression) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimOrExpression.
func (in *ClaimOrExpression) DeepCopy() *ClaimOrExpression {
if in == nil {
return nil
}
out := new(ClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimValidationRule) DeepCopyInto(out *ClaimValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimValidationRule.
func (in *ClaimValidationRule) DeepCopy() *ClaimValidationRule {
if in == nil {
return nil
}
out := new(ClaimValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Connection) DeepCopyInto(out *Connection) {
*out = *in
@@ -148,6 +289,92 @@ func (in *EgressSelectorConfiguration) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtraMapping) DeepCopyInto(out *ExtraMapping) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraMapping.
func (in *ExtraMapping) DeepCopy() *ExtraMapping {
if in == nil {
return nil
}
out := new(ExtraMapping)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Issuer) DeepCopyInto(out *Issuer) {
*out = *in
if in.Audiences != nil {
in, out := &in.Audiences, &out.Audiences
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Issuer.
func (in *Issuer) DeepCopy() *Issuer {
if in == nil {
return nil
}
out := new(Issuer)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
*out = *in
in.Issuer.DeepCopyInto(&out.Issuer)
if in.ClaimValidationRules != nil {
in, out := &in.ClaimValidationRules, &out.ClaimValidationRules
*out = make([]ClaimValidationRule, len(*in))
copy(*out, *in)
}
in.ClaimMappings.DeepCopyInto(&out.ClaimMappings)
if in.UserValidationRules != nil {
in, out := &in.UserValidationRules, &out.UserValidationRules
*out = make([]UserValidationRule, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTAuthenticator.
func (in *JWTAuthenticator) DeepCopy() *JWTAuthenticator {
if in == nil {
return nil
}
out := new(JWTAuthenticator)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PrefixedClaimOrExpression) DeepCopyInto(out *PrefixedClaimOrExpression) {
*out = *in
if in.Prefix != nil {
in, out := &in.Prefix, &out.Prefix
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrefixedClaimOrExpression.
func (in *PrefixedClaimOrExpression) DeepCopy() *PrefixedClaimOrExpression {
if in == nil {
return nil
}
out := new(PrefixedClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TCPTransport) DeepCopyInto(out *TCPTransport) {
*out = *in
@@ -189,16 +416,7 @@ func (in *TLSConfig) DeepCopy() *TLSConfig {
func (in *TracingConfiguration) DeepCopyInto(out *TracingConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Endpoint != nil {
in, out := &in.Endpoint, &out.Endpoint
*out = new(string)
**out = **in
}
if in.SamplingRatePerMillion != nil {
in, out := &in.SamplingRatePerMillion, &out.SamplingRatePerMillion
*out = new(int32)
**out = **in
}
in.TracingConfiguration.DeepCopyInto(&out.TracingConfiguration)
return
}
@@ -261,3 +479,81 @@ func (in *UDSTransport) DeepCopy() *UDSTransport {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserValidationRule) DeepCopyInto(out *UserValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserValidationRule.
func (in *UserValidationRule) DeepCopy() *UserValidationRule {
if in == nil {
return nil
}
out := new(UserValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in
out.AuthorizedTTL = in.AuthorizedTTL
out.UnauthorizedTTL = in.UnauthorizedTTL
out.Timeout = in.Timeout
in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
if in.MatchConditions != nil {
in, out := &in.MatchConditions, &out.MatchConditions
*out = make([]WebhookMatchCondition, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfiguration.
func (in *WebhookConfiguration) DeepCopy() *WebhookConfiguration {
if in == nil {
return nil
}
out := new(WebhookConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConnectionInfo) DeepCopyInto(out *WebhookConnectionInfo) {
*out = *in
if in.KubeConfigFile != nil {
in, out := &in.KubeConfigFile, &out.KubeConfigFile
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConnectionInfo.
func (in *WebhookConnectionInfo) DeepCopy() *WebhookConnectionInfo {
if in == nil {
return nil
}
out := new(WebhookConnectionInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookMatchCondition) DeepCopyInto(out *WebhookMatchCondition) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookMatchCondition.
func (in *WebhookMatchCondition) DeepCopy() *WebhookMatchCondition {
if in == nil {
return nil
}
out := new(WebhookMatchCondition)
in.DeepCopyInto(out)
return out
}

View File

@@ -29,5 +29,15 @@ import (
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&AuthorizationConfiguration{}, func(obj interface{}) { SetObjectDefaults_AuthorizationConfiguration(obj.(*AuthorizationConfiguration)) })
return nil
}
func SetObjectDefaults_AuthorizationConfiguration(in *AuthorizationConfiguration) {
for i := range in.Authorizers {
a := &in.Authorizers[i]
if a.Webhook != nil {
SetDefaults_WebhookConfiguration(a.Webhook)
}
}
}

View File

@@ -23,10 +23,14 @@ import (
)
const GroupName = "apiserver.k8s.io"
const ConfigGroupName = "apiserver.config.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
// ConfigSchemeGroupVersion is group version used to register these objects
var ConfigSchemeGroupVersion = schema.GroupVersion{Group: ConfigGroupName, Version: "v1beta1"}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
@@ -47,6 +51,9 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&EgressSelectorConfiguration{},
)
scheme.AddKnownTypes(ConfigSchemeGroupVersion,
&TracingConfiguration{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -18,6 +18,7 @@ package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
tracingapi "k8s.io/component-base/tracing/api/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -118,3 +119,13 @@ type TLSConfig struct {
// +optional
ClientCert string `json:"clientCert,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TracingConfiguration provides versioned configuration for tracing clients.
type TracingConfiguration struct {
metav1.TypeMeta `json:",inline"`
// Embed the component config tracing configuration struct
tracingapi.TracingConfiguration `json:",inline"`
}

View File

@@ -81,6 +81,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*TracingConfiguration)(nil), (*apiserver.TracingConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_TracingConfiguration_To_apiserver_TracingConfiguration(a.(*TracingConfiguration), b.(*apiserver.TracingConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*apiserver.TracingConfiguration)(nil), (*TracingConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_apiserver_TracingConfiguration_To_v1beta1_TracingConfiguration(a.(*apiserver.TracingConfiguration), b.(*TracingConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Transport)(nil), (*apiserver.Transport)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Transport_To_apiserver_Transport(a.(*Transport), b.(*apiserver.Transport), scope)
}); err != nil {
@@ -238,6 +248,26 @@ func Convert_apiserver_TLSConfig_To_v1beta1_TLSConfig(in *apiserver.TLSConfig, o
return autoConvert_apiserver_TLSConfig_To_v1beta1_TLSConfig(in, out, s)
}
func autoConvert_v1beta1_TracingConfiguration_To_apiserver_TracingConfiguration(in *TracingConfiguration, out *apiserver.TracingConfiguration, s conversion.Scope) error {
out.TracingConfiguration = in.TracingConfiguration
return nil
}
// Convert_v1beta1_TracingConfiguration_To_apiserver_TracingConfiguration is an autogenerated conversion function.
func Convert_v1beta1_TracingConfiguration_To_apiserver_TracingConfiguration(in *TracingConfiguration, out *apiserver.TracingConfiguration, s conversion.Scope) error {
return autoConvert_v1beta1_TracingConfiguration_To_apiserver_TracingConfiguration(in, out, s)
}
func autoConvert_apiserver_TracingConfiguration_To_v1beta1_TracingConfiguration(in *apiserver.TracingConfiguration, out *TracingConfiguration, s conversion.Scope) error {
out.TracingConfiguration = in.TracingConfiguration
return nil
}
// Convert_apiserver_TracingConfiguration_To_v1beta1_TracingConfiguration is an autogenerated conversion function.
func Convert_apiserver_TracingConfiguration_To_v1beta1_TracingConfiguration(in *apiserver.TracingConfiguration, out *TracingConfiguration, s conversion.Scope) error {
return autoConvert_apiserver_TracingConfiguration_To_v1beta1_TracingConfiguration(in, out, s)
}
func autoConvert_v1beta1_Transport_To_apiserver_Transport(in *Transport, out *apiserver.Transport, s conversion.Scope) error {
out.TCP = (*apiserver.TCPTransport)(unsafe.Pointer(in.TCP))
out.UDS = (*apiserver.UDSTransport)(unsafe.Pointer(in.UDS))

View File

@@ -132,6 +132,32 @@ func (in *TLSConfig) DeepCopy() *TLSConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TracingConfiguration) DeepCopyInto(out *TracingConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.TracingConfiguration.DeepCopyInto(&out.TracingConfiguration)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingConfiguration.
func (in *TracingConfiguration) DeepCopy() *TracingConfiguration {
if in == nil {
return nil
}
out := new(TracingConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TracingConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Transport) DeepCopyInto(out *Transport) {
*out = *in

View File

@@ -0,0 +1,630 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"time"
v1 "k8s.io/api/authorization/v1"
"k8s.io/api/authorization/v1beta1"
"k8s.io/apimachinery/pkg/util/sets"
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
api "k8s.io/apiserver/pkg/apis/apiserver"
authenticationcel "k8s.io/apiserver/pkg/authentication/cel"
authorizationcel "k8s.io/apiserver/pkg/authorization/cel"
"k8s.io/apiserver/pkg/cel"
"k8s.io/apiserver/pkg/cel/environment"
"k8s.io/apiserver/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/util/cert"
)
const (
atLeastOneRequiredErrFmt = "at least one %s is required"
)
var (
root = field.NewPath("jwt")
)
// ValidateAuthenticationConfiguration validates a given AuthenticationConfiguration.
func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration) field.ErrorList {
var allErrs field.ErrorList
// This stricter validation is solely based on what the current implementation supports.
// TODO(aramase): when StructuredAuthenticationConfiguration feature gate is added and wired up,
// relax this check to allow 0 authenticators. This will allow us to support the case where
// API server is initially configured with no authenticators and then authenticators are added
// later via dynamic config.
if len(c.JWT) == 0 {
allErrs = append(allErrs, field.Required(root, fmt.Sprintf(atLeastOneRequiredErrFmt, root)))
return allErrs
}
// This stricter validation is because the --oidc-* flag option is singular.
// TODO(aramase): when StructuredAuthenticationConfiguration feature gate is added and wired up,
// remove the 1 authenticator limit check and add set the limit to 64.
if len(c.JWT) > 1 {
allErrs = append(allErrs, field.TooMany(root, len(c.JWT), 1))
return allErrs
}
// TODO(aramase): right now we only support a single JWT authenticator as
// this is wired to the --oidc-* flags. When StructuredAuthenticationConfiguration
// feature gate is added and wired up, we will remove the 1 authenticator limit
// check and add validation for duplicate issuers.
for i, a := range c.JWT {
fldPath := root.Index(i)
_, errs := validateJWTAuthenticator(a, fldPath, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration))
allErrs = append(allErrs, errs...)
}
return allErrs
}
// CompileAndValidateJWTAuthenticator validates a given JWTAuthenticator and returns a CELMapper with the compiled
// CEL expressions for claim mappings and validation rules.
// This is exported for use in oidc package.
func CompileAndValidateJWTAuthenticator(authenticator api.JWTAuthenticator) (authenticationcel.CELMapper, field.ErrorList) {
return validateJWTAuthenticator(authenticator, nil, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration))
}
func validateJWTAuthenticator(authenticator api.JWTAuthenticator, fldPath *field.Path, structuredAuthnFeatureEnabled bool) (authenticationcel.CELMapper, field.ErrorList) {
var allErrs field.ErrorList
compiler := authenticationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
mapper := &authenticationcel.CELMapper{}
allErrs = append(allErrs, validateIssuer(authenticator.Issuer, fldPath.Child("issuer"))...)
allErrs = append(allErrs, validateClaimValidationRules(compiler, mapper, authenticator.ClaimValidationRules, fldPath.Child("claimValidationRules"), structuredAuthnFeatureEnabled)...)
allErrs = append(allErrs, validateClaimMappings(compiler, mapper, authenticator.ClaimMappings, fldPath.Child("claimMappings"), structuredAuthnFeatureEnabled)...)
allErrs = append(allErrs, validateUserValidationRules(compiler, mapper, authenticator.UserValidationRules, fldPath.Child("userValidationRules"), structuredAuthnFeatureEnabled)...)
return *mapper, allErrs
}
func validateIssuer(issuer api.Issuer, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
allErrs = append(allErrs, validateURL(issuer.URL, fldPath.Child("url"))...)
allErrs = append(allErrs, validateAudiences(issuer.Audiences, fldPath.Child("audiences"))...)
allErrs = append(allErrs, validateCertificateAuthority(issuer.CertificateAuthority, fldPath.Child("certificateAuthority"))...)
return allErrs
}
func validateURL(issuerURL string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if len(issuerURL) == 0 {
allErrs = append(allErrs, field.Required(fldPath, "URL is required"))
return allErrs
}
u, err := url.Parse(issuerURL)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, err.Error()))
return allErrs
}
if u.Scheme != "https" {
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, "URL scheme must be https"))
}
if u.User != nil {
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, "URL must not contain a username or password"))
}
if len(u.RawQuery) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, "URL must not contain a query"))
}
if len(u.Fragment) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, "URL must not contain a fragment"))
}
return allErrs
}
func validateAudiences(audiences []string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if len(audiences) == 0 {
allErrs = append(allErrs, field.Required(fldPath, fmt.Sprintf(atLeastOneRequiredErrFmt, fldPath)))
return allErrs
}
// This stricter validation is because the --oidc-client-id flag option is singular.
// This will be removed when we support multiple audiences with the StructuredAuthenticationConfiguration feature gate.
if len(audiences) > 1 {
allErrs = append(allErrs, field.TooMany(fldPath, len(audiences), 1))
return allErrs
}
for i, audience := range audiences {
fldPath := fldPath.Index(i)
if len(audience) == 0 {
allErrs = append(allErrs, field.Required(fldPath, "audience can't be empty"))
}
}
return allErrs
}
func validateCertificateAuthority(certificateAuthority string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if len(certificateAuthority) == 0 {
return allErrs
}
_, err := cert.NewPoolFromBytes([]byte(certificateAuthority))
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "<omitted>", err.Error()))
}
return allErrs
}
func validateClaimValidationRules(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, rules []api.ClaimValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
var allErrs field.ErrorList
seenClaims := sets.NewString()
seenExpressions := sets.NewString()
var compilationResults []authenticationcel.CompilationResult
for i, rule := range rules {
fldPath := fldPath.Index(i)
if len(rule.Expression) > 0 && !structuredAuthnFeatureEnabled {
allErrs = append(allErrs, field.Invalid(fldPath.Child("expression"), rule.Expression, "expression is not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
switch {
case len(rule.Claim) > 0 && len(rule.Expression) > 0:
allErrs = append(allErrs, field.Invalid(fldPath, rule.Claim, "claim and expression can't both be set"))
case len(rule.Claim) == 0 && len(rule.Expression) == 0:
allErrs = append(allErrs, field.Required(fldPath, "claim or expression is required"))
case len(rule.Claim) > 0:
if len(rule.Message) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("message"), rule.Message, "message can't be set when claim is set"))
}
if seenClaims.Has(rule.Claim) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("claim"), rule.Claim))
}
seenClaims.Insert(rule.Claim)
case len(rule.Expression) > 0:
if len(rule.RequiredValue) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("requiredValue"), rule.RequiredValue, "requiredValue can't be set when expression is set"))
}
if seenExpressions.Has(rule.Expression) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("expression"), rule.Expression))
continue
}
seenExpressions.Insert(rule.Expression)
compilationResult, err := compileClaimsCELExpression(compiler, &authenticationcel.ClaimValidationCondition{
Expression: rule.Expression,
}, fldPath.Child("expression"))
if err != nil {
allErrs = append(allErrs, err)
continue
}
if compilationResult != nil {
compilationResults = append(compilationResults, *compilationResult)
}
}
}
if structuredAuthnFeatureEnabled && len(compilationResults) > 0 {
celMapper.ClaimValidationRules = authenticationcel.NewClaimsMapper(compilationResults)
}
return allErrs
}
func validateClaimMappings(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, m api.ClaimMappings, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
var allErrs field.ErrorList
if !structuredAuthnFeatureEnabled {
if len(m.Username.Expression) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("username").Child("expression"), m.Username.Expression, "expression is not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
if len(m.Groups.Expression) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("groups").Child("expression"), m.Groups.Expression, "expression is not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
if len(m.UID.Claim) > 0 || len(m.UID.Expression) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("uid"), "", "uid claim mapping is not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
if len(m.Extra) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("extra"), "", "extra claim mapping is not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
}
compilationResult, err := validatePrefixClaimOrExpression(compiler, m.Username, fldPath.Child("username"), true, structuredAuthnFeatureEnabled)
if err != nil {
allErrs = append(allErrs, err...)
} else if compilationResult != nil && structuredAuthnFeatureEnabled {
celMapper.Username = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
}
compilationResult, err = validatePrefixClaimOrExpression(compiler, m.Groups, fldPath.Child("groups"), false, structuredAuthnFeatureEnabled)
if err != nil {
allErrs = append(allErrs, err...)
} else if compilationResult != nil && structuredAuthnFeatureEnabled {
celMapper.Groups = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
}
switch {
case len(m.UID.Claim) > 0 && len(m.UID.Expression) > 0:
allErrs = append(allErrs, field.Invalid(fldPath.Child("uid"), "", "claim and expression can't both be set"))
case len(m.UID.Expression) > 0:
compilationResult, err := compileClaimsCELExpression(compiler, &authenticationcel.ClaimMappingExpression{
Expression: m.UID.Expression,
}, fldPath.Child("uid").Child("expression"))
if err != nil {
allErrs = append(allErrs, err)
} else if structuredAuthnFeatureEnabled && compilationResult != nil {
celMapper.UID = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
}
}
var extraCompilationResults []authenticationcel.CompilationResult
seenExtraKeys := sets.NewString()
for i, mapping := range m.Extra {
fldPath := fldPath.Child("extra").Index(i)
// Key should be namespaced to the authenticator or authenticator/authorizer pair making use of them.
// For instance: "example.org/foo" instead of "foo".
// xref: https://github.com/kubernetes/kubernetes/blob/3825e206cb162a7ad7431a5bdf6a065ae8422cf7/staging/src/k8s.io/apiserver/pkg/authentication/user/user.go#L31-L41
// IsDomainPrefixedPath checks for non-empty key and that the key is prefixed with a domain name.
allErrs = append(allErrs, utilvalidation.IsDomainPrefixedPath(fldPath.Child("key"), mapping.Key)...)
if mapping.Key != strings.ToLower(mapping.Key) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("key"), mapping.Key, "key must be lowercase"))
}
if seenExtraKeys.Has(mapping.Key) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("key"), mapping.Key))
continue
}
seenExtraKeys.Insert(mapping.Key)
if len(mapping.ValueExpression) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("valueExpression"), "valueExpression is required"))
continue
}
compilationResult, err := compileClaimsCELExpression(compiler, &authenticationcel.ExtraMappingExpression{
Key: mapping.Key,
Expression: mapping.ValueExpression,
}, fldPath.Child("valueExpression"))
if err != nil {
allErrs = append(allErrs, err)
continue
}
if compilationResult != nil {
extraCompilationResults = append(extraCompilationResults, *compilationResult)
}
}
if structuredAuthnFeatureEnabled && len(extraCompilationResults) > 0 {
celMapper.Extra = authenticationcel.NewClaimsMapper(extraCompilationResults)
}
return allErrs
}
func validatePrefixClaimOrExpression(compiler authenticationcel.Compiler, mapping api.PrefixedClaimOrExpression, fldPath *field.Path, claimOrExpressionRequired, structuredAuthnFeatureEnabled bool) (*authenticationcel.CompilationResult, field.ErrorList) {
var allErrs field.ErrorList
var compilationResult *authenticationcel.CompilationResult
switch {
case len(mapping.Expression) > 0 && len(mapping.Claim) > 0:
allErrs = append(allErrs, field.Invalid(fldPath, "", "claim and expression can't both be set"))
case len(mapping.Expression) == 0 && len(mapping.Claim) == 0 && claimOrExpressionRequired:
allErrs = append(allErrs, field.Required(fldPath, "claim or expression is required"))
case len(mapping.Expression) > 0:
var err *field.Error
if mapping.Prefix != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("prefix"), *mapping.Prefix, "prefix can't be set when expression is set"))
}
compilationResult, err = compileClaimsCELExpression(compiler, &authenticationcel.ClaimMappingExpression{
Expression: mapping.Expression,
}, fldPath.Child("expression"))
if err != nil {
allErrs = append(allErrs, err)
}
case len(mapping.Claim) > 0:
if mapping.Prefix == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("prefix"), "prefix is required when claim is set. It can be set to an empty string to disable prefixing"))
}
}
return compilationResult, allErrs
}
func validateUserValidationRules(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, rules []api.UserValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
var allErrs field.ErrorList
var compilationResults []authenticationcel.CompilationResult
if len(rules) > 0 && !structuredAuthnFeatureEnabled {
allErrs = append(allErrs, field.Invalid(fldPath, "", "user validation rules are not supported when StructuredAuthenticationConfiguration feature gate is disabled"))
}
seenExpressions := sets.NewString()
for i, rule := range rules {
fldPath := fldPath.Index(i)
if len(rule.Expression) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("expression"), "expression is required"))
continue
}
if seenExpressions.Has(rule.Expression) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("expression"), rule.Expression))
continue
}
seenExpressions.Insert(rule.Expression)
compilationResult, err := compileUserCELExpression(compiler, &authenticationcel.UserValidationCondition{
Expression: rule.Expression,
Message: rule.Message,
}, fldPath.Child("expression"))
if err != nil {
allErrs = append(allErrs, err)
continue
}
if compilationResult != nil {
compilationResults = append(compilationResults, *compilationResult)
}
}
if structuredAuthnFeatureEnabled && len(compilationResults) > 0 {
celMapper.UserValidationRules = authenticationcel.NewUserMapper(compilationResults)
}
return allErrs
}
func compileClaimsCELExpression(compiler authenticationcel.Compiler, expression authenticationcel.ExpressionAccessor, fldPath *field.Path) (*authenticationcel.CompilationResult, *field.Error) {
compilationResult, err := compiler.CompileClaimsExpression(expression)
if err != nil {
return nil, convertCELErrorToValidationError(fldPath, expression, err)
}
return &compilationResult, nil
}
func compileUserCELExpression(compiler authenticationcel.Compiler, expression authenticationcel.ExpressionAccessor, fldPath *field.Path) (*authenticationcel.CompilationResult, *field.Error) {
compilationResult, err := compiler.CompileUserExpression(expression)
if err != nil {
return nil, convertCELErrorToValidationError(fldPath, expression, err)
}
return &compilationResult, nil
}
// ValidateAuthorizationConfiguration validates a given AuthorizationConfiguration.
func ValidateAuthorizationConfiguration(fldPath *field.Path, c *api.AuthorizationConfiguration, knownTypes sets.String, repeatableTypes sets.String) field.ErrorList {
allErrs := field.ErrorList{}
if len(c.Authorizers) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("authorizers"), "at least one authorization mode must be defined"))
}
seenAuthorizerTypes := sets.NewString()
seenAuthorizerNames := sets.NewString()
for i, a := range c.Authorizers {
fldPath := fldPath.Child("authorizers").Index(i)
aType := string(a.Type)
if aType == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("type"), ""))
continue
}
if !knownTypes.Has(aType) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), aType, knownTypes.List()))
continue
}
if seenAuthorizerTypes.Has(aType) && !repeatableTypes.Has(aType) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("type"), aType))
continue
}
seenAuthorizerTypes.Insert(aType)
if len(a.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
} else if seenAuthorizerNames.Has(a.Name) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("name"), a.Name))
} else if errs := utilvalidation.IsDNS1123Subdomain(a.Name); len(errs) != 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), a.Name, fmt.Sprintf("authorizer name is invalid: %s", strings.Join(errs, ", "))))
}
seenAuthorizerNames.Insert(a.Name)
switch a.Type {
case api.TypeWebhook:
if a.Webhook == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("webhook"), "required when type=Webhook"))
continue
}
allErrs = append(allErrs, ValidateWebhookConfiguration(fldPath, a.Webhook)...)
default:
if a.Webhook != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("webhook"), "non-null", "may only be specified when type=Webhook"))
}
}
}
return allErrs
}
func ValidateWebhookConfiguration(fldPath *field.Path, c *api.WebhookConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
if c.Timeout.Duration == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("timeout"), ""))
} else if c.Timeout.Duration > 30*time.Second || c.Timeout.Duration < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("timeout"), c.Timeout.Duration.String(), "must be > 0s and <= 30s"))
}
if c.AuthorizedTTL.Duration == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("authorizedTTL"), ""))
} else if c.AuthorizedTTL.Duration < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("authorizedTTL"), c.AuthorizedTTL.Duration.String(), "must be > 0s"))
}
if c.UnauthorizedTTL.Duration == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("unauthorizedTTL"), ""))
} else if c.UnauthorizedTTL.Duration < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("unauthorizedTTL"), c.UnauthorizedTTL.Duration.String(), "must be > 0s"))
}
switch c.SubjectAccessReviewVersion {
case "":
allErrs = append(allErrs, field.Required(fldPath.Child("subjectAccessReviewVersion"), ""))
case "v1":
_ = &v1.SubjectAccessReview{}
case "v1beta1":
_ = &v1beta1.SubjectAccessReview{}
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("subjectAccessReviewVersion"), c.SubjectAccessReviewVersion, []string{"v1", "v1beta1"}))
}
switch c.MatchConditionSubjectAccessReviewVersion {
case "":
if len(c.MatchConditions) > 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("matchConditionSubjectAccessReviewVersion"), "required if match conditions are specified"))
}
case "v1":
_ = &v1.SubjectAccessReview{}
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("matchConditionSubjectAccessReviewVersion"), c.MatchConditionSubjectAccessReviewVersion, []string{"v1"}))
}
switch c.FailurePolicy {
case "":
allErrs = append(allErrs, field.Required(fldPath.Child("failurePolicy"), ""))
case api.FailurePolicyNoOpinion, api.FailurePolicyDeny:
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("failurePolicy"), c.FailurePolicy, []string{"NoOpinion", "Deny"}))
}
switch c.ConnectionInfo.Type {
case "":
allErrs = append(allErrs, field.Required(fldPath.Child("connectionInfo", "type"), ""))
case api.AuthorizationWebhookConnectionInfoTypeInCluster:
if c.ConnectionInfo.KubeConfigFile != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "can only be set when type=KubeConfigFile"))
}
case api.AuthorizationWebhookConnectionInfoTypeKubeConfigFile:
if c.ConnectionInfo.KubeConfigFile == nil || *c.ConnectionInfo.KubeConfigFile == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("connectionInfo", "kubeConfigFile"), ""))
} else if !filepath.IsAbs(*c.ConnectionInfo.KubeConfigFile) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "must be an absolute path"))
} else if info, err := os.Stat(*c.ConnectionInfo.KubeConfigFile); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, fmt.Sprintf("error loading file: %v", err)))
} else if !info.Mode().IsRegular() {
allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "must be a regular file"))
}
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("connectionInfo", "type"), c.ConnectionInfo, []string{api.AuthorizationWebhookConnectionInfoTypeInCluster, api.AuthorizationWebhookConnectionInfoTypeKubeConfigFile}))
}
_, errs := compileMatchConditions(c.MatchConditions, fldPath, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration))
allErrs = append(allErrs, errs...)
return allErrs
}
// ValidateAndCompileMatchConditions validates a given webhook's matchConditions.
// This is exported for use in authz package.
func ValidateAndCompileMatchConditions(matchConditions []api.WebhookMatchCondition) (*authorizationcel.CELMatcher, field.ErrorList) {
return compileMatchConditions(matchConditions, nil, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration))
}
func compileMatchConditions(matchConditions []api.WebhookMatchCondition, fldPath *field.Path, structuredAuthzFeatureEnabled bool) (*authorizationcel.CELMatcher, field.ErrorList) {
var allErrs field.ErrorList
// should fail when match conditions are used without feature enabled
if len(matchConditions) > 0 && !structuredAuthzFeatureEnabled {
allErrs = append(allErrs, field.Invalid(fldPath.Child("matchConditions"), "", "matchConditions are not supported when StructuredAuthorizationConfiguration feature gate is disabled"))
}
if len(matchConditions) > 64 {
allErrs = append(allErrs, field.TooMany(fldPath.Child("matchConditions"), len(matchConditions), 64))
return nil, allErrs
}
compiler := authorizationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
seenExpressions := sets.NewString()
var compilationResults []authorizationcel.CompilationResult
for i, condition := range matchConditions {
fldPath := fldPath.Child("matchConditions").Index(i).Child("expression")
if len(strings.TrimSpace(condition.Expression)) == 0 {
allErrs = append(allErrs, field.Required(fldPath, ""))
continue
}
if seenExpressions.Has(condition.Expression) {
allErrs = append(allErrs, field.Duplicate(fldPath, condition.Expression))
continue
}
seenExpressions.Insert(condition.Expression)
compilationResult, err := compileMatchConditionsExpression(fldPath, compiler, condition.Expression)
if err != nil {
allErrs = append(allErrs, err)
continue
}
compilationResults = append(compilationResults, compilationResult)
}
if len(compilationResults) == 0 {
return nil, allErrs
}
return &authorizationcel.CELMatcher{
CompilationResults: compilationResults,
}, allErrs
}
func compileMatchConditionsExpression(fldPath *field.Path, compiler authorizationcel.Compiler, expression string) (authorizationcel.CompilationResult, *field.Error) {
authzExpression := &authorizationcel.SubjectAccessReviewMatchCondition{
Expression: expression,
}
compilationResult, err := compiler.CompileCELExpression(authzExpression)
if err != nil {
return compilationResult, convertCELErrorToValidationError(fldPath, authzExpression, err)
}
return compilationResult, nil
}
func convertCELErrorToValidationError(fldPath *field.Path, expression authorizationcel.ExpressionAccessor, err error) *field.Error {
var celErr *cel.Error
if errors.As(err, &celErr) {
switch celErr.Type {
case cel.ErrorTypeRequired:
return field.Required(fldPath, celErr.Detail)
case cel.ErrorTypeInvalid:
return field.Invalid(fldPath, expression.GetExpression(), celErr.Detail)
default:
return field.InternalError(fldPath, celErr)
}
}
return field.InternalError(fldPath, fmt.Errorf("error is not cel error: %w", err))
}

View File

@@ -78,6 +78,147 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthenticationConfiguration) DeepCopyInto(out *AuthenticationConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.JWT != nil {
in, out := &in.JWT, &out.JWT
*out = make([]JWTAuthenticator, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationConfiguration.
func (in *AuthenticationConfiguration) DeepCopy() *AuthenticationConfiguration {
if in == nil {
return nil
}
out := new(AuthenticationConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AuthenticationConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthorizationConfiguration) DeepCopyInto(out *AuthorizationConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Authorizers != nil {
in, out := &in.Authorizers, &out.Authorizers
*out = make([]AuthorizerConfiguration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationConfiguration.
func (in *AuthorizationConfiguration) DeepCopy() *AuthorizationConfiguration {
if in == nil {
return nil
}
out := new(AuthorizationConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AuthorizationConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthorizerConfiguration) DeepCopyInto(out *AuthorizerConfiguration) {
*out = *in
if in.Webhook != nil {
in, out := &in.Webhook, &out.Webhook
*out = new(WebhookConfiguration)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizerConfiguration.
func (in *AuthorizerConfiguration) DeepCopy() *AuthorizerConfiguration {
if in == nil {
return nil
}
out := new(AuthorizerConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
*out = *in
in.Username.DeepCopyInto(&out.Username)
in.Groups.DeepCopyInto(&out.Groups)
out.UID = in.UID
if in.Extra != nil {
in, out := &in.Extra, &out.Extra
*out = make([]ExtraMapping, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimMappings.
func (in *ClaimMappings) DeepCopy() *ClaimMappings {
if in == nil {
return nil
}
out := new(ClaimMappings)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimOrExpression) DeepCopyInto(out *ClaimOrExpression) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimOrExpression.
func (in *ClaimOrExpression) DeepCopy() *ClaimOrExpression {
if in == nil {
return nil
}
out := new(ClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClaimValidationRule) DeepCopyInto(out *ClaimValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimValidationRule.
func (in *ClaimValidationRule) DeepCopy() *ClaimValidationRule {
if in == nil {
return nil
}
out := new(ClaimValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Connection) DeepCopyInto(out *Connection) {
*out = *in
@@ -148,6 +289,92 @@ func (in *EgressSelectorConfiguration) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtraMapping) DeepCopyInto(out *ExtraMapping) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraMapping.
func (in *ExtraMapping) DeepCopy() *ExtraMapping {
if in == nil {
return nil
}
out := new(ExtraMapping)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Issuer) DeepCopyInto(out *Issuer) {
*out = *in
if in.Audiences != nil {
in, out := &in.Audiences, &out.Audiences
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Issuer.
func (in *Issuer) DeepCopy() *Issuer {
if in == nil {
return nil
}
out := new(Issuer)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JWTAuthenticator) DeepCopyInto(out *JWTAuthenticator) {
*out = *in
in.Issuer.DeepCopyInto(&out.Issuer)
if in.ClaimValidationRules != nil {
in, out := &in.ClaimValidationRules, &out.ClaimValidationRules
*out = make([]ClaimValidationRule, len(*in))
copy(*out, *in)
}
in.ClaimMappings.DeepCopyInto(&out.ClaimMappings)
if in.UserValidationRules != nil {
in, out := &in.UserValidationRules, &out.UserValidationRules
*out = make([]UserValidationRule, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTAuthenticator.
func (in *JWTAuthenticator) DeepCopy() *JWTAuthenticator {
if in == nil {
return nil
}
out := new(JWTAuthenticator)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PrefixedClaimOrExpression) DeepCopyInto(out *PrefixedClaimOrExpression) {
*out = *in
if in.Prefix != nil {
in, out := &in.Prefix, &out.Prefix
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrefixedClaimOrExpression.
func (in *PrefixedClaimOrExpression) DeepCopy() *PrefixedClaimOrExpression {
if in == nil {
return nil
}
out := new(PrefixedClaimOrExpression)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TCPTransport) DeepCopyInto(out *TCPTransport) {
*out = *in
@@ -189,16 +416,7 @@ func (in *TLSConfig) DeepCopy() *TLSConfig {
func (in *TracingConfiguration) DeepCopyInto(out *TracingConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Endpoint != nil {
in, out := &in.Endpoint, &out.Endpoint
*out = new(string)
**out = **in
}
if in.SamplingRatePerMillion != nil {
in, out := &in.SamplingRatePerMillion, &out.SamplingRatePerMillion
*out = new(int32)
**out = **in
}
in.TracingConfiguration.DeepCopyInto(&out.TracingConfiguration)
return
}
@@ -261,3 +479,81 @@ func (in *UDSTransport) DeepCopy() *UDSTransport {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserValidationRule) DeepCopyInto(out *UserValidationRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserValidationRule.
func (in *UserValidationRule) DeepCopy() *UserValidationRule {
if in == nil {
return nil
}
out := new(UserValidationRule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in
out.AuthorizedTTL = in.AuthorizedTTL
out.UnauthorizedTTL = in.UnauthorizedTTL
out.Timeout = in.Timeout
in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
if in.MatchConditions != nil {
in, out := &in.MatchConditions, &out.MatchConditions
*out = make([]WebhookMatchCondition, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfiguration.
func (in *WebhookConfiguration) DeepCopy() *WebhookConfiguration {
if in == nil {
return nil
}
out := new(WebhookConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConnectionInfo) DeepCopyInto(out *WebhookConnectionInfo) {
*out = *in
if in.KubeConfigFile != nil {
in, out := &in.KubeConfigFile, &out.KubeConfigFile
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConnectionInfo.
func (in *WebhookConnectionInfo) DeepCopy() *WebhookConnectionInfo {
if in == nil {
return nil
}
out := new(WebhookConnectionInfo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookMatchCondition) DeepCopyInto(out *WebhookMatchCondition) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookMatchCondition.
func (in *WebhookMatchCondition) DeepCopy() *WebhookMatchCondition {
if in == nil {
return nil
}
out := new(WebhookMatchCondition)
in.DeepCopyInto(out)
return out
}

View File

@@ -235,10 +235,10 @@ type PolicyRule struct {
Namespaces []string
// NonResourceURLs is a set of URL paths that should be audited.
// *s are allowed, but only as the full, final step in the path.
// `*`s are allowed, but only as the full, final step in the path.
// Examples:
// "/metrics" - Log requests for apiserver metrics
// "/healthz*" - Log all health checks
// `/metrics` - Log requests for apiserver metrics
// `/healthz*` - Log all health checks
// +optional
NonResourceURLs []string
@@ -269,11 +269,11 @@ type GroupResources struct {
// Resources is a list of resources this rule applies to.
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
// - `pods` matches pods.
// - `pods/log` matches the log subresource of pods.
// - `*` matches all resources and their subresources.
// - `pods/*` matches all subresources of pods.
// - `*/scale` matches all scale subresources.
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.

View File

@@ -129,11 +129,11 @@ message GroupResources {
// Resources is a list of resources this rule applies to.
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
// - `pods` matches pods.
// - `pods/log` matches the log subresource of pods.
// - `*` matches all resources and their subresources.
// - `pods/*` matches all subresources of pods.
// - `*/scale` matches all scale subresources.
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.
@@ -248,10 +248,10 @@ message PolicyRule {
repeated string namespaces = 6;
// NonResourceURLs is a set of URL paths that should be audited.
// *s are allowed, but only as the full, final step in the path.
// `*`s are allowed, but only as the full, final step in the path.
// Examples:
// "/metrics" - Log requests for apiserver metrics
// "/healthz*" - Log all health checks
// - `/metrics` - Log requests for apiserver metrics
// - `/healthz*` - Log all health checks
// +optional
repeated string nonResourceURLs = 7;

View File

@@ -229,10 +229,10 @@ type PolicyRule struct {
Namespaces []string `json:"namespaces,omitempty" protobuf:"bytes,6,rep,name=namespaces"`
// NonResourceURLs is a set of URL paths that should be audited.
// *s are allowed, but only as the full, final step in the path.
// `*`s are allowed, but only as the full, final step in the path.
// Examples:
// "/metrics" - Log requests for apiserver metrics
// "/healthz*" - Log all health checks
// - `/metrics` - Log requests for apiserver metrics
// - `/healthz*` - Log all health checks
// +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"`
@@ -263,11 +263,11 @@ type GroupResources struct {
// Resources is a list of resources this rule applies to.
//
// For example:
// 'pods' matches pods.
// 'pods/log' matches the log subresource of pods.
// '*' matches all resources and their subresources.
// 'pods/*' matches all subresources of pods.
// '*/scale' matches all scale subresources.
// - `pods` matches pods.
// - `pods/log` matches the log subresource of pods.
// - `*` matches all resources and their subresources.
// - `pods/*` matches all subresources of pods.
// - `*/scale` matches all scale subresources.
//
// If wildcard is present, the validation rule will ensure resources do not
// overlap with each other.

45
vendor/k8s.io/apiserver/pkg/apis/cel/config.go generated vendored Normal file
View File

@@ -0,0 +1,45 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cel
const (
// PerCallLimit specify the actual cost limit per CEL validation call
// current PerCallLimit gives roughly 0.1 second for each expression validation call
PerCallLimit = 1000000
// RuntimeCELCostBudget is the overall cost budget for runtime CEL validation cost per ValidatingAdmissionPolicyBinding or CustomResource
// current RuntimeCELCostBudget gives roughly 1 seconds for the validation
RuntimeCELCostBudget = 10000000
// RuntimeCELCostBudgetMatchConditions is the overall cost budget for runtime CEL validation cost on matchConditions per object with matchConditions
// this is per webhook for validatingwebhookconfigurations and mutatingwebhookconfigurations or per ValidatingAdmissionPolicyBinding
// current RuntimeCELCostBudgetMatchConditions gives roughly 1/4 seconds for the validation
RuntimeCELCostBudgetMatchConditions = 2500000
// CheckFrequency configures the number of iterations within a comprehension to evaluate
// before checking whether the function evaluation has been interrupted
CheckFrequency = 100
// MaxRequestSizeBytes is the maximum size of a request to the API server
// TODO(DangerOnTheRanger): wire in MaxRequestBodyBytes from apiserver/pkg/server/options/server_run_options.go to make this configurable
// Note that even if server_run_options.go becomes configurable in the future, this cost constant should be fixed and it should be the max allowed request size for the server
MaxRequestSizeBytes = int64(3 * 1024 * 1024)
// MaxEvaluatedMessageExpressionSizeBytes represents the largest-allowable string generated
// by a messageExpression field
MaxEvaluatedMessageExpressionSizeBytes = 5 * 1024
)

View File

@@ -24,7 +24,49 @@ import (
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// EncryptionConfiguration stores the complete configuration for encryption providers.
/*
EncryptionConfiguration stores the complete configuration for encryption providers.
It also allows the use of wildcards to specify the resources that should be encrypted.
Use '*.<group>' to encrypt all resources within a group or '*.*' to encrypt all resources.
'*.' can be used to encrypt all resource in the core group. '*.*' will encrypt all
resources, even custom resources that are added after API server start.
Use of wildcards that overlap within the same resource list or across multiple
entries are not allowed since part of the configuration would be ineffective.
Resource lists are processed in order, with earlier lists taking precedence.
Example:
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
- resources:
- events
providers:
- identity: {} # do not encrypt events even though *.* is specified below
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example
providers:
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- resources:
- '*.apps'
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
- resources:
- '*.*'
providers:
- aescbc:
keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
*/
type EncryptionConfiguration struct {
metav1.TypeMeta
// resources is a list containing resources, and their corresponding encryption providers.
@@ -33,10 +75,14 @@ type EncryptionConfiguration struct {
// ResourceConfiguration stores per resource configuration.
type ResourceConfiguration struct {
// resources is a list of kubernetes resources which have to be encrypted.
// resources is a list of kubernetes resources which have to be encrypted. The resource names are derived from `resource` or `resource.group` of the group/version/resource.
// eg: pandas.awesome.bears.example is a custom resource with 'group': awesome.bears.example, 'resource': pandas.
// Use '*.*' to encrypt all resources and '*.<group>' to encrypt all resources in a specific group.
// eg: '*.awesome.bears.example' will encrypt all resources in the group 'awesome.bears.example'.
// eg: '*.' will encrypt all resources in the core group (such as pods, configmaps, etc).
Resources []string
// providers is a list of transformers to be used for reading and writing the resources to disk.
// eg: aesgcm, aescbc, secretbox, identity.
// eg: aesgcm, aescbc, secretbox, identity, kms.
Providers []ProviderConfiguration
}
@@ -92,7 +138,7 @@ type KMSConfiguration struct {
// name is the name of the KMS plugin to be used.
Name string
// cachesize is the maximum number of secrets which are cached in memory. The default value is 1000.
// Set to a negative value to disable caching.
// Set to a negative value to disable caching. This field is only allowed for KMS v1 providers.
// +optional
CacheSize *int32
// endpoint is the gRPC server listening address, for example "unix:///var/run/kms-provider.sock".

View File

@@ -39,11 +39,12 @@ func SetDefaults_KMSConfiguration(obj *KMSConfiguration) {
obj.Timeout = defaultTimeout
}
if obj.CacheSize == nil {
obj.CacheSize = &defaultCacheSize
}
if obj.APIVersion == "" {
obj.APIVersion = defaultAPIVersion
}
// cacheSize is relevant only for kms v1
if obj.CacheSize == nil && obj.APIVersion == "v1" {
obj.CacheSize = &defaultCacheSize
}
}

View File

@@ -24,7 +24,49 @@ import (
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// EncryptionConfiguration stores the complete configuration for encryption providers.
/*
EncryptionConfiguration stores the complete configuration for encryption providers.
It also allows the use of wildcards to specify the resources that should be encrypted.
Use '*.<group>' to encrypt all resources within a group or '*.*' to encrypt all resources.
'*.' can be used to encrypt all resource in the core group. '*.*' will encrypt all
resources, even custom resources that are added after API server start.
Use of wildcards that overlap within the same resource list or across multiple
entries are not allowed since part of the configuration would be ineffective.
Resource lists are processed in order, with earlier lists taking precedence.
Example:
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
- resources:
- events
providers:
- identity: {} # do not encrypt events even though *.* is specified below
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example
providers:
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- resources:
- '*.apps'
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
- resources:
- '*.*'
providers:
- aescbc:
keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
*/
type EncryptionConfiguration struct {
metav1.TypeMeta
// resources is a list containing resources, and their corresponding encryption providers.
@@ -33,10 +75,14 @@ type EncryptionConfiguration struct {
// ResourceConfiguration stores per resource configuration.
type ResourceConfiguration struct {
// resources is a list of kubernetes resources which have to be encrypted.
// resources is a list of kubernetes resources which have to be encrypted. The resource names are derived from `resource` or `resource.group` of the group/version/resource.
// eg: pandas.awesome.bears.example is a custom resource with 'group': awesome.bears.example, 'resource': pandas.
// Use '*.*' to encrypt all resources and '*.<group>' to encrypt all resources in a specific group.
// eg: '*.awesome.bears.example' will encrypt all resources in the group 'awesome.bears.example'.
// eg: '*.' will encrypt all resources in the core group (such as pods, configmaps, etc).
Resources []string `json:"resources"`
// providers is a list of transformers to be used for reading and writing the resources to disk.
// eg: aesgcm, aescbc, secretbox, identity.
// eg: aesgcm, aescbc, secretbox, identity, kms.
Providers []ProviderConfiguration `json:"providers"`
}
@@ -92,7 +138,7 @@ type KMSConfiguration struct {
// name is the name of the KMS plugin to be used.
Name string `json:"name"`
// cachesize is the maximum number of secrets which are cached in memory. The default value is 1000.
// Set to a negative value to disable caching.
// Set to a negative value to disable caching. This field is only allowed for KMS v1 providers.
// +optional
CacheSize *int32 `json:"cachesize,omitempty"`
// endpoint is the gRPC server listening address, for example "unix:///var/run/kms-provider.sock".

View File

@@ -23,6 +23,7 @@ import (
"net/url"
"strings"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/apis/config"
@@ -34,7 +35,7 @@ const (
unsupportedSchemeErrFmt = "unsupported scheme %q for KMS provider, only unix is supported"
unsupportedKMSAPIVersionErrFmt = "unsupported apiVersion %s for KMS provider, only v1 and v2 are supported"
atLeastOneRequiredErrFmt = "at least one %s is required"
invalidURLErrFmt = "invalid endpoint for kms provider, error: parse %s: net/url: invalid control character in URL"
invalidURLErrFmt = "invalid endpoint for kms provider, error: %v"
mandatoryFieldErrFmt = "%s is a mandatory field for a %s"
base64EncodingErr = "secrets must be base64 encoded"
zeroOrNegativeErrFmt = "%s should be a positive value"
@@ -42,6 +43,14 @@ const (
encryptionConfigNilErr = "EncryptionConfiguration can't be nil"
invalidKMSConfigNameErrFmt = "invalid KMS provider name %s, must not contain ':'"
duplicateKMSConfigNameErrFmt = "duplicate KMS provider name %s, names must be unique"
eventsGroupErr = "'*.events.k8s.io' objects are stored using the 'events' API group in etcd. Use 'events' instead in the config file"
extensionsGroupErr = "'extensions' group has been removed and cannot be used for encryption"
starResourceErr = "use '*.' to encrypt all the resources from core API group or *.* to encrypt all resources"
overlapErr = "using overlapping resources such as 'secrets' and '*.' in the same resource list is not allowed as they will be masked"
nonRESTAPIResourceErr = "resources which do not have REST API/s cannot be encrypted"
resourceNameErr = "resource name should not contain capital letters"
resourceAcrossGroupErr = "encrypting the same resource across groups is not supported"
duplicateResourceErr = "the same resource cannot be specified multiple times"
)
var (
@@ -59,7 +68,7 @@ func ValidateEncryptionConfiguration(c *config.EncryptionConfiguration, reload b
allErrs := field.ErrorList{}
if c == nil {
allErrs = append(allErrs, field.Required(root, "EncryptionConfiguration can't be nil"))
allErrs = append(allErrs, field.Required(root, encryptionConfigNilErr))
return allErrs
}
@@ -78,6 +87,9 @@ func ValidateEncryptionConfiguration(c *config.EncryptionConfiguration, reload b
allErrs = append(allErrs, field.Required(r, fmt.Sprintf(atLeastOneRequiredErrFmt, r)))
}
allErrs = append(allErrs, validateResourceOverlap(conf.Resources, r)...)
allErrs = append(allErrs, validateResourceNames(conf.Resources, r)...)
if len(conf.Providers) == 0 {
allErrs = append(allErrs, field.Required(p, fmt.Sprintf(atLeastOneRequiredErrFmt, p)))
}
@@ -103,6 +115,175 @@ func ValidateEncryptionConfiguration(c *config.EncryptionConfiguration, reload b
return allErrs
}
var anyGroupAnyResource = schema.GroupResource{
Group: "*",
Resource: "*",
}
func validateResourceOverlap(resources []string, fieldPath *field.Path) field.ErrorList {
if len(resources) < 2 { // cannot have overlap with a single resource
return nil
}
var allErrs field.ErrorList
r := make([]schema.GroupResource, 0, len(resources))
for _, resource := range resources {
r = append(r, schema.ParseGroupResource(resource))
}
var hasOverlap, hasDuplicate bool
for i, r1 := range r {
for j, r2 := range r {
if i == j {
continue
}
if r1 == r2 && !hasDuplicate {
hasDuplicate = true
continue
}
if hasOverlap {
continue
}
if r1 == anyGroupAnyResource {
hasOverlap = true
continue
}
if r1.Group != r2.Group {
continue
}
if r1.Resource == "*" || r2.Resource == "*" {
hasOverlap = true
continue
}
}
}
if hasDuplicate {
allErrs = append(
allErrs,
field.Invalid(
fieldPath,
resources,
duplicateResourceErr,
),
)
}
if hasOverlap {
allErrs = append(
allErrs,
field.Invalid(
fieldPath,
resources,
overlapErr,
),
)
}
return allErrs
}
func validateResourceNames(resources []string, fieldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
for j, res := range resources {
jj := fieldPath.Index(j)
// check if resource name has capital letters
if hasCapital(res) {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
resourceNameErr,
),
)
continue
}
// check if resource is '*'
if res == "*" {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
starResourceErr,
),
)
continue
}
// check if resource is:
// 'apiserveripinfo' OR
// 'serviceipallocations' OR
// 'servicenodeportallocations' OR
if res == "apiserveripinfo" ||
res == "serviceipallocations" ||
res == "servicenodeportallocations" {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
nonRESTAPIResourceErr,
),
)
continue
}
// check if group is 'events.k8s.io'
gr := schema.ParseGroupResource(res)
if gr.Group == "events.k8s.io" {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
eventsGroupErr,
),
)
continue
}
// check if group is 'extensions'
if gr.Group == "extensions" {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
extensionsGroupErr,
),
)
continue
}
// disallow resource.* as encrypting the same resource across groups does not make sense
if gr.Group == "*" && gr.Resource != "*" {
allErrs = append(
allErrs,
field.Invalid(
jj,
resources[j],
resourceAcrossGroupErr,
),
)
continue
}
}
return allErrs
}
func validateSingleProvider(provider config.ProviderConfiguration, fieldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
found := 0
@@ -195,7 +376,13 @@ func validateKMSConfiguration(c *config.KMSConfiguration, fieldPath *field.Path,
func validateKMSCacheSize(c *config.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if *c.CacheSize == 0 {
// In defaulting, we set the cache size to the default value only when API version is v1.
// So, for v2 API version, we expect the cache size field to be nil.
if c.APIVersion != "v1" && c.CacheSize != nil {
allErrs = append(allErrs, field.Invalid(fieldPath, *c.CacheSize, "cachesize is not supported in v2"))
}
if c.APIVersion == "v1" && *c.CacheSize == 0 {
allErrs = append(allErrs, field.Invalid(fieldPath, *c.CacheSize, fmt.Sprintf(nonZeroErrFmt, "cachesize")))
}
@@ -219,7 +406,7 @@ func validateKMSEndpoint(c *config.KMSConfiguration, fieldPath *field.Path) fiel
u, err := url.Parse(c.Endpoint)
if err != nil {
return append(allErrs, field.Invalid(fieldPath, c.Endpoint, fmt.Sprintf("invalid endpoint for kms provider, error: %v", err)))
return append(allErrs, field.Invalid(fieldPath, c.Endpoint, fmt.Sprintf(invalidURLErrFmt, err)))
}
if u.Scheme != "unix" {
@@ -259,3 +446,7 @@ func validateKMSConfigName(c *config.KMSConfiguration, fieldPath *field.Path, km
return allErrs
}
func hasCapital(input string) bool {
return strings.ToLower(input) != input
}

View File

@@ -19,11 +19,11 @@ package bootstrap
import (
coordinationv1 "k8s.io/api/coordination/v1"
corev1 "k8s.io/api/core/v1"
flowcontrol "k8s.io/api/flowcontrol/v1beta3"
flowcontrol "k8s.io/api/flowcontrol/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
)
// The objects that define an apiserver's initial behavior. The
@@ -89,6 +89,10 @@ var (
flowcontrol.PriorityLevelConfigurationNameExempt,
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: ptr.To(int32(0)),
LendablePercent: ptr.To(int32(0)),
},
},
)
MandatoryPriorityLevelConfigurationCatchAll = newPriorityLevelConfiguration(
@@ -96,8 +100,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 5,
LendablePercent: pointer.Int32(0),
NominalConcurrencyShares: ptr.To(int32(5)),
LendablePercent: ptr.To(int32(0)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject,
},
@@ -169,8 +173,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 30,
LendablePercent: pointer.Int32(33),
NominalConcurrencyShares: ptr.To(int32(30)),
LendablePercent: ptr.To(int32(33)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@@ -186,8 +190,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 40,
LendablePercent: pointer.Int32(25),
NominalConcurrencyShares: ptr.To(int32(40)),
LendablePercent: ptr.To(int32(25)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@@ -204,8 +208,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 10,
LendablePercent: pointer.Int32(0),
NominalConcurrencyShares: ptr.To(int32(10)),
LendablePercent: ptr.To(int32(0)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@@ -222,8 +226,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 40,
LendablePercent: pointer.Int32(50),
NominalConcurrencyShares: ptr.To(int32(40)),
LendablePercent: ptr.To(int32(50)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@@ -240,8 +244,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 100,
LendablePercent: pointer.Int32(90),
NominalConcurrencyShares: ptr.To(int32(100)),
LendablePercent: ptr.To(int32(90)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{
@@ -258,8 +262,8 @@ var (
flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 20,
LendablePercent: pointer.Int32(50),
NominalConcurrencyShares: ptr.To(int32(20)),
LendablePercent: ptr.To(int32(50)),
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeQueue,
Queuing: &flowcontrol.QueuingConfiguration{