mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
rebase: update kubernetes to 1.30
updating kubernetes to 1.30 release Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
62ddcf715b
commit
e727bd351e
7
vendor/k8s.io/apiserver/pkg/admission/initializer/initializer.go
generated
vendored
7
vendor/k8s.io/apiserver/pkg/admission/initializer/initializer.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package initializer
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/client-go/dynamic"
|
||||
@ -32,6 +33,7 @@ type pluginInitializer struct {
|
||||
authorizer authorizer.Authorizer
|
||||
featureGates featuregate.FeatureGate
|
||||
stopCh <-chan struct{}
|
||||
restMapper meta.RESTMapper
|
||||
}
|
||||
|
||||
// New creates an instance of admission plugins initializer.
|
||||
@ -44,6 +46,7 @@ func New(
|
||||
authz authorizer.Authorizer,
|
||||
featureGates featuregate.FeatureGate,
|
||||
stopCh <-chan struct{},
|
||||
restMapper meta.RESTMapper,
|
||||
) pluginInitializer {
|
||||
return pluginInitializer{
|
||||
externalClient: extClientset,
|
||||
@ -52,6 +55,7 @@ func New(
|
||||
authorizer: authz,
|
||||
featureGates: featureGates,
|
||||
stopCh: stopCh,
|
||||
restMapper: restMapper,
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +87,9 @@ func (i pluginInitializer) Initialize(plugin admission.Interface) {
|
||||
if wants, ok := plugin.(WantsAuthorizer); ok {
|
||||
wants.SetAuthorizer(i.authorizer)
|
||||
}
|
||||
if wants, ok := plugin.(WantsRESTMapper); ok {
|
||||
wants.SetRESTMapper(i.restMapper)
|
||||
}
|
||||
}
|
||||
|
||||
var _ admission.PluginInitializer = pluginInitializer{}
|
||||
|
8
vendor/k8s.io/apiserver/pkg/admission/initializer/interfaces.go
generated
vendored
8
vendor/k8s.io/apiserver/pkg/admission/initializer/interfaces.go
generated
vendored
@ -18,6 +18,7 @@ package initializer
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/cel/openapi/resolver"
|
||||
@ -89,3 +90,10 @@ type WantsSchemaResolver interface {
|
||||
SetSchemaResolver(resolver resolver.SchemaResolver)
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
||||
// WantsExcludedAdmissionResources defines a function which sets the ExcludedAdmissionResources
|
||||
// for an admission plugin that needs it.
|
||||
type WantsExcludedAdmissionResources interface {
|
||||
SetExcludedAdmissionResources(excludedAdmissionResources []schema.GroupResource)
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
17
vendor/k8s.io/apiserver/pkg/admission/plugin/cel/composition.go
generated
vendored
17
vendor/k8s.io/apiserver/pkg/admission/plugin/cel/composition.go
generated
vendored
@ -54,13 +54,22 @@ func NewCompositedCompiler(envSet *environment.EnvSet) (*CompositedCompiler, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compiler := NewCompiler(compositionContext.EnvSet)
|
||||
filterCompiler := NewFilterCompiler(compositionContext.EnvSet)
|
||||
return NewCompositedCompilerFromTemplate(compositionContext), nil
|
||||
}
|
||||
|
||||
func NewCompositedCompilerFromTemplate(context *CompositionEnv) *CompositedCompiler {
|
||||
context = &CompositionEnv{
|
||||
MapType: context.MapType,
|
||||
EnvSet: context.EnvSet,
|
||||
CompiledVariables: map[string]CompilationResult{},
|
||||
}
|
||||
compiler := NewCompiler(context.EnvSet)
|
||||
filterCompiler := NewFilterCompiler(context.EnvSet)
|
||||
return &CompositedCompiler{
|
||||
Compiler: compiler,
|
||||
FilterCompiler: filterCompiler,
|
||||
CompositionEnv: compositionContext,
|
||||
}, nil
|
||||
CompositionEnv: context,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CompositedCompiler) CompileAndStoreVariables(variables []NamedExpressionAccessor, options OptionalVariableDeclarations, mode environment.Type) {
|
||||
|
42
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/accessor.go
generated
vendored
Normal file
42
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/accessor.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
type PolicyAccessor interface {
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
GetParamKind() *v1.ParamKind
|
||||
GetMatchConstraints() *v1.MatchResources
|
||||
}
|
||||
|
||||
type BindingAccessor interface {
|
||||
GetName() string
|
||||
GetNamespace() string
|
||||
|
||||
// GetPolicyName returns the name of the (Validating/Mutating)AdmissionPolicy,
|
||||
// which is cluster-scoped, so namespace is usually left blank.
|
||||
// But we leave the door open to add a namespaced vesion in the future
|
||||
GetPolicyName() types.NamespacedName
|
||||
GetParamRef() *v1.ParamRef
|
||||
|
||||
GetMatchResources() *v1.MatchResources
|
||||
}
|
64
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/interfaces.go
generated
vendored
Normal file
64
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/interfaces.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
// Hook represents a dynamic admission hook. The hook may be a webhook or a
|
||||
// policy. For webhook, the Hook may describe how to contact the endpoint, expected
|
||||
// cert, etc. For policies, the hook may describe a compiled policy-binding pair.
|
||||
type Hook interface {
|
||||
// All hooks are expected to contain zero or more match conditions, object
|
||||
// selectors, namespace selectors to help the dispatcher decide when to apply
|
||||
// the hook.
|
||||
//
|
||||
// Methods of matching logic is applied are specific to the hook and left up
|
||||
// to the implementation.
|
||||
}
|
||||
|
||||
// Source can list dynamic admission plugins.
|
||||
type Source[H Hook] interface {
|
||||
// Hooks returns the list of currently known admission hooks.
|
||||
Hooks() []H
|
||||
|
||||
// Run the source. This method should be called only once at startup.
|
||||
Run(ctx context.Context) error
|
||||
|
||||
// HasSynced returns true if the source has completed its initial sync.
|
||||
HasSynced() bool
|
||||
}
|
||||
|
||||
// Dispatcher dispatches evaluates an admission request against the currently
|
||||
// active hooks returned by the source.
|
||||
type Dispatcher[H Hook] interface {
|
||||
// Dispatch a request to the policies. Dispatcher may choose not to
|
||||
// call a hook, either because the rules of the hook does not match, or
|
||||
// the namespaceSelector or the objectSelector of the hook does not
|
||||
// match. A non-nil error means the request is rejected.
|
||||
Dispatch(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces, hooks []H) error
|
||||
}
|
||||
|
||||
// An evaluator represents a compiled CEL expression that can be evaluated a
|
||||
// given a set of inputs used by the generic PolicyHook for Mutating and
|
||||
// ValidatingAdmissionPolicy.
|
||||
// Mutating and Validating may have different forms of evaluators
|
||||
type Evaluator interface {
|
||||
}
|
215
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/plugin.go
generated
vendored
Normal file
215
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/plugin.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/matching"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// H is the Hook type generated by the source and consumed by the dispatcher.
|
||||
type sourceFactory[H any] func(informers.SharedInformerFactory, kubernetes.Interface, dynamic.Interface, meta.RESTMapper) Source[H]
|
||||
type dispatcherFactory[H any] func(authorizer.Authorizer, *matching.Matcher) Dispatcher[H]
|
||||
|
||||
// admissionResources is the list of resources related to CEL-based admission
|
||||
// features.
|
||||
var admissionResources = []schema.GroupResource{
|
||||
{Group: admissionregistrationv1.GroupName, Resource: "validatingadmissionpolicies"},
|
||||
{Group: admissionregistrationv1.GroupName, Resource: "validatingadmissionpolicybindings"},
|
||||
{Group: admissionregistrationv1.GroupName, Resource: "mutatingadmissionpolicies"},
|
||||
{Group: admissionregistrationv1.GroupName, Resource: "mutatingadmissionpolicybindings"},
|
||||
}
|
||||
|
||||
// AdmissionPolicyManager is an abstract admission plugin with all the
|
||||
// infrastructure to define Admit or Validate on-top.
|
||||
type Plugin[H any] struct {
|
||||
*admission.Handler
|
||||
|
||||
sourceFactory sourceFactory[H]
|
||||
dispatcherFactory dispatcherFactory[H]
|
||||
|
||||
source Source[H]
|
||||
dispatcher Dispatcher[H]
|
||||
matcher *matching.Matcher
|
||||
|
||||
informerFactory informers.SharedInformerFactory
|
||||
client kubernetes.Interface
|
||||
restMapper meta.RESTMapper
|
||||
dynamicClient dynamic.Interface
|
||||
excludedResources sets.Set[schema.GroupResource]
|
||||
stopCh <-chan struct{}
|
||||
authorizer authorizer.Authorizer
|
||||
enabled bool
|
||||
}
|
||||
|
||||
var (
|
||||
_ initializer.WantsExternalKubeInformerFactory = &Plugin[any]{}
|
||||
_ initializer.WantsExternalKubeClientSet = &Plugin[any]{}
|
||||
_ initializer.WantsRESTMapper = &Plugin[any]{}
|
||||
_ initializer.WantsDynamicClient = &Plugin[any]{}
|
||||
_ initializer.WantsDrainedNotification = &Plugin[any]{}
|
||||
_ initializer.WantsAuthorizer = &Plugin[any]{}
|
||||
_ initializer.WantsExcludedAdmissionResources = &Plugin[any]{}
|
||||
_ admission.InitializationValidator = &Plugin[any]{}
|
||||
)
|
||||
|
||||
func NewPlugin[H any](
|
||||
handler *admission.Handler,
|
||||
sourceFactory sourceFactory[H],
|
||||
dispatcherFactory dispatcherFactory[H],
|
||||
) *Plugin[H] {
|
||||
return &Plugin[H]{
|
||||
Handler: handler,
|
||||
sourceFactory: sourceFactory,
|
||||
dispatcherFactory: dispatcherFactory,
|
||||
|
||||
// always exclude admission/mutating policies and bindings
|
||||
excludedResources: sets.New(admissionResources...),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
c.informerFactory = f
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
c.client = client
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetRESTMapper(mapper meta.RESTMapper) {
|
||||
c.restMapper = mapper
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetDynamicClient(client dynamic.Interface) {
|
||||
c.dynamicClient = client
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetDrainedNotification(stopCh <-chan struct{}) {
|
||||
c.stopCh = stopCh
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetAuthorizer(authorizer authorizer.Authorizer) {
|
||||
c.authorizer = authorizer
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetMatcher(matcher *matching.Matcher) {
|
||||
c.matcher = matcher
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetEnabled(enabled bool) {
|
||||
c.enabled = enabled
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetExcludedAdmissionResources(excludedResources []schema.GroupResource) {
|
||||
c.excludedResources.Insert(excludedResources...)
|
||||
}
|
||||
|
||||
// ValidateInitialization - once clientset and informer factory are provided, creates and starts the admission controller
|
||||
func (c *Plugin[H]) ValidateInitialization() error {
|
||||
// By default enabled is set to false. It is up to types which embed this
|
||||
// struct to set it to true (if feature gate is enabled, or other conditions)
|
||||
if !c.enabled {
|
||||
return nil
|
||||
}
|
||||
if c.Handler == nil {
|
||||
return errors.New("missing handler")
|
||||
}
|
||||
if c.informerFactory == nil {
|
||||
return errors.New("missing informer factory")
|
||||
}
|
||||
if c.client == nil {
|
||||
return errors.New("missing kubernetes client")
|
||||
}
|
||||
if c.restMapper == nil {
|
||||
return errors.New("missing rest mapper")
|
||||
}
|
||||
if c.dynamicClient == nil {
|
||||
return errors.New("missing dynamic client")
|
||||
}
|
||||
if c.stopCh == nil {
|
||||
return errors.New("missing stop channel")
|
||||
}
|
||||
if c.authorizer == nil {
|
||||
return errors.New("missing authorizer")
|
||||
}
|
||||
|
||||
// Use default matcher
|
||||
namespaceInformer := c.informerFactory.Core().V1().Namespaces()
|
||||
c.matcher = matching.NewMatcher(namespaceInformer.Lister(), c.client)
|
||||
|
||||
if err := c.matcher.ValidateInitialization(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.source = c.sourceFactory(c.informerFactory, c.client, c.dynamicClient, c.restMapper)
|
||||
c.dispatcher = c.dispatcherFactory(c.authorizer, c.matcher)
|
||||
|
||||
pluginContext, pluginContextCancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
defer pluginContextCancel()
|
||||
<-c.stopCh
|
||||
}()
|
||||
|
||||
go func() {
|
||||
err := c.source.Run(pluginContext)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
utilruntime.HandleError(fmt.Errorf("policy source context unexpectedly closed: %v", err))
|
||||
}
|
||||
}()
|
||||
|
||||
c.SetReadyFunc(func() bool {
|
||||
return namespaceInformer.Informer().HasSynced() && c.source.HasSynced()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) Dispatch(
|
||||
ctx context.Context,
|
||||
a admission.Attributes,
|
||||
o admission.ObjectInterfaces,
|
||||
) (err error) {
|
||||
if !c.enabled {
|
||||
return nil
|
||||
} else if c.shouldIgnoreResource(a) {
|
||||
return nil
|
||||
} else if !c.WaitForReady() {
|
||||
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
|
||||
}
|
||||
|
||||
return c.dispatcher.Dispatch(ctx, a, o, c.source.Hooks())
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) shouldIgnoreResource(attr admission.Attributes) bool {
|
||||
gvr := attr.GetResource()
|
||||
// exclusion decision ignores the version.
|
||||
gr := gvr.GroupResource()
|
||||
return c.excludedResources.Has(gr)
|
||||
}
|
354
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_dispatcher.go
generated
vendored
Normal file
354
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_dispatcher.go
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/matching"
|
||||
webhookgeneric "k8s.io/apiserver/pkg/admission/plugin/webhook/generic"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// A policy invocation is a single policy-binding-param tuple from a Policy Hook
|
||||
// in the context of a specific request. The params have already been resolved
|
||||
// and any error in configuration or setting up the invocation is stored in
|
||||
// the Error field.
|
||||
type PolicyInvocation[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||
// Relevant policy for this hook.
|
||||
// This field is always populated
|
||||
Policy P
|
||||
|
||||
// Matched Kind for the request given the policy's matchconstraints
|
||||
// May be empty if there was an error matching the resource
|
||||
Kind schema.GroupVersionKind
|
||||
|
||||
// Matched Resource for the request given the policy's matchconstraints
|
||||
// May be empty if there was an error matching the resource
|
||||
Resource schema.GroupVersionResource
|
||||
|
||||
// Relevant binding for this hook.
|
||||
// May be empty if there was an error with the policy's configuration itself
|
||||
Binding B
|
||||
|
||||
// Compiled policy evaluator
|
||||
Evaluator E
|
||||
|
||||
// Params fetched by the binding to use to evaluate the policy
|
||||
Param runtime.Object
|
||||
|
||||
// Error is set if there was an error with the policy or binding or its
|
||||
// params, etc
|
||||
Error error
|
||||
}
|
||||
|
||||
// dispatcherDelegate is called during a request with a pre-filtered list
|
||||
// of (Policy, Binding, Param) tuples that are active and match the request.
|
||||
// The dispatcher delegate is responsible for updating the object on the
|
||||
// admission attributes in the case of mutation, or returning a status error in
|
||||
// the case of validation.
|
||||
//
|
||||
// The delegate provides the "validation" or "mutation" aspect of dispatcher functionality
|
||||
// (in contrast to generic.PolicyDispatcher which only selects active policies and params)
|
||||
type dispatcherDelegate[P, B runtime.Object, E Evaluator] func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces, versionedAttributes webhookgeneric.VersionedAttributeAccessor, invocations []PolicyInvocation[P, B, E]) error
|
||||
|
||||
type policyDispatcher[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||
newPolicyAccessor func(P) PolicyAccessor
|
||||
newBindingAccessor func(B) BindingAccessor
|
||||
matcher PolicyMatcher
|
||||
delegate dispatcherDelegate[P, B, E]
|
||||
}
|
||||
|
||||
func NewPolicyDispatcher[P runtime.Object, B runtime.Object, E Evaluator](
|
||||
newPolicyAccessor func(P) PolicyAccessor,
|
||||
newBindingAccessor func(B) BindingAccessor,
|
||||
matcher *matching.Matcher,
|
||||
delegate dispatcherDelegate[P, B, E],
|
||||
) Dispatcher[PolicyHook[P, B, E]] {
|
||||
return &policyDispatcher[P, B, E]{
|
||||
newPolicyAccessor: newPolicyAccessor,
|
||||
newBindingAccessor: newBindingAccessor,
|
||||
matcher: NewPolicyMatcher(matcher),
|
||||
delegate: delegate,
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch implements generic.Dispatcher. It loops through all active hooks
|
||||
// (policy x binding pairs) and selects those which are active for the current
|
||||
// request. It then resolves all params and creates an Invocation for each
|
||||
// matching policy-binding-param tuple. The delegate is then called with the
|
||||
// list of tuples.
|
||||
//
|
||||
// Note: MatchConditions expressions are not evaluated here. The dispatcher delegate
|
||||
// is expected to ignore the result of any policies whose match conditions dont pass.
|
||||
// This may be possible to refactor so matchconditions are checked here instead.
|
||||
func (d *policyDispatcher[P, B, E]) Dispatch(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces, hooks []PolicyHook[P, B, E]) error {
|
||||
var relevantHooks []PolicyInvocation[P, B, E]
|
||||
// Construct all the versions we need to call our webhooks
|
||||
versionedAttrAccessor := &versionedAttributeAccessor{
|
||||
versionedAttrs: map[schema.GroupVersionKind]*admission.VersionedAttributes{},
|
||||
attr: a,
|
||||
objectInterfaces: o,
|
||||
}
|
||||
|
||||
for _, hook := range hooks {
|
||||
policyAccessor := d.newPolicyAccessor(hook.Policy)
|
||||
matches, matchGVR, matchGVK, err := d.matcher.DefinitionMatches(a, o, policyAccessor)
|
||||
if err != nil {
|
||||
// There was an error evaluating if this policy matches anything.
|
||||
utilruntime.HandleError(err)
|
||||
relevantHooks = append(relevantHooks, PolicyInvocation[P, B, E]{
|
||||
Policy: hook.Policy,
|
||||
Error: err,
|
||||
})
|
||||
continue
|
||||
} else if !matches {
|
||||
continue
|
||||
} else if hook.ConfigurationError != nil {
|
||||
// The policy matches but there is a configuration error with the
|
||||
// policy itself
|
||||
relevantHooks = append(relevantHooks, PolicyInvocation[P, B, E]{
|
||||
Policy: hook.Policy,
|
||||
Error: hook.ConfigurationError,
|
||||
Resource: matchGVR,
|
||||
Kind: matchGVK,
|
||||
})
|
||||
utilruntime.HandleError(hook.ConfigurationError)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, binding := range hook.Bindings {
|
||||
bindingAccessor := d.newBindingAccessor(binding)
|
||||
matches, err = d.matcher.BindingMatches(a, o, bindingAccessor)
|
||||
if err != nil {
|
||||
// There was an error evaluating if this binding matches anything.
|
||||
utilruntime.HandleError(err)
|
||||
relevantHooks = append(relevantHooks, PolicyInvocation[P, B, E]{
|
||||
Policy: hook.Policy,
|
||||
Binding: binding,
|
||||
Error: err,
|
||||
Resource: matchGVR,
|
||||
Kind: matchGVK,
|
||||
})
|
||||
continue
|
||||
} else if !matches {
|
||||
continue
|
||||
}
|
||||
|
||||
// Collect params for this binding
|
||||
params, err := CollectParams(
|
||||
policyAccessor.GetParamKind(),
|
||||
hook.ParamInformer,
|
||||
hook.ParamScope,
|
||||
bindingAccessor.GetParamRef(),
|
||||
a.GetNamespace(),
|
||||
)
|
||||
if err != nil {
|
||||
// There was an error collecting params for this binding.
|
||||
utilruntime.HandleError(err)
|
||||
relevantHooks = append(relevantHooks, PolicyInvocation[P, B, E]{
|
||||
Policy: hook.Policy,
|
||||
Binding: binding,
|
||||
Error: err,
|
||||
Resource: matchGVR,
|
||||
Kind: matchGVK,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// If params is empty and there was no error, that means that
|
||||
// ParamNotFoundAction is ignore, so it shouldnt be added to list
|
||||
for _, param := range params {
|
||||
relevantHooks = append(relevantHooks, PolicyInvocation[P, B, E]{
|
||||
Policy: hook.Policy,
|
||||
Binding: binding,
|
||||
Kind: matchGVK,
|
||||
Resource: matchGVR,
|
||||
Param: param,
|
||||
Evaluator: hook.Evaluator,
|
||||
})
|
||||
}
|
||||
|
||||
// VersionedAttr result will be cached and reused later during parallel
|
||||
// hook calls
|
||||
_, err = versionedAttrAccessor.VersionedAttribute(matchGVK)
|
||||
if err != nil {
|
||||
return apierrors.NewInternalError(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(relevantHooks) == 0 {
|
||||
// no matching hooks
|
||||
return nil
|
||||
}
|
||||
|
||||
return d.delegate(ctx, a, o, versionedAttrAccessor, relevantHooks)
|
||||
}
|
||||
|
||||
// Returns params to use to evaluate a policy-binding with given param
|
||||
// configuration. If the policy-binding has no param configuration, it
|
||||
// returns a single-element list with a nil param.
|
||||
func CollectParams(
|
||||
paramKind *v1.ParamKind,
|
||||
paramInformer informers.GenericInformer,
|
||||
paramScope meta.RESTScope,
|
||||
paramRef *v1.ParamRef,
|
||||
namespace string,
|
||||
) ([]runtime.Object, error) {
|
||||
// If definition has paramKind, paramRef is required in binding.
|
||||
// If definition has no paramKind, paramRef set in binding will be ignored.
|
||||
var params []runtime.Object
|
||||
var paramStore cache.GenericNamespaceLister
|
||||
|
||||
// Make sure the param kind is ready to use
|
||||
if paramKind != nil && paramRef != nil {
|
||||
if paramInformer == nil {
|
||||
return nil, fmt.Errorf("paramKind kind `%v` not known",
|
||||
paramKind.String())
|
||||
}
|
||||
|
||||
// Set up cluster-scoped, or namespaced access to the params
|
||||
// "default" if not provided, and paramKind is namespaced
|
||||
paramStore = paramInformer.Lister()
|
||||
if paramScope.Name() == meta.RESTScopeNameNamespace {
|
||||
paramsNamespace := namespace
|
||||
if len(paramRef.Namespace) > 0 {
|
||||
paramsNamespace = paramRef.Namespace
|
||||
} else if len(paramsNamespace) == 0 {
|
||||
// You must supply namespace if your matcher can possibly
|
||||
// match a cluster-scoped resource
|
||||
return nil, fmt.Errorf("cannot use namespaced paramRef in policy binding that matches cluster-scoped resources")
|
||||
}
|
||||
|
||||
paramStore = paramInformer.Lister().ByNamespace(paramsNamespace)
|
||||
}
|
||||
|
||||
// If the param informer for this admission policy has not yet
|
||||
// had time to perform an initial listing, don't attempt to use
|
||||
// it.
|
||||
timeoutCtx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if !cache.WaitForCacheSync(timeoutCtx.Done(), paramInformer.Informer().HasSynced) {
|
||||
return nil, fmt.Errorf("paramKind kind `%v` not yet synced to use for admission",
|
||||
paramKind.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Find params to use with policy
|
||||
switch {
|
||||
case paramKind == nil:
|
||||
// ParamKind is unset. Ignore any globalParamRef or namespaceParamRef
|
||||
// setting.
|
||||
return []runtime.Object{nil}, nil
|
||||
case paramRef == nil:
|
||||
// Policy ParamKind is set, but binding does not use it.
|
||||
// Validate with nil params
|
||||
return []runtime.Object{nil}, nil
|
||||
case len(paramRef.Namespace) > 0 && paramScope.Name() == meta.RESTScopeRoot.Name():
|
||||
// Not allowed to set namespace for cluster-scoped param
|
||||
return nil, fmt.Errorf("paramRef.namespace must not be provided for a cluster-scoped `paramKind`")
|
||||
|
||||
case len(paramRef.Name) > 0:
|
||||
if paramRef.Selector != nil {
|
||||
// This should be validated, but just in case.
|
||||
return nil, fmt.Errorf("paramRef.name and paramRef.selector are mutually exclusive")
|
||||
}
|
||||
|
||||
switch param, err := paramStore.Get(paramRef.Name); {
|
||||
case err == nil:
|
||||
params = []runtime.Object{param}
|
||||
case apierrors.IsNotFound(err):
|
||||
// Param not yet available. User may need to wait a bit
|
||||
// before being able to use it for validation.
|
||||
//
|
||||
// Set params to nil to prepare for not found action
|
||||
params = nil
|
||||
case apierrors.IsInvalid(err):
|
||||
// Param mis-configured
|
||||
// require to set namespace for namespaced resource
|
||||
// and unset namespace for cluster scoped resource
|
||||
return nil, err
|
||||
default:
|
||||
// Internal error
|
||||
utilruntime.HandleError(err)
|
||||
return nil, err
|
||||
}
|
||||
case paramRef.Selector != nil:
|
||||
// Select everything by default if empty name and selector
|
||||
selector, err := metav1.LabelSelectorAsSelector(paramRef.Selector)
|
||||
if err != nil {
|
||||
// Cannot parse label selector: configuration error
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
paramList, err := paramStore.List(selector)
|
||||
if err != nil {
|
||||
// There was a bad internal error
|
||||
utilruntime.HandleError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Successfully grabbed params
|
||||
params = paramList
|
||||
default:
|
||||
// Should be unreachable due to validation
|
||||
return nil, fmt.Errorf("one of name or selector must be provided")
|
||||
}
|
||||
|
||||
// Apply fail action for params not found case
|
||||
if len(params) == 0 && paramRef.ParameterNotFoundAction != nil && *paramRef.ParameterNotFoundAction == v1.DenyAction {
|
||||
return nil, errors.New("no params found for policy binding with `Deny` parameterNotFoundAction")
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
var _ webhookgeneric.VersionedAttributeAccessor = &versionedAttributeAccessor{}
|
||||
|
||||
type versionedAttributeAccessor struct {
|
||||
versionedAttrs map[schema.GroupVersionKind]*admission.VersionedAttributes
|
||||
attr admission.Attributes
|
||||
objectInterfaces admission.ObjectInterfaces
|
||||
}
|
||||
|
||||
func (v *versionedAttributeAccessor) VersionedAttribute(gvk schema.GroupVersionKind) (*admission.VersionedAttributes, error) {
|
||||
if val, ok := v.versionedAttrs[gvk]; ok {
|
||||
return val, nil
|
||||
}
|
||||
versionedAttr, err := admission.NewVersionedAttributes(v.attr, gvk, v.objectInterfaces)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v.versionedAttrs[gvk] = versionedAttr
|
||||
return versionedAttr, nil
|
||||
}
|
@ -14,22 +14,82 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package generic
|
||||
|
||||
import (
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
"fmt"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/matching"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/matching"
|
||||
)
|
||||
|
||||
// Matcher is used for matching ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding to attributes
|
||||
type PolicyMatcher interface {
|
||||
admission.InitializationValidator
|
||||
|
||||
// DefinitionMatches says whether this policy definition matches the provided admission
|
||||
// resource request
|
||||
DefinitionMatches(a admission.Attributes, o admission.ObjectInterfaces, definition PolicyAccessor) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error)
|
||||
|
||||
// BindingMatches says whether this policy definition matches the provided admission
|
||||
// resource request
|
||||
BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, binding BindingAccessor) (bool, error)
|
||||
|
||||
// GetNamespace retrieves the Namespace resource by the given name. The name may be empty, in which case
|
||||
// GetNamespace must return nil, nil
|
||||
GetNamespace(name string) (*corev1.Namespace, error)
|
||||
}
|
||||
|
||||
type matcher struct {
|
||||
Matcher *matching.Matcher
|
||||
}
|
||||
|
||||
func NewPolicyMatcher(m *matching.Matcher) PolicyMatcher {
|
||||
return &matcher{
|
||||
Matcher: m,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateInitialization checks if Matcher is initialized.
|
||||
func (c *matcher) ValidateInitialization() error {
|
||||
return c.Matcher.ValidateInitialization()
|
||||
}
|
||||
|
||||
// DefinitionMatches returns whether this ValidatingAdmissionPolicy matches the provided admission resource request
|
||||
func (c *matcher) DefinitionMatches(a admission.Attributes, o admission.ObjectInterfaces, definition PolicyAccessor) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error) {
|
||||
constraints := definition.GetMatchConstraints()
|
||||
if constraints == nil {
|
||||
return false, schema.GroupVersionResource{}, schema.GroupVersionKind{}, fmt.Errorf("policy contained no match constraints, a required field")
|
||||
}
|
||||
criteria := matchCriteria{constraints: constraints}
|
||||
return c.Matcher.Matches(a, o, &criteria)
|
||||
}
|
||||
|
||||
// BindingMatches returns whether this ValidatingAdmissionPolicyBinding matches the provided admission resource request
|
||||
func (c *matcher) BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, binding BindingAccessor) (bool, error) {
|
||||
matchResources := binding.GetMatchResources()
|
||||
if matchResources == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
criteria := matchCriteria{constraints: matchResources}
|
||||
isMatch, _, _, err := c.Matcher.Matches(a, o, &criteria)
|
||||
return isMatch, err
|
||||
}
|
||||
|
||||
func (c *matcher) GetNamespace(name string) (*corev1.Namespace, error) {
|
||||
return c.Matcher.GetNamespace(name)
|
||||
}
|
||||
|
||||
var _ matching.MatchCriteria = &matchCriteria{}
|
||||
|
||||
type matchCriteria struct {
|
||||
constraints *v1beta1.MatchResources
|
||||
constraints *admissionregistrationv1.MatchResources
|
||||
}
|
||||
|
||||
// GetParsedNamespaceSelector returns the converted LabelSelector which implements labels.Selector
|
||||
@ -43,41 +103,6 @@ func (m *matchCriteria) GetParsedObjectSelector() (labels.Selector, error) {
|
||||
}
|
||||
|
||||
// GetMatchResources returns the matchConstraints
|
||||
func (m *matchCriteria) GetMatchResources() v1beta1.MatchResources {
|
||||
func (m *matchCriteria) GetMatchResources() admissionregistrationv1.MatchResources {
|
||||
return *m.constraints
|
||||
}
|
||||
|
||||
type matcher struct {
|
||||
Matcher *matching.Matcher
|
||||
}
|
||||
|
||||
func NewMatcher(m *matching.Matcher) Matcher {
|
||||
return &matcher{
|
||||
Matcher: m,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateInitialization checks if Matcher is initialized.
|
||||
func (c *matcher) ValidateInitialization() error {
|
||||
return c.Matcher.ValidateInitialization()
|
||||
}
|
||||
|
||||
// DefinitionMatches returns whether this ValidatingAdmissionPolicy matches the provided admission resource request
|
||||
func (c *matcher) DefinitionMatches(a admission.Attributes, o admission.ObjectInterfaces, definition *v1beta1.ValidatingAdmissionPolicy) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error) {
|
||||
criteria := matchCriteria{constraints: definition.Spec.MatchConstraints}
|
||||
return c.Matcher.Matches(a, o, &criteria)
|
||||
}
|
||||
|
||||
// BindingMatches returns whether this ValidatingAdmissionPolicyBinding matches the provided admission resource request
|
||||
func (c *matcher) BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, binding *v1beta1.ValidatingAdmissionPolicyBinding) (bool, error) {
|
||||
if binding.Spec.MatchResources == nil {
|
||||
return true, nil
|
||||
}
|
||||
criteria := matchCriteria{constraints: binding.Spec.MatchResources}
|
||||
isMatch, _, _, err := c.Matcher.Matches(a, o, &criteria)
|
||||
return isMatch, err
|
||||
}
|
||||
|
||||
func (c *matcher) GetNamespace(name string) (*corev1.Namespace, error) {
|
||||
return c.Matcher.GetNamespace(name)
|
||||
}
|
477
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_source.go
generated
vendored
Normal file
477
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_source.go
generated
vendored
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
goerrors "errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/internal/generic"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/dynamic/dynamicinformer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type policySource[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||
ctx context.Context
|
||||
policyInformer generic.Informer[P]
|
||||
bindingInformer generic.Informer[B]
|
||||
restMapper meta.RESTMapper
|
||||
newPolicyAccessor func(P) PolicyAccessor
|
||||
newBindingAccessor func(B) BindingAccessor
|
||||
|
||||
informerFactory informers.SharedInformerFactory
|
||||
dynamicClient dynamic.Interface
|
||||
|
||||
compiler func(P) E
|
||||
|
||||
// Currently compiled list of valid/active policy-binding pairs
|
||||
policies atomic.Pointer[[]PolicyHook[P, B, E]]
|
||||
// Whether the cache of policies is dirty and needs to be recompiled
|
||||
policiesDirty atomic.Bool
|
||||
|
||||
lock sync.Mutex
|
||||
compiledPolicies map[types.NamespacedName]compiledPolicyEntry[E]
|
||||
|
||||
// Temporary until we use the dynamic informer factory
|
||||
paramsCRDControllers map[schema.GroupVersionKind]*paramInfo
|
||||
}
|
||||
|
||||
type paramInfo struct {
|
||||
mapping meta.RESTMapping
|
||||
|
||||
// When the param is changed, or the informer is done being used, the cancel
|
||||
// func should be called to stop/cleanup the original informer
|
||||
cancelFunc func()
|
||||
|
||||
// The lister for this param
|
||||
informer informers.GenericInformer
|
||||
}
|
||||
|
||||
type compiledPolicyEntry[E Evaluator] struct {
|
||||
policyVersion string
|
||||
evaluator E
|
||||
}
|
||||
|
||||
type PolicyHook[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||
Policy P
|
||||
Bindings []B
|
||||
|
||||
// ParamInformer is the informer for the param CRD for this policy, or nil if
|
||||
// there is no param or if there was a configuration error
|
||||
ParamInformer informers.GenericInformer
|
||||
ParamScope meta.RESTScope
|
||||
|
||||
Evaluator E
|
||||
ConfigurationError error
|
||||
}
|
||||
|
||||
var _ Source[PolicyHook[runtime.Object, runtime.Object, Evaluator]] = &policySource[runtime.Object, runtime.Object, Evaluator]{}
|
||||
|
||||
func NewPolicySource[P runtime.Object, B runtime.Object, E Evaluator](
|
||||
policyInformer cache.SharedIndexInformer,
|
||||
bindingInformer cache.SharedIndexInformer,
|
||||
newPolicyAccessor func(P) PolicyAccessor,
|
||||
newBindingAccessor func(B) BindingAccessor,
|
||||
compiler func(P) E,
|
||||
paramInformerFactory informers.SharedInformerFactory,
|
||||
dynamicClient dynamic.Interface,
|
||||
restMapper meta.RESTMapper,
|
||||
) Source[PolicyHook[P, B, E]] {
|
||||
res := &policySource[P, B, E]{
|
||||
compiler: compiler,
|
||||
policyInformer: generic.NewInformer[P](policyInformer),
|
||||
bindingInformer: generic.NewInformer[B](bindingInformer),
|
||||
compiledPolicies: map[types.NamespacedName]compiledPolicyEntry[E]{},
|
||||
newPolicyAccessor: newPolicyAccessor,
|
||||
newBindingAccessor: newBindingAccessor,
|
||||
paramsCRDControllers: map[schema.GroupVersionKind]*paramInfo{},
|
||||
informerFactory: paramInformerFactory,
|
||||
dynamicClient: dynamicClient,
|
||||
restMapper: restMapper,
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *policySource[P, B, E]) Run(ctx context.Context) error {
|
||||
if s.ctx != nil {
|
||||
return fmt.Errorf("policy source already running")
|
||||
}
|
||||
|
||||
// Wait for initial cache sync of policies and informers before reconciling
|
||||
// any
|
||||
if !cache.WaitForNamedCacheSync(fmt.Sprintf("%T", s), ctx.Done(), s.UpstreamHasSynced) {
|
||||
err := ctx.Err()
|
||||
if err == nil {
|
||||
err = fmt.Errorf("initial cache sync for %T failed", s)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
s.ctx = ctx
|
||||
|
||||
// Perform initial policy compilation after initial list has finished
|
||||
s.notify()
|
||||
s.refreshPolicies()
|
||||
|
||||
notifyFuncs := cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(_ interface{}) {
|
||||
s.notify()
|
||||
},
|
||||
UpdateFunc: func(_, _ interface{}) {
|
||||
s.notify()
|
||||
},
|
||||
DeleteFunc: func(_ interface{}) {
|
||||
s.notify()
|
||||
},
|
||||
}
|
||||
handle, err := s.policyInformer.AddEventHandler(notifyFuncs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := s.policyInformer.RemoveEventHandler(handle); err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to remove policy event handler: %w", err))
|
||||
}
|
||||
}()
|
||||
|
||||
bindingHandle, err := s.bindingInformer.AddEventHandler(notifyFuncs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := s.bindingInformer.RemoveEventHandler(bindingHandle); err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to remove binding event handler: %w", err))
|
||||
}
|
||||
}()
|
||||
|
||||
// Start a worker that checks every second to see if policy data is dirty
|
||||
// and needs to be recompiled
|
||||
go func() {
|
||||
// Loop every 1 second until context is cancelled, refreshing policies
|
||||
wait.Until(s.refreshPolicies, 1*time.Second, ctx.Done())
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *policySource[P, B, E]) UpstreamHasSynced() bool {
|
||||
return s.policyInformer.HasSynced() && s.bindingInformer.HasSynced()
|
||||
}
|
||||
|
||||
// HasSynced implements Source.
|
||||
func (s *policySource[P, B, E]) HasSynced() bool {
|
||||
// As an invariant we never store `nil` into the atomic list of processed
|
||||
// policy hooks. If it is nil, then we haven't compiled all the policies
|
||||
// and stored them yet.
|
||||
return s.Hooks() != nil
|
||||
}
|
||||
|
||||
// Hooks implements Source.
|
||||
func (s *policySource[P, B, E]) Hooks() []PolicyHook[P, B, E] {
|
||||
res := s.policies.Load()
|
||||
|
||||
// Error case should not happen since evaluation function never
|
||||
// returns error
|
||||
if res == nil {
|
||||
// Not yet synced
|
||||
return nil
|
||||
}
|
||||
|
||||
return *res
|
||||
}
|
||||
|
||||
func (s *policySource[P, B, E]) refreshPolicies() {
|
||||
if !s.UpstreamHasSynced() {
|
||||
return
|
||||
} else if !s.policiesDirty.Swap(false) {
|
||||
return
|
||||
}
|
||||
|
||||
// It is ok the cache gets marked dirty again between us clearing the
|
||||
// flag and us calculating the policies. The dirty flag would be marked again,
|
||||
// and we'd have a no-op after comparing resource versions on the next sync.
|
||||
klog.Infof("refreshing policies")
|
||||
policies, err := s.calculatePolicyData()
|
||||
|
||||
// Intentionally store policy list regardless of error. There may be
|
||||
// an error returned if there was a configuration error in one of the policies,
|
||||
// but we would still want those policies evaluated
|
||||
// (for instance to return error on failaction). Or if there was an error
|
||||
// listing all policies at all, we would want to wipe the list.
|
||||
s.policies.Store(&policies)
|
||||
|
||||
if err != nil {
|
||||
// An error was generated while syncing policies. Mark it as dirty again
|
||||
// so we can retry later
|
||||
utilruntime.HandleError(fmt.Errorf("encountered error syncing policies: %w. Rescheduling policy sync", err))
|
||||
s.notify()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *policySource[P, B, E]) notify() {
|
||||
s.policiesDirty.Store(true)
|
||||
}
|
||||
|
||||
// calculatePolicyData calculates the list of policies and bindings for each
|
||||
// policy. If there is an error in generation, it will return the error and
|
||||
// the partial list of policies that were able to be generated. Policies that
|
||||
// have an error will have a non-nil ConfigurationError field, but still be
|
||||
// included in the result.
|
||||
//
|
||||
// This function caches the result of the intermediate compilations
|
||||
func (s *policySource[P, B, E]) calculatePolicyData() ([]PolicyHook[P, B, E], error) {
|
||||
if !s.UpstreamHasSynced() {
|
||||
return nil, fmt.Errorf("cannot calculate policy data until upstream has synced")
|
||||
}
|
||||
|
||||
// Fat-fingered lock that can be made more fine-tuned if required
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
// Create a local copy of all policies and bindings
|
||||
policiesToBindings := map[types.NamespacedName][]B{}
|
||||
bindingList, err := s.bindingInformer.List(labels.Everything())
|
||||
if err != nil {
|
||||
// This should never happen unless types are misconfigured
|
||||
// (can't use meta.accessor on them)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Gather a list of all active policy bindings
|
||||
for _, bindingSpec := range bindingList {
|
||||
bindingAccessor := s.newBindingAccessor(bindingSpec)
|
||||
policyKey := bindingAccessor.GetPolicyName()
|
||||
|
||||
// Add this binding to the list of bindings for this policy
|
||||
policiesToBindings[policyKey] = append(policiesToBindings[policyKey], bindingSpec)
|
||||
}
|
||||
|
||||
result := make([]PolicyHook[P, B, E], 0, len(bindingList))
|
||||
usedParams := map[schema.GroupVersionKind]struct{}{}
|
||||
var errs []error
|
||||
for policyKey, bindingSpecs := range policiesToBindings {
|
||||
var inf generic.NamespacedLister[P] = s.policyInformer
|
||||
if len(policyKey.Namespace) > 0 {
|
||||
inf = s.policyInformer.Namespaced(policyKey.Namespace)
|
||||
}
|
||||
policySpec, err := inf.Get(policyKey.Name)
|
||||
if errors.IsNotFound(err) {
|
||||
// Policy for bindings doesn't exist. This can happen if the policy
|
||||
// was deleted before the binding, or the binding was created first.
|
||||
//
|
||||
// Just skip bindings that refer to non-existent policies
|
||||
// If the policy is recreated, the cache will be marked dirty and
|
||||
// this function will run again.
|
||||
continue
|
||||
} else if err != nil {
|
||||
// This should never happen since fetching from a cache should never
|
||||
// fail and this function checks that the cache was synced before
|
||||
// even getting to this point.
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var parsedParamKind *schema.GroupVersionKind
|
||||
policyAccessor := s.newPolicyAccessor(policySpec)
|
||||
|
||||
if paramKind := policyAccessor.GetParamKind(); paramKind != nil {
|
||||
groupVersion, err := schema.ParseGroupVersion(paramKind.APIVersion)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to parse paramKind APIVersion: %w", err))
|
||||
continue
|
||||
}
|
||||
parsedParamKind = &schema.GroupVersionKind{
|
||||
Group: groupVersion.Group,
|
||||
Version: groupVersion.Version,
|
||||
Kind: paramKind.Kind,
|
||||
}
|
||||
|
||||
// TEMPORARY UNTIL WE HAVE SHARED PARAM INFORMERS
|
||||
usedParams[*parsedParamKind] = struct{}{}
|
||||
}
|
||||
|
||||
paramInformer, paramScope, configurationError := s.ensureParamsForPolicyLocked(parsedParamKind)
|
||||
result = append(result, PolicyHook[P, B, E]{
|
||||
Policy: policySpec,
|
||||
Bindings: bindingSpecs,
|
||||
Evaluator: s.compilePolicyLocked(policySpec),
|
||||
ParamInformer: paramInformer,
|
||||
ParamScope: paramScope,
|
||||
ConfigurationError: configurationError,
|
||||
})
|
||||
|
||||
// Should queue a re-sync for policy sync error. If our shared param
|
||||
// informer can notify us when CRD discovery changes we can remove this
|
||||
// and just rely on the informer to notify us when the CRDs change
|
||||
if configurationError != nil {
|
||||
errs = append(errs, configurationError)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up orphaned policies by replacing the old cache of compiled policies
|
||||
// (the map of used policies is updated by `compilePolicy`)
|
||||
for policyKey := range s.compiledPolicies {
|
||||
if _, wasSeen := policiesToBindings[policyKey]; !wasSeen {
|
||||
delete(s.compiledPolicies, policyKey)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up orphaned param informers
|
||||
for paramKind, info := range s.paramsCRDControllers {
|
||||
if _, wasSeen := usedParams[paramKind]; !wasSeen {
|
||||
info.cancelFunc()
|
||||
delete(s.paramsCRDControllers, paramKind)
|
||||
}
|
||||
}
|
||||
|
||||
err = nil
|
||||
if len(errs) > 0 {
|
||||
err = goerrors.Join(errs...)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// ensureParamsForPolicyLocked ensures that the informer for the paramKind is
|
||||
// started and returns the informer and the scope of the paramKind.
|
||||
//
|
||||
// Must be called under write lock
|
||||
func (s *policySource[P, B, E]) ensureParamsForPolicyLocked(paramSource *schema.GroupVersionKind) (informers.GenericInformer, meta.RESTScope, error) {
|
||||
if paramSource == nil {
|
||||
return nil, nil, nil
|
||||
} else if info, ok := s.paramsCRDControllers[*paramSource]; ok {
|
||||
return info.informer, info.mapping.Scope, nil
|
||||
}
|
||||
|
||||
mapping, err := s.restMapper.RESTMapping(schema.GroupKind{
|
||||
Group: paramSource.Group,
|
||||
Kind: paramSource.Kind,
|
||||
}, paramSource.Version)
|
||||
|
||||
if err != nil {
|
||||
// Failed to resolve. Return error so we retry again (rate limited)
|
||||
// Save a record of this definition with an evaluator that unconditionally
|
||||
return nil, nil, fmt.Errorf("failed to find resource referenced by paramKind: '%v'", *paramSource)
|
||||
}
|
||||
|
||||
// We are not watching this param. Start an informer for it.
|
||||
instanceContext, instanceCancel := context.WithCancel(s.ctx)
|
||||
|
||||
var informer informers.GenericInformer
|
||||
|
||||
// Try to see if our provided informer factory has an informer for this type.
|
||||
// We assume the informer is already started, and starts all types associated
|
||||
// with it.
|
||||
if genericInformer, err := s.informerFactory.ForResource(mapping.Resource); err == nil {
|
||||
informer = genericInformer
|
||||
|
||||
// Start the informer
|
||||
s.informerFactory.Start(instanceContext.Done())
|
||||
|
||||
} else {
|
||||
// Dynamic JSON informer fallback.
|
||||
// Cannot use shared dynamic informer since it would be impossible
|
||||
// to clean CRD informers properly with multiple dependents
|
||||
// (cannot start ahead of time, and cannot track dependencies via stopCh)
|
||||
informer = dynamicinformer.NewFilteredDynamicInformer(
|
||||
s.dynamicClient,
|
||||
mapping.Resource,
|
||||
corev1.NamespaceAll,
|
||||
// Use same interval as is used for k8s typed sharedInformerFactory
|
||||
// https://github.com/kubernetes/kubernetes/blob/7e0923899fed622efbc8679cca6b000d43633e38/cmd/kube-apiserver/app/server.go#L430
|
||||
10*time.Minute,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
nil,
|
||||
)
|
||||
go informer.Informer().Run(instanceContext.Done())
|
||||
}
|
||||
|
||||
klog.Infof("informer started for %v", *paramSource)
|
||||
ret := ¶mInfo{
|
||||
mapping: *mapping,
|
||||
cancelFunc: instanceCancel,
|
||||
informer: informer,
|
||||
}
|
||||
s.paramsCRDControllers[*paramSource] = ret
|
||||
return ret.informer, mapping.Scope, nil
|
||||
}
|
||||
|
||||
// For testing
|
||||
func (s *policySource[P, B, E]) getParamInformer(param schema.GroupVersionKind) (informers.GenericInformer, meta.RESTScope) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if info, ok := s.paramsCRDControllers[param]; ok {
|
||||
return info.informer, info.mapping.Scope
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// compilePolicyLocked compiles the policy and returns the evaluator for it.
|
||||
// If the policy has not changed since the last compilation, it will return
|
||||
// the cached evaluator.
|
||||
//
|
||||
// Must be called under write lock
|
||||
func (s *policySource[P, B, E]) compilePolicyLocked(policySpec P) E {
|
||||
policyMeta, err := meta.Accessor(policySpec)
|
||||
if err != nil {
|
||||
// This should not happen if P, and B have ObjectMeta, but
|
||||
// unfortunately there is no way to express "able to call
|
||||
// meta.Accessor" as a type constraint
|
||||
utilruntime.HandleError(err)
|
||||
var emptyEvaluator E
|
||||
return emptyEvaluator
|
||||
}
|
||||
key := types.NamespacedName{
|
||||
Namespace: policyMeta.GetNamespace(),
|
||||
Name: policyMeta.GetName(),
|
||||
}
|
||||
|
||||
compiledPolicy, wasCompiled := s.compiledPolicies[key]
|
||||
|
||||
// If the policy or binding has changed since it was last compiled,
|
||||
// and if there is no configuration error (like a missing param CRD)
|
||||
// then we recompile
|
||||
if !wasCompiled ||
|
||||
compiledPolicy.policyVersion != policyMeta.GetResourceVersion() {
|
||||
|
||||
compiledPolicy = compiledPolicyEntry[E]{
|
||||
policyVersion: policyMeta.GetResourceVersion(),
|
||||
evaluator: s.compiler(policySpec),
|
||||
}
|
||||
s.compiledPolicies[key] = compiledPolicy
|
||||
}
|
||||
|
||||
return compiledPolicy.evaluator
|
||||
}
|
639
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_test_context.go
generated
vendored
Normal file
639
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_test_context.go
generated
vendored
Normal file
@ -0,0 +1,639 @@
|
||||
/*
|
||||
Copyright 2024 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 generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/dynamic"
|
||||
dynamicfake "k8s.io/client-go/dynamic/fake"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/component-base/featuregate"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
)
|
||||
|
||||
// PolicyTestContext is everything you need to unit test a policy plugin
|
||||
type PolicyTestContext[P runtime.Object, B runtime.Object, E Evaluator] struct {
|
||||
context.Context
|
||||
Plugin *Plugin[PolicyHook[P, B, E]]
|
||||
Source Source[PolicyHook[P, B, E]]
|
||||
Start func() error
|
||||
|
||||
scheme *runtime.Scheme
|
||||
restMapper *meta.DefaultRESTMapper
|
||||
policyGVR schema.GroupVersionResource
|
||||
bindingGVR schema.GroupVersionResource
|
||||
|
||||
policyGVK schema.GroupVersionKind
|
||||
bindingGVK schema.GroupVersionKind
|
||||
|
||||
nativeTracker clienttesting.ObjectTracker
|
||||
policyAndBindingTracker clienttesting.ObjectTracker
|
||||
unstructuredTracker clienttesting.ObjectTracker
|
||||
}
|
||||
|
||||
func NewPolicyTestContext[P, B runtime.Object, E Evaluator](
|
||||
newPolicyAccessor func(P) PolicyAccessor,
|
||||
newBindingAccessor func(B) BindingAccessor,
|
||||
compileFunc func(P) E,
|
||||
dispatcher dispatcherFactory[PolicyHook[P, B, E]],
|
||||
initialObjects []runtime.Object,
|
||||
paramMappings []meta.RESTMapping,
|
||||
) (*PolicyTestContext[P, B, E], func(), error) {
|
||||
var Pexample P
|
||||
var Bexample B
|
||||
|
||||
// Create a fake resource and kind for the provided policy and binding types
|
||||
fakePolicyGVR := schema.GroupVersionResource{
|
||||
Group: "policy.example.com",
|
||||
Version: "v1",
|
||||
Resource: "fakepolicies",
|
||||
}
|
||||
fakeBindingGVR := schema.GroupVersionResource{
|
||||
Group: "policy.example.com",
|
||||
Version: "v1",
|
||||
Resource: "fakebindings",
|
||||
}
|
||||
fakePolicyGVK := fakePolicyGVR.GroupVersion().WithKind("FakePolicy")
|
||||
fakeBindingGVK := fakeBindingGVR.GroupVersion().WithKind("FakeBinding")
|
||||
|
||||
policySourceTestScheme, err := func() (*runtime.Scheme, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
if err := fake.AddToScheme(scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scheme.AddKnownTypeWithName(fakePolicyGVK, Pexample)
|
||||
scheme.AddKnownTypeWithName(fakeBindingGVK, Bexample)
|
||||
scheme.AddKnownTypeWithName(fakePolicyGVK.GroupVersion().WithKind(fakePolicyGVK.Kind+"List"), &FakeList[P]{})
|
||||
scheme.AddKnownTypeWithName(fakeBindingGVK.GroupVersion().WithKind(fakeBindingGVK.Kind+"List"), &FakeList[B]{})
|
||||
|
||||
for _, mapping := range paramMappings {
|
||||
// Skip if it is in the scheme already
|
||||
if scheme.Recognizes(mapping.GroupVersionKind) {
|
||||
continue
|
||||
}
|
||||
scheme.AddKnownTypeWithName(mapping.GroupVersionKind, &unstructured.Unstructured{})
|
||||
scheme.AddKnownTypeWithName(mapping.GroupVersionKind.GroupVersion().WithKind(mapping.GroupVersionKind.Kind+"List"), &unstructured.UnstructuredList{})
|
||||
}
|
||||
|
||||
return scheme, nil
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fakeRestMapper := func() *meta.DefaultRESTMapper {
|
||||
res := meta.NewDefaultRESTMapper([]schema.GroupVersion{
|
||||
{
|
||||
Group: "",
|
||||
Version: "v1",
|
||||
},
|
||||
})
|
||||
|
||||
res.Add(fakePolicyGVK, meta.RESTScopeRoot)
|
||||
res.Add(fakeBindingGVK, meta.RESTScopeRoot)
|
||||
res.Add(corev1.SchemeGroupVersion.WithKind("ConfigMap"), meta.RESTScopeNamespace)
|
||||
|
||||
for _, mapping := range paramMappings {
|
||||
res.AddSpecific(mapping.GroupVersionKind, mapping.Resource, mapping.Resource, mapping.Scope)
|
||||
}
|
||||
|
||||
return res
|
||||
}()
|
||||
|
||||
nativeClient := fake.NewSimpleClientset()
|
||||
dynamicClient := dynamicfake.NewSimpleDynamicClient(policySourceTestScheme)
|
||||
fakeInformerFactory := informers.NewSharedInformerFactory(nativeClient, 30*time.Second)
|
||||
|
||||
// Make an object tracker specifically for our policies and bindings
|
||||
policiesAndBindingsTracker := clienttesting.NewObjectTracker(
|
||||
policySourceTestScheme,
|
||||
serializer.NewCodecFactory(policySourceTestScheme).UniversalDecoder())
|
||||
|
||||
// Make an informer for our policies and bindings
|
||||
|
||||
policyInformer := cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return policiesAndBindingsTracker.List(fakePolicyGVR, fakePolicyGVK, "")
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return policiesAndBindingsTracker.Watch(fakePolicyGVR, "")
|
||||
},
|
||||
},
|
||||
Pexample,
|
||||
30*time.Second,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
)
|
||||
bindingInformer := cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return policiesAndBindingsTracker.List(fakeBindingGVR, fakeBindingGVK, "")
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return policiesAndBindingsTracker.Watch(fakeBindingGVR, "")
|
||||
},
|
||||
},
|
||||
Bexample,
|
||||
30*time.Second,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
)
|
||||
|
||||
var source Source[PolicyHook[P, B, E]]
|
||||
plugin := NewPlugin[PolicyHook[P, B, E]](
|
||||
admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update),
|
||||
func(sif informers.SharedInformerFactory, i1 kubernetes.Interface, i2 dynamic.Interface, r meta.RESTMapper) Source[PolicyHook[P, B, E]] {
|
||||
source = NewPolicySource[P, B, E](
|
||||
policyInformer,
|
||||
bindingInformer,
|
||||
newPolicyAccessor,
|
||||
newBindingAccessor,
|
||||
compileFunc,
|
||||
sif,
|
||||
i2,
|
||||
r,
|
||||
)
|
||||
return source
|
||||
}, dispatcher)
|
||||
plugin.SetEnabled(true)
|
||||
|
||||
featureGate := featuregate.NewFeatureGate()
|
||||
err = featureGate.Add(map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
//!TODO: move this to validating specific tests
|
||||
features.ValidatingAdmissionPolicy: {
|
||||
Default: true, PreRelease: featuregate.Beta}})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = featureGate.SetFromMap(map[string]bool{string(features.ValidatingAdmissionPolicy): true})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
testContext, testCancel := context.WithCancel(context.Background())
|
||||
genericInitializer := initializer.New(
|
||||
nativeClient,
|
||||
dynamicClient,
|
||||
fakeInformerFactory,
|
||||
fakeAuthorizer{},
|
||||
featureGate,
|
||||
testContext.Done(),
|
||||
fakeRestMapper,
|
||||
)
|
||||
genericInitializer.Initialize(plugin)
|
||||
plugin.SetRESTMapper(fakeRestMapper)
|
||||
|
||||
if err := plugin.ValidateInitialization(); err != nil {
|
||||
testCancel()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
res := &PolicyTestContext[P, B, E]{
|
||||
Context: testContext,
|
||||
Plugin: plugin,
|
||||
Source: source,
|
||||
|
||||
restMapper: fakeRestMapper,
|
||||
scheme: policySourceTestScheme,
|
||||
policyGVK: fakePolicyGVK,
|
||||
bindingGVK: fakeBindingGVK,
|
||||
policyGVR: fakePolicyGVR,
|
||||
bindingGVR: fakeBindingGVR,
|
||||
nativeTracker: nativeClient.Tracker(),
|
||||
policyAndBindingTracker: policiesAndBindingsTracker,
|
||||
unstructuredTracker: dynamicClient.Tracker(),
|
||||
}
|
||||
|
||||
for _, obj := range initialObjects {
|
||||
err := res.updateOne(obj)
|
||||
if err != nil {
|
||||
testCancel()
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
res.Start = func() error {
|
||||
fakeInformerFactory.Start(res.Done())
|
||||
go policyInformer.Run(res.Done())
|
||||
go bindingInformer.Run(res.Done())
|
||||
|
||||
if !cache.WaitForCacheSync(res.Done(), res.Source.HasSynced) {
|
||||
return fmt.Errorf("timed out waiting for initial cache sync")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return res, testCancel, nil
|
||||
}
|
||||
|
||||
// UpdateAndWait updates the given object in the test, or creates it if it doesn't exist
|
||||
// Depending upon object type, waits afterward until the object is synced
|
||||
// by the policy source
|
||||
//
|
||||
// Be aware the UpdateAndWait will modify the ResourceVersion of the
|
||||
// provided objects.
|
||||
func (p *PolicyTestContext[P, B, E]) UpdateAndWait(objects ...runtime.Object) error {
|
||||
return p.update(true, objects...)
|
||||
}
|
||||
|
||||
// Update updates the given object in the test, or creates it if it doesn't exist
|
||||
//
|
||||
// Be aware the Update will modify the ResourceVersion of the
|
||||
// provided objects.
|
||||
func (p *PolicyTestContext[P, B, E]) Update(objects ...runtime.Object) error {
|
||||
return p.update(false, objects...)
|
||||
}
|
||||
|
||||
// Objects the given object in the test, or creates it if it doesn't exist
|
||||
// Depending upon object type, waits afterward until the object is synced
|
||||
// by the policy source
|
||||
func (p *PolicyTestContext[P, B, E]) update(wait bool, objects ...runtime.Object) error {
|
||||
for _, object := range objects {
|
||||
if err := p.updateOne(object); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if wait {
|
||||
timeoutCtx, timeoutCancel := context.WithTimeout(p, 3*time.Second)
|
||||
defer timeoutCancel()
|
||||
|
||||
for _, object := range objects {
|
||||
if err := p.WaitForReconcile(timeoutCtx, object); err != nil {
|
||||
return fmt.Errorf("error waiting for reconcile of %v: %v", object, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Depending upon object type, waits afterward until the object is synced
|
||||
// by the policy source. Note that policies that are not bound are skipped,
|
||||
// so you should not try to wait for an unbound policy. Create both the binding
|
||||
// and policy, then wait.
|
||||
func (p *PolicyTestContext[P, B, E]) WaitForReconcile(timeoutCtx context.Context, object runtime.Object) error {
|
||||
if !p.Source.HasSynced() {
|
||||
return nil
|
||||
}
|
||||
|
||||
objectMeta, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objectGVK, _, err := p.inferGVK(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch objectGVK {
|
||||
case p.policyGVK:
|
||||
return wait.PollUntilContextCancel(timeoutCtx, 100*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
||||
policies := p.Source.Hooks()
|
||||
for _, policy := range policies {
|
||||
policyMeta, err := meta.Accessor(policy.Policy)
|
||||
if err != nil {
|
||||
return true, err
|
||||
} else if policyMeta.GetName() == objectMeta.GetName() && policyMeta.GetResourceVersion() == objectMeta.GetResourceVersion() {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
case p.bindingGVK:
|
||||
return wait.PollUntilContextCancel(timeoutCtx, 100*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
||||
policies := p.Source.Hooks()
|
||||
for _, policy := range policies {
|
||||
for _, binding := range policy.Bindings {
|
||||
bindingMeta, err := meta.Accessor(binding)
|
||||
if err != nil {
|
||||
return true, err
|
||||
} else if bindingMeta.GetName() == objectMeta.GetName() && bindingMeta.GetResourceVersion() == objectMeta.GetResourceVersion() {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
default:
|
||||
// Do nothing, params are visible immediately
|
||||
// Loop until one of the params is visible via get of the param informer
|
||||
return wait.PollUntilContextCancel(timeoutCtx, 100*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
||||
informer, scope := p.Source.(*policySource[P, B, E]).getParamInformer(objectGVK)
|
||||
if informer == nil {
|
||||
// Informer does not exist yet, keep waiting for sync
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !cache.WaitForCacheSync(timeoutCtx.Done(), informer.Informer().HasSynced) {
|
||||
return false, fmt.Errorf("timed out waiting for cache sync of param informer")
|
||||
}
|
||||
|
||||
var lister cache.GenericNamespaceLister = informer.Lister()
|
||||
if scope == meta.RESTScopeNamespace {
|
||||
lister = informer.Lister().ByNamespace(objectMeta.GetNamespace())
|
||||
}
|
||||
|
||||
fetched, err := lister.Get(objectMeta.GetName())
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return false, nil
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
// Ensure RV matches
|
||||
fetchedMeta, err := meta.Accessor(fetched)
|
||||
if err != nil {
|
||||
return true, err
|
||||
} else if fetchedMeta.GetResourceVersion() != objectMeta.GetResourceVersion() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PolicyTestContext[P, B, E]) waitForDelete(ctx context.Context, objectGVK schema.GroupVersionKind, name types.NamespacedName) error {
|
||||
srce := p.Source.(*policySource[P, B, E])
|
||||
|
||||
return wait.PollUntilContextCancel(ctx, 100*time.Millisecond, true, func(ctx context.Context) (done bool, err error) {
|
||||
switch objectGVK {
|
||||
case p.policyGVK:
|
||||
for _, hook := range p.Source.Hooks() {
|
||||
accessor := srce.newPolicyAccessor(hook.Policy)
|
||||
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
case p.bindingGVK:
|
||||
for _, hook := range p.Source.Hooks() {
|
||||
for _, binding := range hook.Bindings {
|
||||
accessor := srce.newBindingAccessor(binding)
|
||||
if accessor.GetName() == name.Name && accessor.GetNamespace() == name.Namespace {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
default:
|
||||
// Do nothing, params are visible immediately
|
||||
// Loop until one of the params is visible via get of the param informer
|
||||
informer, scope := p.Source.(*policySource[P, B, E]).getParamInformer(objectGVK)
|
||||
if informer == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var lister cache.GenericNamespaceLister = informer.Lister()
|
||||
if scope == meta.RESTScopeNamespace {
|
||||
lister = informer.Lister().ByNamespace(name.Namespace)
|
||||
}
|
||||
|
||||
_, err = lister.Get(name.Name)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (p *PolicyTestContext[P, B, E]) updateOne(object runtime.Object) error {
|
||||
objectMeta, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectMeta.SetResourceVersion(string(uuid.NewUUID()))
|
||||
objectGVK, gvr, err := p.inferGVK(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch objectGVK {
|
||||
case p.policyGVK:
|
||||
err := p.policyAndBindingTracker.Update(p.policyGVR, object, objectMeta.GetNamespace())
|
||||
if errors.IsNotFound(err) {
|
||||
err = p.policyAndBindingTracker.Create(p.policyGVR, object, objectMeta.GetNamespace())
|
||||
}
|
||||
|
||||
return err
|
||||
case p.bindingGVK:
|
||||
err := p.policyAndBindingTracker.Update(p.bindingGVR, object, objectMeta.GetNamespace())
|
||||
if errors.IsNotFound(err) {
|
||||
err = p.policyAndBindingTracker.Create(p.bindingGVR, object, objectMeta.GetNamespace())
|
||||
}
|
||||
|
||||
return err
|
||||
default:
|
||||
if _, ok := object.(*unstructured.Unstructured); ok {
|
||||
if err := p.unstructuredTracker.Create(gvr, object, objectMeta.GetNamespace()); err != nil {
|
||||
if errors.IsAlreadyExists(err) {
|
||||
return p.unstructuredTracker.Update(gvr, object, objectMeta.GetNamespace())
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
} else if err := p.nativeTracker.Create(gvr, object, objectMeta.GetNamespace()); err != nil {
|
||||
if errors.IsAlreadyExists(err) {
|
||||
return p.nativeTracker.Update(gvr, object, objectMeta.GetNamespace())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Depending upon object type, waits afterward until the object is synced
|
||||
// by the policy source
|
||||
func (p *PolicyTestContext[P, B, E]) DeleteAndWait(object ...runtime.Object) error {
|
||||
for _, object := range object {
|
||||
if err := p.deleteOne(object); err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
timeoutCtx, timeoutCancel := context.WithTimeout(p, 3*time.Second)
|
||||
defer timeoutCancel()
|
||||
|
||||
for _, object := range object {
|
||||
accessor, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objectGVK, _, err := p.inferGVK(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.waitForDelete(
|
||||
timeoutCtx,
|
||||
objectGVK,
|
||||
types.NamespacedName{Name: accessor.GetName(), Namespace: accessor.GetNamespace()}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PolicyTestContext[P, B, E]) deleteOne(object runtime.Object) error {
|
||||
objectMeta, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectMeta.SetResourceVersion(string(uuid.NewUUID()))
|
||||
objectGVK, gvr, err := p.inferGVK(object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch objectGVK {
|
||||
case p.policyGVK:
|
||||
return p.policyAndBindingTracker.Delete(p.policyGVR, objectMeta.GetNamespace(), objectMeta.GetName())
|
||||
case p.bindingGVK:
|
||||
return p.policyAndBindingTracker.Delete(p.bindingGVR, objectMeta.GetNamespace(), objectMeta.GetName())
|
||||
default:
|
||||
if _, ok := object.(*unstructured.Unstructured); ok {
|
||||
return p.unstructuredTracker.Delete(gvr, objectMeta.GetNamespace(), objectMeta.GetName())
|
||||
}
|
||||
return p.nativeTracker.Delete(gvr, objectMeta.GetNamespace(), objectMeta.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PolicyTestContext[P, B, E]) Dispatch(
|
||||
new, old runtime.Object,
|
||||
operation admission.Operation,
|
||||
) error {
|
||||
if old == nil && new == nil {
|
||||
return fmt.Errorf("both old and new objects cannot be nil")
|
||||
}
|
||||
|
||||
nonNilObject := new
|
||||
if nonNilObject == nil {
|
||||
nonNilObject = old
|
||||
}
|
||||
|
||||
gvk, gvr, err := p.inferGVK(nonNilObject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nonNilMeta, err := meta.Accessor(nonNilObject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Plugin.Dispatch(
|
||||
p,
|
||||
admission.NewAttributesRecord(
|
||||
new,
|
||||
old,
|
||||
gvk,
|
||||
nonNilMeta.GetName(),
|
||||
nonNilMeta.GetNamespace(),
|
||||
gvr,
|
||||
"",
|
||||
operation,
|
||||
nil,
|
||||
false,
|
||||
nil,
|
||||
), admission.NewObjectInterfacesFromScheme(p.scheme))
|
||||
}
|
||||
|
||||
func (p *PolicyTestContext[P, B, E]) inferGVK(object runtime.Object) (schema.GroupVersionKind, schema.GroupVersionResource, error) {
|
||||
objectGVK := object.GetObjectKind().GroupVersionKind()
|
||||
if objectGVK.Empty() {
|
||||
// If the object doesn't have a GVK, ask the schema for preferred GVK
|
||||
knownKinds, _, err := p.scheme.ObjectKinds(object)
|
||||
if err != nil {
|
||||
return schema.GroupVersionKind{}, schema.GroupVersionResource{}, err
|
||||
} else if len(knownKinds) == 0 {
|
||||
return schema.GroupVersionKind{}, schema.GroupVersionResource{}, fmt.Errorf("no known GVKs for object in schema: %T", object)
|
||||
}
|
||||
toTake := 0
|
||||
|
||||
// Prefer GVK if it is our fake policy or binding
|
||||
for i, knownKind := range knownKinds {
|
||||
if knownKind == p.policyGVK || knownKind == p.bindingGVK {
|
||||
toTake = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
objectGVK = knownKinds[toTake]
|
||||
}
|
||||
|
||||
// Make sure GVK is known to the fake rest mapper. To prevent cryptic error
|
||||
mapping, err := p.restMapper.RESTMapping(objectGVK.GroupKind(), objectGVK.Version)
|
||||
if err != nil {
|
||||
return schema.GroupVersionKind{}, schema.GroupVersionResource{}, err
|
||||
}
|
||||
return objectGVK, mapping.Resource, nil
|
||||
}
|
||||
|
||||
type FakeList[T runtime.Object] struct {
|
||||
metav1.TypeMeta
|
||||
metav1.ListMeta
|
||||
Items []T
|
||||
}
|
||||
|
||||
func (fl *FakeList[P]) DeepCopyObject() runtime.Object {
|
||||
copiedItems := make([]P, len(fl.Items))
|
||||
for i, item := range fl.Items {
|
||||
copiedItems[i] = item.DeepCopyObject().(P)
|
||||
}
|
||||
return &FakeList[P]{
|
||||
TypeMeta: fl.TypeMeta,
|
||||
ListMeta: fl.ListMeta,
|
||||
Items: copiedItems,
|
||||
}
|
||||
}
|
||||
|
||||
type fakeAuthorizer struct{}
|
||||
|
||||
func (f fakeAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
@ -28,6 +28,10 @@ type informer[T runtime.Object] struct {
|
||||
lister[T]
|
||||
}
|
||||
|
||||
// Creates a generic informer around a type-erased cache.SharedIndexInformer
|
||||
// It is incumbent on the caller to ensure that the generic type argument is
|
||||
// consistent with the type of the objects stored inside the SharedIndexInformer
|
||||
// as they will be casted.
|
||||
func NewInformer[T runtime.Object](informe cache.SharedIndexInformer) Informer[T] {
|
||||
return informer[T]{
|
||||
SharedIndexInformer: informe,
|
@ -20,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
@ -36,7 +35,7 @@ type MatchCriteria interface {
|
||||
namespace.NamespaceSelectorProvider
|
||||
object.ObjectSelectorProvider
|
||||
|
||||
GetMatchResources() v1beta1.MatchResources
|
||||
GetMatchResources() v1.MatchResources
|
||||
}
|
||||
|
||||
// Matcher decides if a request matches against matchCriteria
|
||||
@ -121,7 +120,7 @@ func (m *Matcher) Matches(attr admission.Attributes, o admission.ObjectInterface
|
||||
return true, matchResource, matchKind, nil
|
||||
}
|
||||
|
||||
func matchesResourceRules(namedRules []v1beta1.NamedRuleWithOperations, matchPolicy *v1beta1.MatchPolicyType, attr admission.Attributes, o admission.ObjectInterfaces) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error) {
|
||||
func matchesResourceRules(namedRules []v1.NamedRuleWithOperations, matchPolicy *v1.MatchPolicyType, attr admission.Attributes, o admission.ObjectInterfaces) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error) {
|
||||
matchKind := attr.GetKind()
|
||||
matchResource := attr.GetResource()
|
||||
|
||||
@ -150,7 +149,7 @@ func matchesResourceRules(namedRules []v1beta1.NamedRuleWithOperations, matchPol
|
||||
|
||||
// if match policy is undefined or exact, don't perform fuzzy matching
|
||||
// note that defaulting to fuzzy matching is set by the API
|
||||
if matchPolicy == nil || *matchPolicy == v1beta1.Exact {
|
||||
if matchPolicy == nil || *matchPolicy == v1.Exact {
|
||||
return false, schema.GroupVersionResource{}, schema.GroupVersionKind{}, nil
|
||||
}
|
||||
|
82
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/validating/accessor.go
generated
vendored
Normal file
82
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/validating/accessor.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright 2024 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 validating
|
||||
|
||||
import (
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
|
||||
)
|
||||
|
||||
func NewValidatingAdmissionPolicyAccessor(obj *v1.ValidatingAdmissionPolicy) generic.PolicyAccessor {
|
||||
return &validatingAdmissionPolicyAccessor{
|
||||
ValidatingAdmissionPolicy: obj,
|
||||
}
|
||||
}
|
||||
|
||||
func NewValidatingAdmissionPolicyBindingAccessor(obj *v1.ValidatingAdmissionPolicyBinding) generic.BindingAccessor {
|
||||
return &validatingAdmissionPolicyBindingAccessor{
|
||||
ValidatingAdmissionPolicyBinding: obj,
|
||||
}
|
||||
}
|
||||
|
||||
type validatingAdmissionPolicyAccessor struct {
|
||||
*v1.ValidatingAdmissionPolicy
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyAccessor) GetNamespace() string {
|
||||
return v.Namespace
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyAccessor) GetName() string {
|
||||
return v.Name
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyAccessor) GetParamKind() *v1.ParamKind {
|
||||
return v.Spec.ParamKind
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyAccessor) GetMatchConstraints() *v1.MatchResources {
|
||||
return v.Spec.MatchConstraints
|
||||
}
|
||||
|
||||
type validatingAdmissionPolicyBindingAccessor struct {
|
||||
*v1.ValidatingAdmissionPolicyBinding
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyBindingAccessor) GetNamespace() string {
|
||||
return v.Namespace
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyBindingAccessor) GetName() string {
|
||||
return v.Name
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyBindingAccessor) GetPolicyName() types.NamespacedName {
|
||||
return types.NamespacedName{
|
||||
Namespace: "",
|
||||
Name: v.Spec.PolicyName,
|
||||
}
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyBindingAccessor) GetMatchResources() *v1.MatchResources {
|
||||
return v.Spec.MatchResources
|
||||
}
|
||||
|
||||
func (v *validatingAdmissionPolicyBindingAccessor) GetParamRef() *v1.ParamRef {
|
||||
return v.Spec.ParamRef
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
@ -14,199 +14,75 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utiljson "k8s.io/apimachinery/pkg/util/json"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
celmetrics "k8s.io/apiserver/pkg/admission/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/matching"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
|
||||
celmetrics "k8s.io/apiserver/pkg/admission/plugin/policy/validating/metrics"
|
||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/warning"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var _ CELPolicyEvaluator = &celAdmissionController{}
|
||||
|
||||
// celAdmissionController is the top-level controller for admission control using CEL
|
||||
// it is responsible for watching policy definitions, bindings, and config param CRDs
|
||||
type celAdmissionController struct {
|
||||
// Controller which manages book-keeping for the cluster's dynamic policy
|
||||
// information.
|
||||
policyController *policyController
|
||||
|
||||
// atomic []policyData
|
||||
// list of every known policy definition, and all informatoin required to
|
||||
// validate its bindings against an object.
|
||||
// A snapshot of the current policy configuration is synced with this field
|
||||
// asynchronously
|
||||
definitions atomic.Value
|
||||
|
||||
authz authorizer.Authorizer
|
||||
type dispatcher struct {
|
||||
matcher generic.PolicyMatcher
|
||||
authz authorizer.Authorizer
|
||||
}
|
||||
|
||||
// Everything someone might need to validate a single ValidatingPolicyDefinition
|
||||
// against all of its registered bindings.
|
||||
type policyData struct {
|
||||
definitionInfo
|
||||
paramInfo
|
||||
bindings []bindingInfo
|
||||
var _ generic.Dispatcher[PolicyHook] = &dispatcher{}
|
||||
|
||||
func NewDispatcher(
|
||||
authorizer authorizer.Authorizer,
|
||||
matcher generic.PolicyMatcher,
|
||||
) generic.Dispatcher[PolicyHook] {
|
||||
return &dispatcher{
|
||||
matcher: matcher,
|
||||
authz: authorizer,
|
||||
}
|
||||
}
|
||||
|
||||
// contains the cel PolicyDecisions along with the ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding
|
||||
// that determined the decision
|
||||
type policyDecisionWithMetadata struct {
|
||||
PolicyDecision
|
||||
Definition *v1beta1.ValidatingAdmissionPolicy
|
||||
Binding *v1beta1.ValidatingAdmissionPolicyBinding
|
||||
Definition *admissionregistrationv1.ValidatingAdmissionPolicy
|
||||
Binding *admissionregistrationv1.ValidatingAdmissionPolicyBinding
|
||||
}
|
||||
|
||||
// namespaceName is used as a key in definitionInfo and bindingInfos
|
||||
type namespacedName struct {
|
||||
namespace, name string
|
||||
}
|
||||
|
||||
type definitionInfo struct {
|
||||
// Error about the state of the definition's configuration and the cluster
|
||||
// preventing its enforcement or compilation.
|
||||
// Reset every reconciliation
|
||||
configurationError error
|
||||
|
||||
// Last value seen by this controller to be used in policy enforcement
|
||||
// May not be nil
|
||||
lastReconciledValue *v1beta1.ValidatingAdmissionPolicy
|
||||
}
|
||||
|
||||
type bindingInfo struct {
|
||||
// Compiled CEL expression turned into an validator
|
||||
validator Validator
|
||||
|
||||
// Last value seen by this controller to be used in policy enforcement
|
||||
// May not be nil
|
||||
lastReconciledValue *v1beta1.ValidatingAdmissionPolicyBinding
|
||||
}
|
||||
|
||||
type paramInfo struct {
|
||||
// Controller which is watching this param CRD
|
||||
controller generic.Controller[runtime.Object]
|
||||
|
||||
// Function to call to stop the informer and clean up the controller
|
||||
stop func()
|
||||
|
||||
// Whether this param is cluster or namespace scoped
|
||||
scope meta.RESTScope
|
||||
|
||||
// Policy Definitions which refer to this param CRD
|
||||
dependentDefinitions sets.Set[namespacedName]
|
||||
}
|
||||
|
||||
func NewAdmissionController(
|
||||
// Injected Dependencies
|
||||
informerFactory informers.SharedInformerFactory,
|
||||
client kubernetes.Interface,
|
||||
restMapper meta.RESTMapper,
|
||||
dynamicClient dynamic.Interface,
|
||||
authz authorizer.Authorizer,
|
||||
) CELPolicyEvaluator {
|
||||
return &celAdmissionController{
|
||||
definitions: atomic.Value{},
|
||||
policyController: newPolicyController(
|
||||
restMapper,
|
||||
client,
|
||||
dynamicClient,
|
||||
informerFactory,
|
||||
nil,
|
||||
NewMatcher(matching.NewMatcher(informerFactory.Core().V1().Namespaces().Lister(), client)),
|
||||
generic.NewInformer[*v1beta1.ValidatingAdmissionPolicy](
|
||||
informerFactory.Admissionregistration().V1beta1().ValidatingAdmissionPolicies().Informer()),
|
||||
generic.NewInformer[*v1beta1.ValidatingAdmissionPolicyBinding](
|
||||
informerFactory.Admissionregistration().V1beta1().ValidatingAdmissionPolicyBindings().Informer()),
|
||||
),
|
||||
authz: authz,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *celAdmissionController) Run(stopCh <-chan struct{}) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c.policyController.Run(ctx)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
// Wait indefinitely until policies/bindings are listed & handled before
|
||||
// allowing policies to be refreshed
|
||||
if !cache.WaitForNamedCacheSync("cel-admission-controller", ctx.Done(), c.policyController.HasSynced) {
|
||||
return
|
||||
}
|
||||
|
||||
// Loop every 1 second until context is cancelled, refreshing policies
|
||||
wait.Until(c.refreshPolicies, 1*time.Second, ctx.Done())
|
||||
}()
|
||||
|
||||
<-stopCh
|
||||
cancel()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
const maxAuditAnnotationValueLength = 10 * 1024
|
||||
|
||||
func (c *celAdmissionController) Validate(
|
||||
ctx context.Context,
|
||||
a admission.Attributes,
|
||||
o admission.ObjectInterfaces,
|
||||
) (err error) {
|
||||
if !c.HasSynced() {
|
||||
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
|
||||
}
|
||||
// Dispatch implements generic.Dispatcher.
|
||||
func (c *dispatcher) Dispatch(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces, hooks []PolicyHook) error {
|
||||
|
||||
var deniedDecisions []policyDecisionWithMetadata
|
||||
|
||||
addConfigError := func(err error, definition *v1beta1.ValidatingAdmissionPolicy, binding *v1beta1.ValidatingAdmissionPolicyBinding) {
|
||||
addConfigError := func(err error, definition *admissionregistrationv1.ValidatingAdmissionPolicy, binding *admissionregistrationv1.ValidatingAdmissionPolicyBinding) {
|
||||
// we always default the FailurePolicy if it is unset and validate it in API level
|
||||
var policy v1beta1.FailurePolicyType
|
||||
var policy admissionregistrationv1.FailurePolicyType
|
||||
if definition.Spec.FailurePolicy == nil {
|
||||
policy = v1beta1.Fail
|
||||
policy = admissionregistrationv1.Fail
|
||||
} else {
|
||||
policy = *definition.Spec.FailurePolicy
|
||||
}
|
||||
|
||||
// apply FailurePolicy specified in ValidatingAdmissionPolicy, the default would be Fail
|
||||
switch policy {
|
||||
case v1beta1.Ignore:
|
||||
case admissionregistrationv1.Ignore:
|
||||
// TODO: add metrics for ignored error here
|
||||
return
|
||||
case v1beta1.Fail:
|
||||
case admissionregistrationv1.Fail:
|
||||
var message string
|
||||
if binding == nil {
|
||||
message = fmt.Errorf("failed to configure policy: %w", err).Error()
|
||||
@ -232,19 +108,18 @@ func (c *celAdmissionController) Validate(
|
||||
})
|
||||
}
|
||||
}
|
||||
policyDatas := c.definitions.Load().([]policyData)
|
||||
|
||||
authz := newCachingAuthorizer(c.authz)
|
||||
|
||||
for _, definitionInfo := range policyDatas {
|
||||
for _, hook := range hooks {
|
||||
// versionedAttributes will be set to non-nil inside of the loop, but
|
||||
// is scoped outside of the param loop so we only convert once. We defer
|
||||
// conversion so that it is only performed when we know a policy matches,
|
||||
// saving the cost of converting non-matching requests.
|
||||
var versionedAttr *admission.VersionedAttributes
|
||||
|
||||
definition := definitionInfo.lastReconciledValue
|
||||
matches, matchResource, matchKind, err := c.policyController.matcher.DefinitionMatches(a, o, definition)
|
||||
definition := hook.Policy
|
||||
matches, matchResource, matchKind, err := c.matcher.DefinitionMatches(a, o, NewValidatingAdmissionPolicyAccessor(definition))
|
||||
if err != nil {
|
||||
// Configuration error.
|
||||
addConfigError(err, definition, nil)
|
||||
@ -253,18 +128,17 @@ func (c *celAdmissionController) Validate(
|
||||
if !matches {
|
||||
// Policy definition does not match request
|
||||
continue
|
||||
} else if definitionInfo.configurationError != nil {
|
||||
} else if hook.ConfigurationError != nil {
|
||||
// Configuration error.
|
||||
addConfigError(definitionInfo.configurationError, definition, nil)
|
||||
addConfigError(hook.ConfigurationError, definition, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
auditAnnotationCollector := newAuditAnnotationCollector()
|
||||
for _, bindingInfo := range definitionInfo.bindings {
|
||||
for _, binding := range hook.Bindings {
|
||||
// If the key is inside dependentBindings, there is guaranteed to
|
||||
// be a bindingInfo for it
|
||||
binding := bindingInfo.lastReconciledValue
|
||||
matches, err := c.policyController.matcher.BindingMatches(a, o, binding)
|
||||
matches, err := c.matcher.BindingMatches(a, o, NewValidatingAdmissionPolicyBindingAccessor(binding))
|
||||
if err != nil {
|
||||
// Configuration error.
|
||||
addConfigError(err, definition, binding)
|
||||
@ -274,7 +148,14 @@ func (c *celAdmissionController) Validate(
|
||||
continue
|
||||
}
|
||||
|
||||
params, err := c.collectParams(definition.Spec.ParamKind, definitionInfo.paramInfo, binding.Spec.ParamRef, a.GetNamespace())
|
||||
params, err := generic.CollectParams(
|
||||
hook.Policy.Spec.ParamKind,
|
||||
hook.ParamInformer,
|
||||
hook.ParamScope,
|
||||
binding.Spec.ParamRef,
|
||||
a.GetNamespace(),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
addConfigError(err, definition, binding)
|
||||
continue
|
||||
@ -303,7 +184,7 @@ func (c *celAdmissionController) Validate(
|
||||
// if it is cluster scoped, namespaceName will be empty
|
||||
// Otherwise, get the Namespace resource.
|
||||
if namespaceName != "" {
|
||||
namespace, err = c.policyController.matcher.GetNamespace(namespaceName)
|
||||
namespace, err = c.matcher.GetNamespace(namespaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -323,7 +204,18 @@ func (c *celAdmissionController) Validate(
|
||||
nested: param,
|
||||
}
|
||||
}
|
||||
validationResults = append(validationResults, bindingInfo.validator.Validate(ctx, matchResource, versionedAttr, p, namespace, celconfig.RuntimeCELCostBudget, authz))
|
||||
|
||||
validationResults = append(validationResults,
|
||||
hook.Evaluator.Validate(
|
||||
ctx,
|
||||
matchResource,
|
||||
versionedAttr,
|
||||
p,
|
||||
namespace,
|
||||
celconfig.RuntimeCELCostBudget,
|
||||
authz,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
for _, validationResult := range validationResults {
|
||||
@ -336,17 +228,17 @@ func (c *celAdmissionController) Validate(
|
||||
case ActionDeny:
|
||||
for _, action := range binding.Spec.ValidationActions {
|
||||
switch action {
|
||||
case v1beta1.Deny:
|
||||
case admissionregistrationv1.Deny:
|
||||
deniedDecisions = append(deniedDecisions, policyDecisionWithMetadata{
|
||||
Definition: definition,
|
||||
Binding: binding,
|
||||
PolicyDecision: decision,
|
||||
})
|
||||
celmetrics.Metrics.ObserveRejection(ctx, decision.Elapsed, definition.Name, binding.Name, "active")
|
||||
case v1beta1.Audit:
|
||||
c.publishValidationFailureAnnotation(binding, i, decision, versionedAttr)
|
||||
case admissionregistrationv1.Audit:
|
||||
publishValidationFailureAnnotation(binding, i, decision, versionedAttr)
|
||||
celmetrics.Metrics.ObserveAudit(ctx, decision.Elapsed, definition.Name, binding.Name, "active")
|
||||
case v1beta1.Warn:
|
||||
case admissionregistrationv1.Warn:
|
||||
warning.AddWarning(ctx, "", fmt.Sprintf("Validation failed for ValidatingAdmissionPolicy '%s' with binding '%s': %s", definition.Name, binding.Name, decision.Message))
|
||||
celmetrics.Metrics.ObserveWarn(ctx, decision.Elapsed, definition.Name, binding.Name, "active")
|
||||
}
|
||||
@ -410,127 +302,10 @@ func (c *celAdmissionController) Validate(
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns objects to use to evaluate the policy
|
||||
func (c *celAdmissionController) collectParams(
|
||||
paramKind *v1beta1.ParamKind,
|
||||
info paramInfo,
|
||||
paramRef *v1beta1.ParamRef,
|
||||
namespace string,
|
||||
) ([]runtime.Object, error) {
|
||||
// If definition has paramKind, paramRef is required in binding.
|
||||
// If definition has no paramKind, paramRef set in binding will be ignored.
|
||||
var params []runtime.Object
|
||||
var paramStore generic.NamespacedLister[runtime.Object]
|
||||
|
||||
// Make sure the param kind is ready to use
|
||||
if paramKind != nil && paramRef != nil {
|
||||
if info.controller == nil {
|
||||
return nil, fmt.Errorf("paramKind kind `%v` not known",
|
||||
paramKind.String())
|
||||
}
|
||||
|
||||
// Set up cluster-scoped, or namespaced access to the params
|
||||
// "default" if not provided, and paramKind is namespaced
|
||||
paramStore = info.controller.Informer()
|
||||
if info.scope.Name() == meta.RESTScopeNameNamespace {
|
||||
paramsNamespace := namespace
|
||||
if len(paramRef.Namespace) > 0 {
|
||||
paramsNamespace = paramRef.Namespace
|
||||
} else if len(paramsNamespace) == 0 {
|
||||
// You must supply namespace if your matcher can possibly
|
||||
// match a cluster-scoped resource
|
||||
return nil, fmt.Errorf("cannot use namespaced paramRef in policy binding that matches cluster-scoped resources")
|
||||
}
|
||||
|
||||
paramStore = info.controller.Informer().Namespaced(paramsNamespace)
|
||||
}
|
||||
|
||||
// If the param informer for this admission policy has not yet
|
||||
// had time to perform an initial listing, don't attempt to use
|
||||
// it.
|
||||
timeoutCtx, cancel := context.WithTimeout(c.policyController.context, 1*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if !cache.WaitForCacheSync(timeoutCtx.Done(), info.controller.HasSynced) {
|
||||
return nil, fmt.Errorf("paramKind kind `%v` not yet synced to use for admission",
|
||||
paramKind.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Find params to use with policy
|
||||
switch {
|
||||
case paramKind == nil:
|
||||
// ParamKind is unset. Ignore any globalParamRef or namespaceParamRef
|
||||
// setting.
|
||||
return []runtime.Object{nil}, nil
|
||||
case paramRef == nil:
|
||||
// Policy ParamKind is set, but binding does not use it.
|
||||
// Validate with nil params
|
||||
return []runtime.Object{nil}, nil
|
||||
case len(paramRef.Namespace) > 0 && info.scope.Name() == meta.RESTScopeRoot.Name():
|
||||
// Not allowed to set namespace for cluster-scoped param
|
||||
return nil, fmt.Errorf("paramRef.namespace must not be provided for a cluster-scoped `paramKind`")
|
||||
|
||||
case len(paramRef.Name) > 0:
|
||||
if paramRef.Selector != nil {
|
||||
// This should be validated, but just in case.
|
||||
return nil, fmt.Errorf("paramRef.name and paramRef.selector are mutually exclusive")
|
||||
}
|
||||
|
||||
switch param, err := paramStore.Get(paramRef.Name); {
|
||||
case err == nil:
|
||||
params = []runtime.Object{param}
|
||||
case k8serrors.IsNotFound(err):
|
||||
// Param not yet available. User may need to wait a bit
|
||||
// before being able to use it for validation.
|
||||
//
|
||||
// Set params to nil to prepare for not found action
|
||||
params = nil
|
||||
case k8serrors.IsInvalid(err):
|
||||
// Param mis-configured
|
||||
// require to set namespace for namespaced resource
|
||||
// and unset namespace for cluster scoped resource
|
||||
return nil, err
|
||||
default:
|
||||
// Internal error
|
||||
utilruntime.HandleError(err)
|
||||
return nil, err
|
||||
}
|
||||
case paramRef.Selector != nil:
|
||||
// Select everything by default if empty name and selector
|
||||
selector, err := metav1.LabelSelectorAsSelector(paramRef.Selector)
|
||||
if err != nil {
|
||||
// Cannot parse label selector: configuration error
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
paramList, err := paramStore.List(selector)
|
||||
if err != nil {
|
||||
// There was a bad internal error
|
||||
utilruntime.HandleError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Successfully grabbed params
|
||||
params = paramList
|
||||
default:
|
||||
// Should be unreachable due to validation
|
||||
return nil, fmt.Errorf("one of name or selector must be provided")
|
||||
}
|
||||
|
||||
// Apply fail action for params not found case
|
||||
if len(params) == 0 && paramRef.ParameterNotFoundAction != nil && *paramRef.ParameterNotFoundAction == v1beta1.DenyAction {
|
||||
return nil, errors.New("no params found for policy binding with `Deny` parameterNotFoundAction")
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *celAdmissionController) publishValidationFailureAnnotation(binding *v1beta1.ValidatingAdmissionPolicyBinding, expressionIndex int, decision PolicyDecision, attributes admission.Attributes) {
|
||||
func publishValidationFailureAnnotation(binding *admissionregistrationv1.ValidatingAdmissionPolicyBinding, expressionIndex int, decision PolicyDecision, attributes admission.Attributes) {
|
||||
key := "validation.policy.admission.k8s.io/validation_failure"
|
||||
// Marshal to a list of failures since, in the future, we may need to support multiple failures
|
||||
valueJson, err := utiljson.Marshal([]validationFailureValue{{
|
||||
valueJSON, err := utiljson.Marshal([]ValidationFailureValue{{
|
||||
ExpressionIndex: expressionIndex,
|
||||
Message: decision.Message,
|
||||
ValidationActions: binding.Spec.ValidationActions,
|
||||
@ -540,32 +315,22 @@ func (c *celAdmissionController) publishValidationFailureAnnotation(binding *v1b
|
||||
if err != nil {
|
||||
klog.Warningf("Failed to set admission audit annotation %s for ValidatingAdmissionPolicy %s and ValidatingAdmissionPolicyBinding %s: %v", key, binding.Spec.PolicyName, binding.Name, err)
|
||||
}
|
||||
value := string(valueJson)
|
||||
value := string(valueJSON)
|
||||
if err := attributes.AddAnnotation(key, value); err != nil {
|
||||
klog.Warningf("Failed to set admission audit annotation %s to %s for ValidatingAdmissionPolicy %s and ValidatingAdmissionPolicyBinding %s: %v", key, value, binding.Spec.PolicyName, binding.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *celAdmissionController) HasSynced() bool {
|
||||
return c.policyController.HasSynced() && c.definitions.Load() != nil
|
||||
}
|
||||
|
||||
func (c *celAdmissionController) ValidateInitialization() error {
|
||||
return c.policyController.matcher.ValidateInitialization()
|
||||
}
|
||||
|
||||
func (c *celAdmissionController) refreshPolicies() {
|
||||
c.definitions.Store(c.policyController.latestPolicyData())
|
||||
}
|
||||
const maxAuditAnnotationValueLength = 10 * 1024
|
||||
|
||||
// validationFailureValue defines the JSON format of a "validation.policy.admission.k8s.io/validation_failure" audit
|
||||
// annotation value.
|
||||
type validationFailureValue struct {
|
||||
Message string `json:"message"`
|
||||
Policy string `json:"policy"`
|
||||
Binding string `json:"binding"`
|
||||
ExpressionIndex int `json:"expressionIndex"`
|
||||
ValidationActions []v1beta1.ValidationAction `json:"validationActions"`
|
||||
type ValidationFailureValue struct {
|
||||
Message string `json:"message"`
|
||||
Policy string `json:"policy"`
|
||||
Binding string `json:"binding"`
|
||||
ExpressionIndex int `json:"expressionIndex"`
|
||||
ValidationActions []admissionregistrationv1.ValidationAction `json:"validationActions"`
|
||||
}
|
||||
|
||||
type auditAnnotationCollector struct {
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
@ -14,14 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
celgo "github.com/google/cel-go/cel"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -80,23 +79,6 @@ func (v *Variable) GetName() string {
|
||||
return v.Name
|
||||
}
|
||||
|
||||
// Matcher is used for matching ValidatingAdmissionPolicy and ValidatingAdmissionPolicyBinding to attributes
|
||||
type Matcher interface {
|
||||
admission.InitializationValidator
|
||||
|
||||
// DefinitionMatches says whether this policy definition matches the provided admission
|
||||
// resource request
|
||||
DefinitionMatches(a admission.Attributes, o admission.ObjectInterfaces, definition *v1beta1.ValidatingAdmissionPolicy) (bool, schema.GroupVersionResource, schema.GroupVersionKind, error)
|
||||
|
||||
// BindingMatches says whether this policy definition matches the provided admission
|
||||
// resource request
|
||||
BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, definition *v1beta1.ValidatingAdmissionPolicyBinding) (bool, error)
|
||||
|
||||
// GetNamespace retrieves the Namespace resource by the given name. The name may be empty, in which case
|
||||
// GetNamespace must return nil, nil
|
||||
GetNamespace(name string) (*corev1.Namespace, error)
|
||||
}
|
||||
|
||||
// ValidateResult defines the result of a Validator.Validate operation.
|
||||
type ValidateResult struct {
|
||||
// Decisions specifies the outcome of the validation as well as the details about the decision.
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
celgo "github.com/google/cel-go/cel"
|
188
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/validating/plugin.go
generated
vendored
Normal file
188
vendor/k8s.io/apiserver/pkg/admission/plugin/policy/validating/plugin.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright 2024 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 validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/matching"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/matchconditions"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/cel/environment"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// PluginName indicates the name of admission plug-in
|
||||
PluginName = "ValidatingAdmissionPolicy"
|
||||
)
|
||||
|
||||
var (
|
||||
compositionEnvTemplate *cel.CompositionEnv = func() *cel.CompositionEnv {
|
||||
compositionEnvTemplate, err := cel.NewCompositionEnv(cel.VariablesTypeName, environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return compositionEnvTemplate
|
||||
}()
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) {
|
||||
return NewPlugin(configFile), nil
|
||||
})
|
||||
}
|
||||
|
||||
// Plugin is an implementation of admission.Interface.
|
||||
type Policy = v1.ValidatingAdmissionPolicy
|
||||
type PolicyBinding = v1.ValidatingAdmissionPolicyBinding
|
||||
type PolicyEvaluator = Validator
|
||||
type PolicyHook = generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]
|
||||
|
||||
type Plugin struct {
|
||||
*generic.Plugin[PolicyHook]
|
||||
}
|
||||
|
||||
var _ admission.Interface = &Plugin{}
|
||||
var _ admission.ValidationInterface = &Plugin{}
|
||||
var _ initializer.WantsFeatures = &Plugin{}
|
||||
var _ initializer.WantsExcludedAdmissionResources = &Plugin{}
|
||||
|
||||
func NewPlugin(_ io.Reader) *Plugin {
|
||||
handler := admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update)
|
||||
|
||||
return &Plugin{
|
||||
Plugin: generic.NewPlugin(
|
||||
handler,
|
||||
func(f informers.SharedInformerFactory, client kubernetes.Interface, dynamicClient dynamic.Interface, restMapper meta.RESTMapper) generic.Source[PolicyHook] {
|
||||
return generic.NewPolicySource(
|
||||
f.Admissionregistration().V1().ValidatingAdmissionPolicies().Informer(),
|
||||
f.Admissionregistration().V1().ValidatingAdmissionPolicyBindings().Informer(),
|
||||
NewValidatingAdmissionPolicyAccessor,
|
||||
NewValidatingAdmissionPolicyBindingAccessor,
|
||||
compilePolicy,
|
||||
f,
|
||||
dynamicClient,
|
||||
restMapper,
|
||||
)
|
||||
},
|
||||
func(a authorizer.Authorizer, m *matching.Matcher) generic.Dispatcher[PolicyHook] {
|
||||
return NewDispatcher(a, generic.NewPolicyMatcher(m))
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate makes an admission decision based on the request attributes.
|
||||
func (a *Plugin) Validate(ctx context.Context, attr admission.Attributes, o admission.ObjectInterfaces) error {
|
||||
return a.Plugin.Dispatch(ctx, attr, o)
|
||||
}
|
||||
|
||||
func (a *Plugin) InspectFeatureGates(featureGates featuregate.FeatureGate) {
|
||||
a.Plugin.SetEnabled(featureGates.Enabled(features.ValidatingAdmissionPolicy))
|
||||
}
|
||||
|
||||
func compilePolicy(policy *Policy) Validator {
|
||||
hasParam := false
|
||||
if policy.Spec.ParamKind != nil {
|
||||
hasParam = true
|
||||
}
|
||||
optionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: true}
|
||||
expressionOptionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: false}
|
||||
failurePolicy := policy.Spec.FailurePolicy
|
||||
var matcher matchconditions.Matcher = nil
|
||||
matchConditions := policy.Spec.MatchConditions
|
||||
|
||||
filterCompiler := cel.NewCompositedCompilerFromTemplate(compositionEnvTemplate)
|
||||
filterCompiler.CompileAndStoreVariables(convertv1beta1Variables(policy.Spec.Variables), optionalVars, environment.StoredExpressions)
|
||||
|
||||
if len(matchConditions) > 0 {
|
||||
matchExpressionAccessors := make([]cel.ExpressionAccessor, len(matchConditions))
|
||||
for i := range matchConditions {
|
||||
matchExpressionAccessors[i] = (*matchconditions.MatchCondition)(&matchConditions[i])
|
||||
}
|
||||
matcher = matchconditions.NewMatcher(filterCompiler.Compile(matchExpressionAccessors, optionalVars, environment.StoredExpressions), failurePolicy, "policy", "validate", policy.Name)
|
||||
}
|
||||
res := NewValidator(
|
||||
filterCompiler.Compile(convertv1Validations(policy.Spec.Validations), optionalVars, environment.StoredExpressions),
|
||||
matcher,
|
||||
filterCompiler.Compile(convertv1AuditAnnotations(policy.Spec.AuditAnnotations), optionalVars, environment.StoredExpressions),
|
||||
filterCompiler.Compile(convertv1MessageExpressions(policy.Spec.Validations), expressionOptionalVars, environment.StoredExpressions),
|
||||
failurePolicy,
|
||||
)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func convertv1Validations(inputValidations []v1.Validation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
validation := ValidationCondition{
|
||||
Expression: validation.Expression,
|
||||
Message: validation.Message,
|
||||
Reason: validation.Reason,
|
||||
}
|
||||
celExpressionAccessor[i] = &validation
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1MessageExpressions(inputValidations []v1.Validation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
if validation.MessageExpression != "" {
|
||||
condition := MessageExpressionCondition{
|
||||
MessageExpression: validation.MessageExpression,
|
||||
}
|
||||
celExpressionAccessor[i] = &condition
|
||||
}
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1AuditAnnotations(inputValidations []v1.AuditAnnotation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
validation := AuditAnnotationCondition{
|
||||
Key: validation.Key,
|
||||
ValueExpression: validation.ValueExpression,
|
||||
}
|
||||
celExpressionAccessor[i] = &validation
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1beta1Variables(variables []v1.Variable) []cel.NamedExpressionAccessor {
|
||||
namedExpressions := make([]cel.NamedExpressionAccessor, len(variables))
|
||||
for i, variable := range variables {
|
||||
namedExpressions[i] = &Variable{Name: variable.Name, Expression: variable.Expression}
|
||||
}
|
||||
return namedExpressions
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"net/http"
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -25,9 +25,10 @@ import (
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
"k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
@ -55,6 +56,8 @@ type TypeCheckingContext struct {
|
||||
declTypes []*apiservercel.DeclType
|
||||
paramGVK schema.GroupVersionKind
|
||||
paramDeclType *apiservercel.DeclType
|
||||
|
||||
variables []v1.Variable
|
||||
}
|
||||
|
||||
type typeOverwrite struct {
|
||||
@ -68,7 +71,7 @@ type TypeCheckingResult struct {
|
||||
// GVK is the associated GVK
|
||||
GVK schema.GroupVersionKind
|
||||
// Issues contain machine-readable information about the typechecking result.
|
||||
Issues *cel.Issues
|
||||
Issues error
|
||||
// Err is the possible error that was encounter during type checking.
|
||||
Err error
|
||||
}
|
||||
@ -102,18 +105,18 @@ func (r *TypeCheckingResult) String() string {
|
||||
// as []ExpressionWarning that is ready to be set in policy.Status
|
||||
// The result is nil if type checking returns no warning.
|
||||
// The policy object is NOT mutated. The caller should update Status accordingly
|
||||
func (c *TypeChecker) Check(policy *v1beta1.ValidatingAdmissionPolicy) []v1beta1.ExpressionWarning {
|
||||
func (c *TypeChecker) Check(policy *v1.ValidatingAdmissionPolicy) []v1.ExpressionWarning {
|
||||
ctx := c.CreateContext(policy)
|
||||
|
||||
// warnings to return, note that the capacity is optimistically set to zero
|
||||
var warnings []v1beta1.ExpressionWarning // intentionally not setting capacity
|
||||
var warnings []v1.ExpressionWarning // intentionally not setting capacity
|
||||
|
||||
// check main validation expressions and their message expressions, located in spec.validations[*]
|
||||
fieldRef := field.NewPath("spec", "validations")
|
||||
for i, v := range policy.Spec.Validations {
|
||||
results := c.CheckExpression(ctx, v.Expression)
|
||||
if len(results) != 0 {
|
||||
warnings = append(warnings, v1beta1.ExpressionWarning{
|
||||
warnings = append(warnings, v1.ExpressionWarning{
|
||||
FieldRef: fieldRef.Index(i).Child("expression").String(),
|
||||
Warning: results.String(),
|
||||
})
|
||||
@ -124,7 +127,7 @@ func (c *TypeChecker) Check(policy *v1beta1.ValidatingAdmissionPolicy) []v1beta1
|
||||
}
|
||||
results = c.CheckExpression(ctx, v.MessageExpression)
|
||||
if len(results) != 0 {
|
||||
warnings = append(warnings, v1beta1.ExpressionWarning{
|
||||
warnings = append(warnings, v1.ExpressionWarning{
|
||||
FieldRef: fieldRef.Index(i).Child("messageExpression").String(),
|
||||
Warning: results.String(),
|
||||
})
|
||||
@ -135,7 +138,7 @@ func (c *TypeChecker) Check(policy *v1beta1.ValidatingAdmissionPolicy) []v1beta1
|
||||
}
|
||||
|
||||
// CreateContext resolves all types and their schemas from a policy definition and creates the context.
|
||||
func (c *TypeChecker) CreateContext(policy *v1beta1.ValidatingAdmissionPolicy) *TypeCheckingContext {
|
||||
func (c *TypeChecker) CreateContext(policy *v1.ValidatingAdmissionPolicy) *TypeCheckingContext {
|
||||
ctx := new(TypeCheckingContext)
|
||||
allGvks := c.typesToCheck(policy)
|
||||
gvks := make([]schema.GroupVersionKind, 0, len(allGvks))
|
||||
@ -168,26 +171,70 @@ func (c *TypeChecker) CreateContext(policy *v1beta1.ValidatingAdmissionPolicy) *
|
||||
}
|
||||
ctx.paramGVK = paramsGVK
|
||||
ctx.paramDeclType = paramsDeclType
|
||||
ctx.variables = policy.Spec.Variables
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (c *TypeChecker) compiler(ctx *TypeCheckingContext, typeOverwrite typeOverwrite) (*plugincel.CompositedCompiler, error) {
|
||||
envSet, err := buildEnvSet(
|
||||
/* hasParams */ ctx.paramDeclType != nil,
|
||||
/* hasAuthorizer */ true,
|
||||
typeOverwrite)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
env, err := plugincel.NewCompositionEnv(plugincel.VariablesTypeName, envSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compiler := &plugincel.CompositedCompiler{
|
||||
Compiler: &typeCheckingCompiler{typeOverwrite: typeOverwrite, compositionEnv: env},
|
||||
CompositionEnv: env,
|
||||
}
|
||||
return compiler, nil
|
||||
}
|
||||
|
||||
// CheckExpression type checks a single expression, given the context
|
||||
func (c *TypeChecker) CheckExpression(ctx *TypeCheckingContext, expression string) TypeCheckingResults {
|
||||
var results TypeCheckingResults
|
||||
for i, gvk := range ctx.gvks {
|
||||
declType := ctx.declTypes[i]
|
||||
// TODO(jiahuif) hasAuthorizer always true for now, will change after expending type checking to all fields.
|
||||
issues, err := c.checkExpression(expression, ctx.paramDeclType != nil, true, typeOverwrite{
|
||||
compiler, err := c.compiler(ctx, typeOverwrite{
|
||||
object: declType,
|
||||
params: ctx.paramDeclType,
|
||||
})
|
||||
if issues != nil || err != nil {
|
||||
results = append(results, &TypeCheckingResult{Issues: issues, Err: err, GVK: gvk})
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
continue
|
||||
}
|
||||
options := plugincel.OptionalVariableDeclarations{
|
||||
HasParams: ctx.paramDeclType != nil,
|
||||
HasAuthorizer: true,
|
||||
}
|
||||
compiler.CompileAndStoreVariables(convertv1beta1Variables(ctx.variables), options, environment.StoredExpressions)
|
||||
result := compiler.CompileCELExpression(celExpression(expression), options, environment.StoredExpressions)
|
||||
if err := result.Error; err != nil {
|
||||
typeCheckingResult := &TypeCheckingResult{GVK: gvk}
|
||||
if err.Type == apiservercel.ErrorTypeInvalid {
|
||||
typeCheckingResult.Issues = err
|
||||
} else {
|
||||
typeCheckingResult.Err = err
|
||||
}
|
||||
results = append(results, typeCheckingResult)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
type celExpression string
|
||||
|
||||
func (c celExpression) GetExpression() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func (c celExpression) ReturnTypes() []*cel.Type {
|
||||
return []*cel.Type{cel.AnyType}
|
||||
}
|
||||
func generateUniqueTypeName(kind string) string {
|
||||
return fmt.Sprintf("%s%d", kind, time.Now().Nanosecond())
|
||||
}
|
||||
@ -203,7 +250,7 @@ func (c *TypeChecker) declType(gvk schema.GroupVersionKind) (*apiservercel.DeclT
|
||||
return common.SchemaDeclType(&openapi.Schema{Schema: s}, true).MaybeAssignTypeName(generateUniqueTypeName(gvk.Kind)), nil
|
||||
}
|
||||
|
||||
func (c *TypeChecker) paramsGVK(policy *v1beta1.ValidatingAdmissionPolicy) schema.GroupVersionKind {
|
||||
func (c *TypeChecker) paramsGVK(policy *v1.ValidatingAdmissionPolicy) schema.GroupVersionKind {
|
||||
if policy.Spec.ParamKind == nil {
|
||||
return schema.GroupVersionKind{}
|
||||
}
|
||||
@ -214,26 +261,9 @@ func (c *TypeChecker) paramsGVK(policy *v1beta1.ValidatingAdmissionPolicy) schem
|
||||
return gv.WithKind(policy.Spec.ParamKind.Kind)
|
||||
}
|
||||
|
||||
func (c *TypeChecker) checkExpression(expression string, hasParams, hasAuthorizer bool, types typeOverwrite) (*cel.Issues, error) {
|
||||
env, err := buildEnv(hasParams, hasAuthorizer, types)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We cannot reuse an AST that is parsed by another env, so reparse it here.
|
||||
// Compile = Parse + Check, we especially want the results of Check.
|
||||
//
|
||||
// Paradoxically, we discard the type-checked result and let the admission
|
||||
// controller use the dynamic typed program.
|
||||
// This is a compromise that is defined in the KEP. We can revisit this
|
||||
// decision and expect a change with limited size.
|
||||
_, issues := env.Compile(expression)
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
// typesToCheck extracts a list of GVKs that needs type checking from the policy
|
||||
// the result is sorted in the order of Group, Version, and Kind
|
||||
func (c *TypeChecker) typesToCheck(p *v1beta1.ValidatingAdmissionPolicy) []schema.GroupVersionKind {
|
||||
func (c *TypeChecker) typesToCheck(p *v1.ValidatingAdmissionPolicy) []schema.GroupVersionKind {
|
||||
gvks := sets.New[schema.GroupVersionKind]()
|
||||
if p.Spec.MatchConstraints == nil || len(p.Spec.MatchConstraints.ResourceRules) == 0 {
|
||||
return nil
|
||||
@ -303,7 +333,7 @@ func (c *TypeChecker) typesToCheck(p *v1beta1.ValidatingAdmissionPolicy) []schem
|
||||
return sortGVKList(gvks.UnsortedList())
|
||||
}
|
||||
|
||||
func extractGroups(rule *v1beta1.Rule) []string {
|
||||
func extractGroups(rule *v1.Rule) []string {
|
||||
groups := make([]string, 0, len(rule.APIGroups))
|
||||
for _, group := range rule.APIGroups {
|
||||
// give up if wildcard
|
||||
@ -315,7 +345,7 @@ func extractGroups(rule *v1beta1.Rule) []string {
|
||||
return groups
|
||||
}
|
||||
|
||||
func extractVersions(rule *v1beta1.Rule) []string {
|
||||
func extractVersions(rule *v1.Rule) []string {
|
||||
versions := make([]string, 0, len(rule.APIVersions))
|
||||
for _, version := range rule.APIVersions {
|
||||
if strings.ContainsAny(version, "*") {
|
||||
@ -326,7 +356,7 @@ func extractVersions(rule *v1beta1.Rule) []string {
|
||||
return versions
|
||||
}
|
||||
|
||||
func extractResources(rule *v1beta1.Rule) []string {
|
||||
func extractResources(rule *v1.Rule) []string {
|
||||
resources := make([]string, 0, len(rule.Resources))
|
||||
for _, resource := range rule.Resources {
|
||||
// skip wildcard and subresources
|
||||
@ -360,7 +390,7 @@ func (c *TypeChecker) tryRefreshRESTMapper() {
|
||||
}
|
||||
}
|
||||
|
||||
func buildEnv(hasParams bool, hasAuthorizer bool, types typeOverwrite) (*cel.Env, error) {
|
||||
func buildEnvSet(hasParams bool, hasAuthorizer bool, types typeOverwrite) (*environment.EnvSet, error) {
|
||||
baseEnv := environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion())
|
||||
requestType := plugincel.BuildRequestType()
|
||||
namespaceType := plugincel.BuildNamespaceType()
|
||||
@ -392,7 +422,7 @@ func buildEnv(hasParams bool, hasAuthorizer bool, types typeOverwrite) (*cel.Env
|
||||
varOpts = append(varOpts, cel.Variable("authorizer", library.AuthorizerType))
|
||||
}
|
||||
|
||||
env, err := baseEnv.Extend(
|
||||
return baseEnv.Extend(
|
||||
environment.VersionedOptions{
|
||||
// Feature epoch was actually 1.26, but we artificially set it to 1.0 because these
|
||||
// options should always be present.
|
||||
@ -401,10 +431,6 @@ func buildEnv(hasParams bool, hasAuthorizer bool, types typeOverwrite) (*cel.Env
|
||||
DeclTypes: declTypes,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return env.Env(environment.StoredExpressions)
|
||||
}
|
||||
|
||||
// createVariableOpts creates a slice of EnvOption
|
||||
@ -421,3 +447,40 @@ func createVariableOpts(declType *apiservercel.DeclType, variables ...string) []
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
type typeCheckingCompiler struct {
|
||||
compositionEnv *plugincel.CompositionEnv
|
||||
typeOverwrite typeOverwrite
|
||||
}
|
||||
|
||||
// CompileCELExpression compiles the given expression.
|
||||
// The implementation is the same as that of staging/src/k8s.io/apiserver/pkg/admission/plugin/cel/compile.go
|
||||
// except that:
|
||||
// - object, oldObject, and params are typed instead of Dyn
|
||||
// - compiler does not enforce the output type
|
||||
// - the compiler does not initialize the program
|
||||
func (c *typeCheckingCompiler) CompileCELExpression(expressionAccessor plugincel.ExpressionAccessor, options plugincel.OptionalVariableDeclarations, mode environment.Type) plugincel.CompilationResult {
|
||||
resultError := func(errorString string, errType apiservercel.ErrorType) plugincel.CompilationResult {
|
||||
return plugincel.CompilationResult{
|
||||
Error: &apiservercel.Error{
|
||||
Type: errType,
|
||||
Detail: errorString,
|
||||
},
|
||||
ExpressionAccessor: expressionAccessor,
|
||||
}
|
||||
}
|
||||
env, err := c.compositionEnv.Env(mode)
|
||||
if err != nil {
|
||||
return resultError(fmt.Sprintf("fail to build env: %v", err), apiservercel.ErrorTypeInternal)
|
||||
}
|
||||
ast, issues := env.Compile(expressionAccessor.GetExpression())
|
||||
if issues != nil {
|
||||
return resultError(issues.String(), apiservercel.ErrorTypeInvalid)
|
||||
}
|
||||
// type checker does not require the program, however the type must still be set.
|
||||
return plugincel.CompilationResult{
|
||||
OutputType: ast.OutputType(),
|
||||
}
|
||||
}
|
||||
|
||||
var _ plugincel.Compiler = (*typeCheckingCompiler)(nil)
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validatingadmissionpolicy
|
||||
package validating
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -80,7 +80,6 @@ func (v *validator) Validate(ctx context.Context, matchedResource schema.GroupVe
|
||||
} else {
|
||||
f = *v.failPolicy
|
||||
}
|
||||
|
||||
if v.celMatcher != nil {
|
||||
matchResults := v.celMatcher.Match(ctx, versionedAttr, versionedParams, authz)
|
||||
if matchResults.Error != nil {
|
10
vendor/k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/OWNERS
generated
vendored
10
vendor/k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/OWNERS
generated
vendored
@ -1,10 +0,0 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- jpbetz
|
||||
- cici37
|
||||
- alexzielenski
|
||||
reviewers:
|
||||
- jpbetz
|
||||
- cici37
|
||||
- alexzielenski
|
197
vendor/k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/admission.go
generated
vendored
197
vendor/k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/admission.go
generated
vendored
@ -1,197 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 validatingadmissionpolicy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/component-base/featuregate"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Plugin Definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Definition for CEL admission plugin. This is the entry point into the
|
||||
// CEL admission control system.
|
||||
//
|
||||
// Each plugin is asked to validate every object update.
|
||||
|
||||
const (
|
||||
// PluginName indicates the name of admission plug-in
|
||||
PluginName = "ValidatingAdmissionPolicy"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewPlugin()
|
||||
})
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Plugin Initialization & Dependency Injection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type celAdmissionPlugin struct {
|
||||
*admission.Handler
|
||||
evaluator CELPolicyEvaluator
|
||||
|
||||
inspectedFeatureGates bool
|
||||
enabled bool
|
||||
|
||||
// Injected Dependencies
|
||||
informerFactory informers.SharedInformerFactory
|
||||
client kubernetes.Interface
|
||||
restMapper meta.RESTMapper
|
||||
dynamicClient dynamic.Interface
|
||||
stopCh <-chan struct{}
|
||||
authorizer authorizer.Authorizer
|
||||
}
|
||||
|
||||
var _ initializer.WantsExternalKubeInformerFactory = &celAdmissionPlugin{}
|
||||
var _ initializer.WantsExternalKubeClientSet = &celAdmissionPlugin{}
|
||||
var _ initializer.WantsRESTMapper = &celAdmissionPlugin{}
|
||||
var _ initializer.WantsDynamicClient = &celAdmissionPlugin{}
|
||||
var _ initializer.WantsDrainedNotification = &celAdmissionPlugin{}
|
||||
var _ initializer.WantsAuthorizer = &celAdmissionPlugin{}
|
||||
var _ admission.InitializationValidator = &celAdmissionPlugin{}
|
||||
var _ admission.ValidationInterface = &celAdmissionPlugin{}
|
||||
|
||||
func NewPlugin() (admission.Interface, error) {
|
||||
return &celAdmissionPlugin{
|
||||
Handler: admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
c.informerFactory = f
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
c.client = client
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetRESTMapper(mapper meta.RESTMapper) {
|
||||
c.restMapper = mapper
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetDynamicClient(client dynamic.Interface) {
|
||||
c.dynamicClient = client
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetDrainedNotification(stopCh <-chan struct{}) {
|
||||
c.stopCh = stopCh
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) SetAuthorizer(authorizer authorizer.Authorizer) {
|
||||
c.authorizer = authorizer
|
||||
}
|
||||
func (c *celAdmissionPlugin) InspectFeatureGates(featureGates featuregate.FeatureGate) {
|
||||
if featureGates.Enabled(features.ValidatingAdmissionPolicy) {
|
||||
c.enabled = true
|
||||
}
|
||||
c.inspectedFeatureGates = true
|
||||
}
|
||||
|
||||
// ValidateInitialization - once clientset and informer factory are provided, creates and starts the admission controller
|
||||
func (c *celAdmissionPlugin) ValidateInitialization() error {
|
||||
if !c.inspectedFeatureGates {
|
||||
return fmt.Errorf("%s did not see feature gates", PluginName)
|
||||
}
|
||||
if !c.enabled {
|
||||
return nil
|
||||
}
|
||||
if c.informerFactory == nil {
|
||||
return errors.New("missing informer factory")
|
||||
}
|
||||
if c.client == nil {
|
||||
return errors.New("missing kubernetes client")
|
||||
}
|
||||
if c.restMapper == nil {
|
||||
return errors.New("missing rest mapper")
|
||||
}
|
||||
if c.dynamicClient == nil {
|
||||
return errors.New("missing dynamic client")
|
||||
}
|
||||
if c.stopCh == nil {
|
||||
return errors.New("missing stop channel")
|
||||
}
|
||||
if c.authorizer == nil {
|
||||
return errors.New("missing authorizer")
|
||||
}
|
||||
c.evaluator = NewAdmissionController(c.informerFactory, c.client, c.restMapper, c.dynamicClient, c.authorizer)
|
||||
if err := c.evaluator.ValidateInitialization(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.SetReadyFunc(c.evaluator.HasSynced)
|
||||
go c.evaluator.Run(c.stopCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// admission.ValidationInterface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (c *celAdmissionPlugin) Handles(operation admission.Operation) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *celAdmissionPlugin) Validate(
|
||||
ctx context.Context,
|
||||
a admission.Attributes,
|
||||
o admission.ObjectInterfaces,
|
||||
) (err error) {
|
||||
if !c.enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isPolicyResource determines if an admission.Attributes object is describing
|
||||
// the admission of a ValidatingAdmissionPolicy or a ValidatingAdmissionPolicyBinding
|
||||
if isPolicyResource(a) {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.WaitForReady() {
|
||||
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
|
||||
}
|
||||
|
||||
return c.evaluator.Validate(ctx, a, o)
|
||||
}
|
||||
|
||||
func isPolicyResource(attr admission.Attributes) bool {
|
||||
gvk := attr.GetResource()
|
||||
if gvk.Group == "admissionregistration.k8s.io" {
|
||||
if gvk.Resource == "validatingadmissionpolicies" || gvk.Resource == "validatingadmissionpolicybindings" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@ -1,551 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 validatingadmissionpolicy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
celmetrics "k8s.io/apiserver/pkg/admission/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/internal/generic"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/matchconditions"
|
||||
"k8s.io/apiserver/pkg/cel/environment"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/dynamic/dynamicinformer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type policyController struct {
|
||||
once sync.Once
|
||||
context context.Context
|
||||
dynamicClient dynamic.Interface
|
||||
informerFactory informers.SharedInformerFactory
|
||||
restMapper meta.RESTMapper
|
||||
policyDefinitionsController generic.Controller[*v1beta1.ValidatingAdmissionPolicy]
|
||||
policyBindingController generic.Controller[*v1beta1.ValidatingAdmissionPolicyBinding]
|
||||
|
||||
// Provided to the policy's Compile function as an injected dependency to
|
||||
// assist with compiling its expressions to CEL
|
||||
// pass nil to create filter compiler in demand
|
||||
filterCompiler cel.FilterCompiler
|
||||
|
||||
matcher Matcher
|
||||
|
||||
newValidator
|
||||
|
||||
client kubernetes.Interface
|
||||
// Lock which protects
|
||||
// All Below fields
|
||||
// All above fields should be assumed constant
|
||||
mutex sync.RWMutex
|
||||
|
||||
cachedPolicies []policyData
|
||||
|
||||
// controller and metadata
|
||||
paramsCRDControllers map[v1beta1.ParamKind]*paramInfo
|
||||
|
||||
// Index for each definition namespace/name, contains all binding
|
||||
// namespace/names known to exist for that definition
|
||||
definitionInfo map[namespacedName]*definitionInfo
|
||||
|
||||
// Index for each bindings namespace/name. Contains compiled templates
|
||||
// for the binding depending on the policy/param combination.
|
||||
bindingInfos map[namespacedName]*bindingInfo
|
||||
|
||||
// Map from namespace/name of a definition to a set of namespace/name
|
||||
// of bindings which depend on it.
|
||||
// All keys must have at least one dependent binding
|
||||
// All binding names MUST exist as a key bindingInfos
|
||||
definitionsToBindings map[namespacedName]sets.Set[namespacedName]
|
||||
}
|
||||
|
||||
type newValidator func(validationFilter cel.Filter, celMatcher matchconditions.Matcher, auditAnnotationFilter, messageFilter cel.Filter, failurePolicy *v1.FailurePolicyType) Validator
|
||||
|
||||
func newPolicyController(
|
||||
restMapper meta.RESTMapper,
|
||||
client kubernetes.Interface,
|
||||
dynamicClient dynamic.Interface,
|
||||
informerFactory informers.SharedInformerFactory,
|
||||
filterCompiler cel.FilterCompiler,
|
||||
matcher Matcher,
|
||||
policiesInformer generic.Informer[*v1beta1.ValidatingAdmissionPolicy],
|
||||
bindingsInformer generic.Informer[*v1beta1.ValidatingAdmissionPolicyBinding],
|
||||
) *policyController {
|
||||
res := &policyController{}
|
||||
*res = policyController{
|
||||
filterCompiler: filterCompiler,
|
||||
definitionInfo: make(map[namespacedName]*definitionInfo),
|
||||
bindingInfos: make(map[namespacedName]*bindingInfo),
|
||||
paramsCRDControllers: make(map[v1beta1.ParamKind]*paramInfo),
|
||||
definitionsToBindings: make(map[namespacedName]sets.Set[namespacedName]),
|
||||
matcher: matcher,
|
||||
newValidator: NewValidator,
|
||||
policyDefinitionsController: generic.NewController(
|
||||
policiesInformer,
|
||||
res.reconcilePolicyDefinition,
|
||||
generic.ControllerOptions{
|
||||
Workers: 1,
|
||||
Name: "cel-policy-definitions",
|
||||
},
|
||||
),
|
||||
policyBindingController: generic.NewController(
|
||||
bindingsInformer,
|
||||
res.reconcilePolicyBinding,
|
||||
generic.ControllerOptions{
|
||||
Workers: 1,
|
||||
Name: "cel-policy-bindings",
|
||||
},
|
||||
),
|
||||
restMapper: restMapper,
|
||||
dynamicClient: dynamicClient,
|
||||
informerFactory: informerFactory,
|
||||
client: client,
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *policyController) Run(ctx context.Context) {
|
||||
// Only support being run once
|
||||
c.once.Do(func() {
|
||||
c.context = ctx
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c.policyDefinitionsController.Run(ctx)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c.policyBindingController.Run(ctx)
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
wg.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
func (c *policyController) HasSynced() bool {
|
||||
return c.policyDefinitionsController.HasSynced() && c.policyBindingController.HasSynced()
|
||||
}
|
||||
|
||||
func (c *policyController) reconcilePolicyDefinition(namespace, name string, definition *v1beta1.ValidatingAdmissionPolicy) error {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
err := c.reconcilePolicyDefinitionSpec(namespace, name, definition)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *policyController) reconcilePolicyDefinitionSpec(namespace, name string, definition *v1beta1.ValidatingAdmissionPolicy) error {
|
||||
c.cachedPolicies = nil // invalidate cachedPolicies
|
||||
|
||||
// Namespace for policydefinition is empty.
|
||||
nn := getNamespaceName(namespace, name)
|
||||
info, ok := c.definitionInfo[nn]
|
||||
if !ok {
|
||||
info = &definitionInfo{}
|
||||
c.definitionInfo[nn] = info
|
||||
// TODO(DangerOnTheRanger): add support for "warn" being a valid enforcementAction
|
||||
celmetrics.Metrics.ObserveDefinition(context.TODO(), "active", "deny")
|
||||
}
|
||||
|
||||
// Skip reconcile if the spec of the definition is unchanged and had a
|
||||
// successful previous sync
|
||||
if info.configurationError == nil && info.lastReconciledValue != nil && definition != nil &&
|
||||
apiequality.Semantic.DeepEqual(info.lastReconciledValue.Spec, definition.Spec) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var paramSource *v1beta1.ParamKind
|
||||
if definition != nil {
|
||||
paramSource = definition.Spec.ParamKind
|
||||
}
|
||||
|
||||
// If param source has changed, remove definition as dependent of old params
|
||||
// If there are no more dependents of old param, stop and clean up controller
|
||||
if info.lastReconciledValue != nil && info.lastReconciledValue.Spec.ParamKind != nil {
|
||||
oldParamSource := *info.lastReconciledValue.Spec.ParamKind
|
||||
|
||||
// If we are:
|
||||
// - switching from having a param to not having a param (includes deletion)
|
||||
// - or from having a param to a different one
|
||||
// we remove dependency on the controller.
|
||||
if paramSource == nil || *paramSource != oldParamSource {
|
||||
if oldParamInfo, ok := c.paramsCRDControllers[oldParamSource]; ok {
|
||||
oldParamInfo.dependentDefinitions.Delete(nn)
|
||||
if len(oldParamInfo.dependentDefinitions) == 0 {
|
||||
oldParamInfo.stop()
|
||||
delete(c.paramsCRDControllers, oldParamSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all previously compiled evaluators in case something relevant in
|
||||
// definition has changed.
|
||||
for key := range c.definitionsToBindings[nn] {
|
||||
bindingInfo := c.bindingInfos[key]
|
||||
bindingInfo.validator = nil
|
||||
c.bindingInfos[key] = bindingInfo
|
||||
}
|
||||
|
||||
if definition == nil {
|
||||
delete(c.definitionInfo, nn)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update definition info
|
||||
info.lastReconciledValue = definition
|
||||
info.configurationError = nil
|
||||
|
||||
if paramSource == nil {
|
||||
// Skip setting up controller for empty param type
|
||||
return nil
|
||||
}
|
||||
// find GVR for params
|
||||
// Parse param source into a GVK
|
||||
|
||||
paramSourceGV, err := schema.ParseGroupVersion(paramSource.APIVersion)
|
||||
if err != nil {
|
||||
// Failed to resolve. Return error so we retry again (rate limited)
|
||||
// Save a record of this definition with an evaluator that unconditionally
|
||||
info.configurationError = fmt.Errorf("failed to parse apiVersion of paramKind '%v' with error: %w", paramSource.String(), err)
|
||||
|
||||
// Return nil, since this error cannot be resolved by waiting more time
|
||||
return nil
|
||||
}
|
||||
|
||||
paramsGVR, err := c.restMapper.RESTMapping(schema.GroupKind{
|
||||
Group: paramSourceGV.Group,
|
||||
Kind: paramSource.Kind,
|
||||
}, paramSourceGV.Version)
|
||||
|
||||
if err != nil {
|
||||
// Failed to resolve. Return error so we retry again (rate limited)
|
||||
// Save a record of this definition with an evaluator that unconditionally
|
||||
//
|
||||
info.configurationError = fmt.Errorf("failed to find resource referenced by paramKind: '%v'", paramSourceGV.WithKind(paramSource.Kind))
|
||||
return info.configurationError
|
||||
}
|
||||
|
||||
paramInfo := c.ensureParamInfo(paramSource, paramsGVR)
|
||||
paramInfo.dependentDefinitions.Insert(nn)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensures that there is an informer started for the given GVK to be used as a
|
||||
// param
|
||||
func (c *policyController) ensureParamInfo(paramSource *v1beta1.ParamKind, mapping *meta.RESTMapping) *paramInfo {
|
||||
if info, ok := c.paramsCRDControllers[*paramSource]; ok {
|
||||
return info
|
||||
}
|
||||
|
||||
// We are not watching this param. Start an informer for it.
|
||||
instanceContext, instanceCancel := context.WithCancel(c.context)
|
||||
|
||||
var informer cache.SharedIndexInformer
|
||||
|
||||
// Try to see if our provided informer factory has an informer for this type.
|
||||
// We assume the informer is already started, and starts all types associated
|
||||
// with it.
|
||||
if genericInformer, err := c.informerFactory.ForResource(mapping.Resource); err == nil {
|
||||
informer = genericInformer.Informer()
|
||||
|
||||
// Ensure the informer is started
|
||||
// Use policyController's context rather than the instance context.
|
||||
// PolicyController context is expected to last until app shutdown
|
||||
// This is due to behavior of informerFactory which would cause the
|
||||
// informer to stop running once the context is cancelled, and
|
||||
// never started again.
|
||||
c.informerFactory.Start(c.context.Done())
|
||||
} else {
|
||||
// Dynamic JSON informer fallback.
|
||||
// Cannot use shared dynamic informer since it would be impossible
|
||||
// to clean CRD informers properly with multiple dependents
|
||||
// (cannot start ahead of time, and cannot track dependencies via stopCh)
|
||||
informer = dynamicinformer.NewFilteredDynamicInformer(
|
||||
c.dynamicClient,
|
||||
mapping.Resource,
|
||||
corev1.NamespaceAll,
|
||||
// Use same interval as is used for k8s typed sharedInformerFactory
|
||||
// https://github.com/kubernetes/kubernetes/blob/7e0923899fed622efbc8679cca6b000d43633e38/cmd/kube-apiserver/app/server.go#L430
|
||||
10*time.Minute,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
nil,
|
||||
).Informer()
|
||||
go informer.Run(instanceContext.Done())
|
||||
}
|
||||
|
||||
controller := generic.NewController(
|
||||
generic.NewInformer[runtime.Object](informer),
|
||||
c.reconcileParams,
|
||||
generic.ControllerOptions{
|
||||
Workers: 1,
|
||||
Name: paramSource.String() + "-controller",
|
||||
},
|
||||
)
|
||||
|
||||
ret := ¶mInfo{
|
||||
controller: controller,
|
||||
stop: instanceCancel,
|
||||
scope: mapping.Scope,
|
||||
dependentDefinitions: sets.New[namespacedName](),
|
||||
}
|
||||
c.paramsCRDControllers[*paramSource] = ret
|
||||
|
||||
go controller.Run(instanceContext)
|
||||
return ret
|
||||
|
||||
}
|
||||
|
||||
func (c *policyController) reconcilePolicyBinding(namespace, name string, binding *v1beta1.ValidatingAdmissionPolicyBinding) error {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.cachedPolicies = nil // invalidate cachedPolicies
|
||||
|
||||
// Namespace for PolicyBinding is empty. In the future a namespaced binding
|
||||
// may be added
|
||||
// https://github.com/kubernetes/enhancements/blob/bf5c3c81ea2081d60c1dc7c832faa98479e06209/keps/sig-api-machinery/3488-cel-admission-control/README.md?plain=1#L1042
|
||||
nn := getNamespaceName(namespace, name)
|
||||
info, ok := c.bindingInfos[nn]
|
||||
if !ok {
|
||||
info = &bindingInfo{}
|
||||
c.bindingInfos[nn] = info
|
||||
}
|
||||
|
||||
// Skip if the spec of the binding is unchanged.
|
||||
if info.lastReconciledValue != nil && binding != nil &&
|
||||
apiequality.Semantic.DeepEqual(info.lastReconciledValue.Spec, binding.Spec) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldNamespacedDefinitionName namespacedName
|
||||
if info.lastReconciledValue != nil {
|
||||
// All validating policies are cluster-scoped so have empty namespace
|
||||
oldNamespacedDefinitionName = getNamespaceName("", info.lastReconciledValue.Spec.PolicyName)
|
||||
}
|
||||
|
||||
var namespacedDefinitionName namespacedName
|
||||
if binding != nil {
|
||||
// All validating policies are cluster-scoped so have empty namespace
|
||||
namespacedDefinitionName = getNamespaceName("", binding.Spec.PolicyName)
|
||||
}
|
||||
|
||||
// Remove record of binding from old definition if the referred policy
|
||||
// has changed
|
||||
if oldNamespacedDefinitionName != namespacedDefinitionName {
|
||||
if dependentBindings, ok := c.definitionsToBindings[oldNamespacedDefinitionName]; ok {
|
||||
dependentBindings.Delete(nn)
|
||||
|
||||
// if there are no more dependent bindings, remove knowledge of the
|
||||
// definition altogether
|
||||
if len(dependentBindings) == 0 {
|
||||
delete(c.definitionsToBindings, oldNamespacedDefinitionName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if binding == nil {
|
||||
delete(c.bindingInfos, nn)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add record of binding to new definition
|
||||
if dependentBindings, ok := c.definitionsToBindings[namespacedDefinitionName]; ok {
|
||||
dependentBindings.Insert(nn)
|
||||
} else {
|
||||
c.definitionsToBindings[namespacedDefinitionName] = sets.New(nn)
|
||||
}
|
||||
|
||||
// Remove compiled template for old binding
|
||||
info.validator = nil
|
||||
info.lastReconciledValue = binding
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *policyController) reconcileParams(namespace, name string, params runtime.Object) error {
|
||||
// Do nothing.
|
||||
// When we add informational type checking we will need to compile in the
|
||||
// reconcile loops instead of lazily so we can add compiler errors / type
|
||||
// checker errors to the status of the resources.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fetches the latest set of policy data or recalculates it if it has changed
|
||||
// since it was last fetched
|
||||
func (c *policyController) latestPolicyData() []policyData {
|
||||
existing := func() []policyData {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
return c.cachedPolicies
|
||||
}()
|
||||
|
||||
if existing != nil {
|
||||
return existing
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
var res []policyData
|
||||
for definitionNN, definitionInfo := range c.definitionInfo {
|
||||
var bindingInfos []bindingInfo
|
||||
for bindingNN := range c.definitionsToBindings[definitionNN] {
|
||||
bindingInfo := c.bindingInfos[bindingNN]
|
||||
if bindingInfo.validator == nil && definitionInfo.configurationError == nil {
|
||||
hasParam := false
|
||||
if definitionInfo.lastReconciledValue.Spec.ParamKind != nil {
|
||||
hasParam = true
|
||||
}
|
||||
optionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: true}
|
||||
expressionOptionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: false}
|
||||
failurePolicy := convertv1beta1FailurePolicyTypeTov1FailurePolicyType(definitionInfo.lastReconciledValue.Spec.FailurePolicy)
|
||||
var matcher matchconditions.Matcher = nil
|
||||
matchConditions := definitionInfo.lastReconciledValue.Spec.MatchConditions
|
||||
|
||||
filterCompiler := c.filterCompiler
|
||||
if filterCompiler == nil {
|
||||
compositedCompiler, err := cel.NewCompositedCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
|
||||
if err == nil {
|
||||
filterCompiler = compositedCompiler
|
||||
compositedCompiler.CompileAndStoreVariables(convertv1beta1Variables(definitionInfo.lastReconciledValue.Spec.Variables), optionalVars, environment.StoredExpressions)
|
||||
} else {
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
}
|
||||
if len(matchConditions) > 0 {
|
||||
matchExpressionAccessors := make([]cel.ExpressionAccessor, len(matchConditions))
|
||||
for i := range matchConditions {
|
||||
matchExpressionAccessors[i] = (*matchconditions.MatchCondition)(&matchConditions[i])
|
||||
}
|
||||
matcher = matchconditions.NewMatcher(filterCompiler.Compile(matchExpressionAccessors, optionalVars, environment.StoredExpressions), failurePolicy, "policy", "validate", definitionInfo.lastReconciledValue.Name)
|
||||
}
|
||||
bindingInfo.validator = c.newValidator(
|
||||
filterCompiler.Compile(convertv1beta1Validations(definitionInfo.lastReconciledValue.Spec.Validations), optionalVars, environment.StoredExpressions),
|
||||
matcher,
|
||||
filterCompiler.Compile(convertv1beta1AuditAnnotations(definitionInfo.lastReconciledValue.Spec.AuditAnnotations), optionalVars, environment.StoredExpressions),
|
||||
filterCompiler.Compile(convertv1beta1MessageExpressions(definitionInfo.lastReconciledValue.Spec.Validations), expressionOptionalVars, environment.StoredExpressions),
|
||||
failurePolicy,
|
||||
)
|
||||
}
|
||||
bindingInfos = append(bindingInfos, *bindingInfo)
|
||||
}
|
||||
|
||||
var pInfo paramInfo
|
||||
if paramKind := definitionInfo.lastReconciledValue.Spec.ParamKind; paramKind != nil {
|
||||
if info, ok := c.paramsCRDControllers[*paramKind]; ok {
|
||||
pInfo = *info
|
||||
}
|
||||
}
|
||||
|
||||
res = append(res, policyData{
|
||||
definitionInfo: *definitionInfo,
|
||||
paramInfo: pInfo,
|
||||
bindings: bindingInfos,
|
||||
})
|
||||
}
|
||||
|
||||
c.cachedPolicies = res
|
||||
return res
|
||||
}
|
||||
|
||||
func convertv1beta1FailurePolicyTypeTov1FailurePolicyType(policyType *v1beta1.FailurePolicyType) *v1.FailurePolicyType {
|
||||
if policyType == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var v1FailPolicy v1.FailurePolicyType
|
||||
if *policyType == v1beta1.Fail {
|
||||
v1FailPolicy = v1.Fail
|
||||
} else if *policyType == v1beta1.Ignore {
|
||||
v1FailPolicy = v1.Ignore
|
||||
}
|
||||
return &v1FailPolicy
|
||||
}
|
||||
|
||||
func convertv1beta1Validations(inputValidations []v1beta1.Validation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
validation := ValidationCondition{
|
||||
Expression: validation.Expression,
|
||||
Message: validation.Message,
|
||||
Reason: validation.Reason,
|
||||
}
|
||||
celExpressionAccessor[i] = &validation
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1beta1MessageExpressions(inputValidations []v1beta1.Validation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
if validation.MessageExpression != "" {
|
||||
condition := MessageExpressionCondition{
|
||||
MessageExpression: validation.MessageExpression,
|
||||
}
|
||||
celExpressionAccessor[i] = &condition
|
||||
}
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1beta1AuditAnnotations(inputValidations []v1beta1.AuditAnnotation) []cel.ExpressionAccessor {
|
||||
celExpressionAccessor := make([]cel.ExpressionAccessor, len(inputValidations))
|
||||
for i, validation := range inputValidations {
|
||||
validation := AuditAnnotationCondition{
|
||||
Key: validation.Key,
|
||||
ValueExpression: validation.ValueExpression,
|
||||
}
|
||||
celExpressionAccessor[i] = &validation
|
||||
}
|
||||
return celExpressionAccessor
|
||||
}
|
||||
|
||||
func convertv1beta1Variables(variables []v1beta1.Variable) []cel.NamedExpressionAccessor {
|
||||
namedExpressions := make([]cel.NamedExpressionAccessor, len(variables))
|
||||
for i, variable := range variables {
|
||||
namedExpressions[i] = &Variable{Name: variable.Name, Expression: variable.Expression}
|
||||
}
|
||||
return namedExpressions
|
||||
}
|
||||
|
||||
func getNamespaceName(namespace, name string) namespacedName {
|
||||
return namespacedName{
|
||||
namespace: namespace,
|
||||
name: name,
|
||||
}
|
||||
}
|
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
package webhookadmission
|
||||
package webhookadmission // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
|
||||
|
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1 is the v1 version of the API.
|
||||
package v1
|
||||
package v1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1"
|
||||
|
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
package v1alpha1
|
||||
package v1alpha1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
|
||||
|
226
vendor/k8s.io/apiserver/pkg/apis/apidiscovery/v2/conversion.go
generated
vendored
Normal file
226
vendor/k8s.io/apiserver/pkg/apis/apidiscovery/v2/conversion.go
generated
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
Copyright 2024 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.
|
||||
*/
|
||||
|
||||
// This file was duplicated from the auto-generated file by conversion-gen in
|
||||
// k8s.io/kubernetes/pkg/apis/apidiscovery Unlike most k8s types discovery is
|
||||
// served by all apiservers and conversion is needed by all apiservers. The
|
||||
// concept of internal/hub type does not exist for discovery as we work directly
|
||||
// with the versioned types.
|
||||
|
||||
// The conversion code here facilities conversion strictly between v2beta1 and
|
||||
// v2 types. It is only necessary in k8s versions where mixed state could be
|
||||
// possible before the full removal of the v2beta1 types. It is placed in this
|
||||
// directory such that all apiservers can benefit from the conversion without
|
||||
// having to implement their own if the client/server they're communicating with
|
||||
// only supports one version.
|
||||
|
||||
// Once the v2beta1 types are removed (intended for Kubernetes v1.33), this file
|
||||
// will be removed.
|
||||
package v2
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v2 "k8s.io/api/apidiscovery/v2"
|
||||
v2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta1.APIGroupDiscovery)(nil), (*v2.APIGroupDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(a.(*v2beta1.APIGroupDiscovery), b.(*v2.APIGroupDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2.APIGroupDiscovery)(nil), (*v2beta1.APIGroupDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(a.(*v2.APIGroupDiscovery), b.(*v2beta1.APIGroupDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta1.APIGroupDiscoveryList)(nil), (*v2.APIGroupDiscoveryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(a.(*v2beta1.APIGroupDiscoveryList), b.(*v2.APIGroupDiscoveryList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2.APIGroupDiscoveryList)(nil), (*v2beta1.APIGroupDiscoveryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(a.(*v2.APIGroupDiscoveryList), b.(*v2beta1.APIGroupDiscoveryList), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta1.APIResourceDiscovery)(nil), (*v2.APIResourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(a.(*v2beta1.APIResourceDiscovery), b.(*v2.APIResourceDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2.APIResourceDiscovery)(nil), (*v2beta1.APIResourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(a.(*v2.APIResourceDiscovery), b.(*v2beta1.APIResourceDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta1.APISubresourceDiscovery)(nil), (*v2.APISubresourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(a.(*v2beta1.APISubresourceDiscovery), b.(*v2.APISubresourceDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2.APISubresourceDiscovery)(nil), (*v2beta1.APISubresourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(a.(*v2.APISubresourceDiscovery), b.(*v2beta1.APISubresourceDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2beta1.APIVersionDiscovery)(nil), (*v2.APIVersionDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(a.(*v2beta1.APIVersionDiscovery), b.(*v2.APIVersionDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v2.APIVersionDiscovery)(nil), (*v2beta1.APIVersionDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(a.(*v2.APIVersionDiscovery), b.(*v2beta1.APIVersionDiscovery), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in *v2beta1.APIGroupDiscovery, out *v2.APIGroupDiscovery, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Versions = *(*[]v2.APIVersionDiscovery)(unsafe.Pointer(&in.Versions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery is an autogenerated conversion function.
|
||||
func Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in *v2beta1.APIGroupDiscovery, out *v2.APIGroupDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in *v2.APIGroupDiscovery, out *v2beta1.APIGroupDiscovery, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Versions = *(*[]v2beta1.APIVersionDiscovery)(unsafe.Pointer(&in.Versions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery is an autogenerated conversion function.
|
||||
func Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in *v2.APIGroupDiscovery, out *v2beta1.APIGroupDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in *v2beta1.APIGroupDiscoveryList, out *v2.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]v2.APIGroupDiscovery)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList is an autogenerated conversion function.
|
||||
func Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in *v2beta1.APIGroupDiscoveryList, out *v2.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||
return autoConvertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in *v2.APIGroupDiscoveryList, out *v2beta1.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
out.Items = *(*[]v2beta1.APIGroupDiscovery)(unsafe.Pointer(&in.Items))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList is an autogenerated conversion function.
|
||||
func Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in *v2.APIGroupDiscoveryList, out *v2beta1.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||
return autoConvertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in *v2beta1.APIResourceDiscovery, out *v2.APIResourceDiscovery, s conversion.Scope) error {
|
||||
out.Resource = in.Resource
|
||||
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||
out.Scope = v2.ResourceScope(in.Scope)
|
||||
out.SingularResource = in.SingularResource
|
||||
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||
out.Subresources = *(*[]v2.APISubresourceDiscovery)(unsafe.Pointer(&in.Subresources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery is an autogenerated conversion function.
|
||||
func Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in *v2beta1.APIResourceDiscovery, out *v2.APIResourceDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in *v2.APIResourceDiscovery, out *v2beta1.APIResourceDiscovery, s conversion.Scope) error {
|
||||
out.Resource = in.Resource
|
||||
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||
out.Scope = v2beta1.ResourceScope(in.Scope)
|
||||
out.SingularResource = in.SingularResource
|
||||
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||
out.Subresources = *(*[]v2beta1.APISubresourceDiscovery)(unsafe.Pointer(&in.Subresources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery is an autogenerated conversion function.
|
||||
func Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in *v2.APIResourceDiscovery, out *v2beta1.APIResourceDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in *v2beta1.APISubresourceDiscovery, out *v2.APISubresourceDiscovery, s conversion.Scope) error {
|
||||
out.Subresource = in.Subresource
|
||||
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||
out.AcceptedTypes = *(*[]v1.GroupVersionKind)(unsafe.Pointer(&in.AcceptedTypes))
|
||||
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery is an autogenerated conversion function.
|
||||
func Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in *v2beta1.APISubresourceDiscovery, out *v2.APISubresourceDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in *v2.APISubresourceDiscovery, out *v2beta1.APISubresourceDiscovery, s conversion.Scope) error {
|
||||
out.Subresource = in.Subresource
|
||||
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||
out.AcceptedTypes = *(*[]v1.GroupVersionKind)(unsafe.Pointer(&in.AcceptedTypes))
|
||||
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery is an autogenerated conversion function.
|
||||
func Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in *v2.APISubresourceDiscovery, out *v2beta1.APISubresourceDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in *v2beta1.APIVersionDiscovery, out *v2.APIVersionDiscovery, s conversion.Scope) error {
|
||||
out.Version = in.Version
|
||||
out.Resources = *(*[]v2.APIResourceDiscovery)(unsafe.Pointer(&in.Resources))
|
||||
out.Freshness = v2.DiscoveryFreshness(in.Freshness)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery is an autogenerated conversion function.
|
||||
func Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in *v2beta1.APIVersionDiscovery, out *v2.APIVersionDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in *v2.APIVersionDiscovery, out *v2beta1.APIVersionDiscovery, s conversion.Scope) error {
|
||||
out.Version = in.Version
|
||||
out.Resources = *(*[]v2beta1.APIResourceDiscovery)(unsafe.Pointer(&in.Resources))
|
||||
out.Freshness = v2beta1.DiscoveryFreshness(in.Freshness)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery is an autogenerated conversion function.
|
||||
func Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in *v2.APIVersionDiscovery, out *v2beta1.APIVersionDiscovery, s conversion.Scope) error {
|
||||
return autoConvertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in, out, s)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
Copyright 2024 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.
|
||||
@ -14,6 +14,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +groupName=apidiscovery.k8s.io
|
||||
|
||||
package config // import "k8s.io/apiserver/pkg/apis/config"
|
||||
package v2 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
Copyright 2024 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.
|
||||
@ -14,40 +14,26 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
package v2
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
// AddToScheme adds this group to a scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "apidiscovery.k8s.io"
|
||||
|
||||
// GroupName is the group name use in this package.
|
||||
const GroupName = "apiserver.config.k8s.io"
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2"}
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects.
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind.
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource.
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
// TODO this will get cleaned up with the scheme types are fixed
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&EncryptionConfiguration{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
SchemeBuilder = &apidiscoveryv2.SchemeBuilder
|
||||
// AddToScheme adds api to a scheme
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
1
vendor/k8s.io/apiserver/pkg/apis/apiserver/register.go
generated
vendored
1
vendor/k8s.io/apiserver/pkg/apis/apiserver/register.go
generated
vendored
@ -45,6 +45,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&AdmissionConfiguration{},
|
||||
&AuthenticationConfiguration{},
|
||||
&AuthorizationConfiguration{},
|
||||
&EncryptionConfiguration{},
|
||||
&EgressSelectorConfiguration{},
|
||||
&TracingConfiguration{},
|
||||
)
|
||||
|
47
vendor/k8s.io/apiserver/pkg/apis/apiserver/types.go
generated
vendored
47
vendor/k8s.io/apiserver/pkg/apis/apiserver/types.go
generated
vendored
@ -175,13 +175,56 @@ type JWTAuthenticator struct {
|
||||
UserValidationRules []UserValidationRule
|
||||
}
|
||||
|
||||
// Issuer provides the configuration for a external provider specific settings.
|
||||
// Issuer provides the configuration for an external provider's specific settings.
|
||||
type Issuer struct {
|
||||
URL string
|
||||
// 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.
|
||||
// Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +required
|
||||
URL string
|
||||
// discoveryURL, if specified, overrides the URL used to fetch discovery
|
||||
// information instead of using "{url}/.well-known/openid-configuration".
|
||||
// The exact value specified is used, so "/.well-known/openid-configuration"
|
||||
// must be included in discoveryURL if needed.
|
||||
//
|
||||
// The "issuer" field in the fetched discovery information must match the "issuer.url" field
|
||||
// in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
|
||||
// This is for scenarios where the well-known and jwks endpoints are hosted at a different
|
||||
// location than the issuer (such as locally in the cluster).
|
||||
//
|
||||
// Example:
|
||||
// A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
|
||||
// and discovery information is available at '/.well-known/openid-configuration'.
|
||||
// discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
|
||||
// certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
|
||||
// must be set to 'oidc.oidc-namespace'.
|
||||
//
|
||||
// curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
|
||||
// {
|
||||
// issuer: "https://oidc.example.com" (.url field)
|
||||
// }
|
||||
//
|
||||
// discoveryURL must be different from url.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +optional
|
||||
DiscoveryURL string
|
||||
CertificateAuthority string
|
||||
Audiences []string
|
||||
AudienceMatchPolicy AudienceMatchPolicyType
|
||||
}
|
||||
|
||||
// AudienceMatchPolicyType is a set of valid values for Issuer.AudienceMatchPolicy
|
||||
type AudienceMatchPolicyType string
|
||||
|
||||
// Valid types for AudienceMatchPolicyType
|
||||
const (
|
||||
AudienceMatchPolicyMatchAny AudienceMatchPolicyType = "MatchAny"
|
||||
)
|
||||
|
||||
// ClaimValidationRule provides the configuration for a single claim validation rule.
|
||||
type ClaimValidationRule struct {
|
||||
Claim string
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
4
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/register.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/register.go
generated
vendored
@ -40,13 +40,17 @@ func init() {
|
||||
// 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(addDefaultingFuncs)
|
||||
}
|
||||
|
||||
// Adds the list of known types to the given scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&AdmissionConfiguration{},
|
||||
&EncryptionConfiguration{},
|
||||
)
|
||||
// also register into the v1 group as EncryptionConfig (due to a docs bug)
|
||||
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "EncryptionConfig"}, &EncryptionConfiguration{})
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
259
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.conversion.go
generated
vendored
259
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.conversion.go
generated
vendored
@ -24,6 +24,7 @@ package v1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
apiserver "k8s.io/apiserver/pkg/apis/apiserver"
|
||||
@ -36,6 +37,16 @@ func init() {
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*AESConfiguration)(nil), (*apiserver.AESConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_AESConfiguration_To_apiserver_AESConfiguration(a.(*AESConfiguration), b.(*apiserver.AESConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.AESConfiguration)(nil), (*AESConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_AESConfiguration_To_v1_AESConfiguration(a.(*apiserver.AESConfiguration), b.(*AESConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*AdmissionConfiguration)(nil), (*apiserver.AdmissionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(a.(*AdmissionConfiguration), b.(*apiserver.AdmissionConfiguration), scope)
|
||||
}); err != nil {
|
||||
@ -56,9 +67,99 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*EncryptionConfiguration)(nil), (*apiserver.EncryptionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(a.(*EncryptionConfiguration), b.(*apiserver.EncryptionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.EncryptionConfiguration)(nil), (*EncryptionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(a.(*apiserver.EncryptionConfiguration), b.(*EncryptionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*IdentityConfiguration)(nil), (*apiserver.IdentityConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(a.(*IdentityConfiguration), b.(*apiserver.IdentityConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.IdentityConfiguration)(nil), (*IdentityConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(a.(*apiserver.IdentityConfiguration), b.(*IdentityConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*KMSConfiguration)(nil), (*apiserver.KMSConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(a.(*KMSConfiguration), b.(*apiserver.KMSConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.KMSConfiguration)(nil), (*KMSConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_KMSConfiguration_To_v1_KMSConfiguration(a.(*apiserver.KMSConfiguration), b.(*KMSConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Key)(nil), (*apiserver.Key)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_Key_To_apiserver_Key(a.(*Key), b.(*apiserver.Key), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.Key)(nil), (*Key)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_Key_To_v1_Key(a.(*apiserver.Key), b.(*Key), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ProviderConfiguration)(nil), (*apiserver.ProviderConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(a.(*ProviderConfiguration), b.(*apiserver.ProviderConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.ProviderConfiguration)(nil), (*ProviderConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_ProviderConfiguration_To_v1_ProviderConfiguration(a.(*apiserver.ProviderConfiguration), b.(*ProviderConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ResourceConfiguration)(nil), (*apiserver.ResourceConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ResourceConfiguration_To_apiserver_ResourceConfiguration(a.(*ResourceConfiguration), b.(*apiserver.ResourceConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.ResourceConfiguration)(nil), (*ResourceConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_ResourceConfiguration_To_v1_ResourceConfiguration(a.(*apiserver.ResourceConfiguration), b.(*ResourceConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*SecretboxConfiguration)(nil), (*apiserver.SecretboxConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_SecretboxConfiguration_To_apiserver_SecretboxConfiguration(a.(*SecretboxConfiguration), b.(*apiserver.SecretboxConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*apiserver.SecretboxConfiguration)(nil), (*SecretboxConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(a.(*apiserver.SecretboxConfiguration), b.(*SecretboxConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_AESConfiguration_To_apiserver_AESConfiguration(in *AESConfiguration, out *apiserver.AESConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]apiserver.Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_AESConfiguration_To_apiserver_AESConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_AESConfiguration_To_apiserver_AESConfiguration(in *AESConfiguration, out *apiserver.AESConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_AESConfiguration_To_apiserver_AESConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_AESConfiguration_To_v1_AESConfiguration(in *apiserver.AESConfiguration, out *AESConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_AESConfiguration_To_v1_AESConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_AESConfiguration_To_v1_AESConfiguration(in *apiserver.AESConfiguration, out *AESConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_AESConfiguration_To_v1_AESConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_AdmissionConfiguration_To_apiserver_AdmissionConfiguration(in *AdmissionConfiguration, out *apiserver.AdmissionConfiguration, s conversion.Scope) error {
|
||||
out.Plugins = *(*[]apiserver.AdmissionPluginConfiguration)(unsafe.Pointer(&in.Plugins))
|
||||
return nil
|
||||
@ -102,3 +203,161 @@ func autoConvert_apiserver_AdmissionPluginConfiguration_To_v1_AdmissionPluginCon
|
||||
func Convert_apiserver_AdmissionPluginConfiguration_To_v1_AdmissionPluginConfiguration(in *apiserver.AdmissionPluginConfiguration, out *AdmissionPluginConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_AdmissionPluginConfiguration_To_v1_AdmissionPluginConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(in *EncryptionConfiguration, out *apiserver.EncryptionConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]apiserver.ResourceConfiguration)(unsafe.Pointer(&in.Resources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(in *EncryptionConfiguration, out *apiserver.EncryptionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_EncryptionConfiguration_To_apiserver_EncryptionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(in *apiserver.EncryptionConfiguration, out *EncryptionConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]ResourceConfiguration)(unsafe.Pointer(&in.Resources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(in *apiserver.EncryptionConfiguration, out *EncryptionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_EncryptionConfiguration_To_v1_EncryptionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(in *IdentityConfiguration, out *apiserver.IdentityConfiguration, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(in *IdentityConfiguration, out *apiserver.IdentityConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_IdentityConfiguration_To_apiserver_IdentityConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(in *apiserver.IdentityConfiguration, out *IdentityConfiguration, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(in *apiserver.IdentityConfiguration, out *IdentityConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_IdentityConfiguration_To_v1_IdentityConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(in *KMSConfiguration, out *apiserver.KMSConfiguration, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Name = in.Name
|
||||
out.CacheSize = (*int32)(unsafe.Pointer(in.CacheSize))
|
||||
out.Endpoint = in.Endpoint
|
||||
out.Timeout = (*metav1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_KMSConfiguration_To_apiserver_KMSConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(in *KMSConfiguration, out *apiserver.KMSConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_KMSConfiguration_To_apiserver_KMSConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_KMSConfiguration_To_v1_KMSConfiguration(in *apiserver.KMSConfiguration, out *KMSConfiguration, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Name = in.Name
|
||||
out.CacheSize = (*int32)(unsafe.Pointer(in.CacheSize))
|
||||
out.Endpoint = in.Endpoint
|
||||
out.Timeout = (*metav1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_KMSConfiguration_To_v1_KMSConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_KMSConfiguration_To_v1_KMSConfiguration(in *apiserver.KMSConfiguration, out *KMSConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_KMSConfiguration_To_v1_KMSConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Key_To_apiserver_Key(in *Key, out *apiserver.Key, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_Key_To_apiserver_Key is an autogenerated conversion function.
|
||||
func Convert_v1_Key_To_apiserver_Key(in *Key, out *apiserver.Key, s conversion.Scope) error {
|
||||
return autoConvert_v1_Key_To_apiserver_Key(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_Key_To_v1_Key(in *apiserver.Key, out *Key, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_Key_To_v1_Key is an autogenerated conversion function.
|
||||
func Convert_apiserver_Key_To_v1_Key(in *apiserver.Key, out *Key, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_Key_To_v1_Key(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(in *ProviderConfiguration, out *apiserver.ProviderConfiguration, s conversion.Scope) error {
|
||||
out.AESGCM = (*apiserver.AESConfiguration)(unsafe.Pointer(in.AESGCM))
|
||||
out.AESCBC = (*apiserver.AESConfiguration)(unsafe.Pointer(in.AESCBC))
|
||||
out.Secretbox = (*apiserver.SecretboxConfiguration)(unsafe.Pointer(in.Secretbox))
|
||||
out.Identity = (*apiserver.IdentityConfiguration)(unsafe.Pointer(in.Identity))
|
||||
out.KMS = (*apiserver.KMSConfiguration)(unsafe.Pointer(in.KMS))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(in *ProviderConfiguration, out *apiserver.ProviderConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_ProviderConfiguration_To_apiserver_ProviderConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ProviderConfiguration_To_v1_ProviderConfiguration(in *apiserver.ProviderConfiguration, out *ProviderConfiguration, s conversion.Scope) error {
|
||||
out.AESGCM = (*AESConfiguration)(unsafe.Pointer(in.AESGCM))
|
||||
out.AESCBC = (*AESConfiguration)(unsafe.Pointer(in.AESCBC))
|
||||
out.Secretbox = (*SecretboxConfiguration)(unsafe.Pointer(in.Secretbox))
|
||||
out.Identity = (*IdentityConfiguration)(unsafe.Pointer(in.Identity))
|
||||
out.KMS = (*KMSConfiguration)(unsafe.Pointer(in.KMS))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_ProviderConfiguration_To_v1_ProviderConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_ProviderConfiguration_To_v1_ProviderConfiguration(in *apiserver.ProviderConfiguration, out *ProviderConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ProviderConfiguration_To_v1_ProviderConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ResourceConfiguration_To_apiserver_ResourceConfiguration(in *ResourceConfiguration, out *apiserver.ResourceConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
|
||||
out.Providers = *(*[]apiserver.ProviderConfiguration)(unsafe.Pointer(&in.Providers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ResourceConfiguration_To_apiserver_ResourceConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_ResourceConfiguration_To_apiserver_ResourceConfiguration(in *ResourceConfiguration, out *apiserver.ResourceConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_ResourceConfiguration_To_apiserver_ResourceConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ResourceConfiguration_To_v1_ResourceConfiguration(in *apiserver.ResourceConfiguration, out *ResourceConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
|
||||
out.Providers = *(*[]ProviderConfiguration)(unsafe.Pointer(&in.Providers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_ResourceConfiguration_To_v1_ResourceConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_ResourceConfiguration_To_v1_ResourceConfiguration(in *apiserver.ResourceConfiguration, out *ResourceConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ResourceConfiguration_To_v1_ResourceConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_SecretboxConfiguration_To_apiserver_SecretboxConfiguration(in *SecretboxConfiguration, out *apiserver.SecretboxConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]apiserver.Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_SecretboxConfiguration_To_apiserver_SecretboxConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_SecretboxConfiguration_To_apiserver_SecretboxConfiguration(in *SecretboxConfiguration, out *apiserver.SecretboxConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_SecretboxConfiguration_To_apiserver_SecretboxConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(in *apiserver.SecretboxConfiguration, out *SecretboxConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(in *apiserver.SecretboxConfiguration, out *SecretboxConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_SecretboxConfiguration_To_v1_SecretboxConfiguration(in, out, s)
|
||||
}
|
||||
|
202
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.deepcopy.go
generated
vendored
202
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.deepcopy.go
generated
vendored
@ -22,9 +22,31 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AESConfiguration) DeepCopyInto(out *AESConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AESConfiguration.
|
||||
func (in *AESConfiguration) DeepCopy() *AESConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AESConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AdmissionConfiguration) DeepCopyInto(out *AdmissionConfiguration) {
|
||||
*out = *in
|
||||
@ -77,3 +99,183 @@ func (in *AdmissionPluginConfiguration) DeepCopy() *AdmissionPluginConfiguration
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EncryptionConfiguration) DeepCopyInto(out *EncryptionConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]ResourceConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EncryptionConfiguration.
|
||||
func (in *EncryptionConfiguration) DeepCopy() *EncryptionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EncryptionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *EncryptionConfiguration) 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 *IdentityConfiguration) DeepCopyInto(out *IdentityConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfiguration.
|
||||
func (in *IdentityConfiguration) DeepCopy() *IdentityConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IdentityConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KMSConfiguration) DeepCopyInto(out *KMSConfiguration) {
|
||||
*out = *in
|
||||
if in.CacheSize != nil {
|
||||
in, out := &in.CacheSize, &out.CacheSize
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(metav1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSConfiguration.
|
||||
func (in *KMSConfiguration) DeepCopy() *KMSConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KMSConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Key) DeepCopyInto(out *Key) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Key.
|
||||
func (in *Key) DeepCopy() *Key {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Key)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) {
|
||||
*out = *in
|
||||
if in.AESGCM != nil {
|
||||
in, out := &in.AESGCM, &out.AESGCM
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AESCBC != nil {
|
||||
in, out := &in.AESCBC, &out.AESCBC
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Secretbox != nil {
|
||||
in, out := &in.Secretbox, &out.Secretbox
|
||||
*out = new(SecretboxConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Identity != nil {
|
||||
in, out := &in.Identity, &out.Identity
|
||||
*out = new(IdentityConfiguration)
|
||||
**out = **in
|
||||
}
|
||||
if in.KMS != nil {
|
||||
in, out := &in.KMS, &out.KMS
|
||||
*out = new(KMSConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfiguration.
|
||||
func (in *ProviderConfiguration) DeepCopy() *ProviderConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProviderConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceConfiguration) DeepCopyInto(out *ResourceConfiguration) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Providers != nil {
|
||||
in, out := &in.Providers, &out.Providers
|
||||
*out = make([]ProviderConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceConfiguration.
|
||||
func (in *ResourceConfiguration) DeepCopy() *ResourceConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SecretboxConfiguration) DeepCopyInto(out *SecretboxConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretboxConfiguration.
|
||||
func (in *SecretboxConfiguration) DeepCopy() *SecretboxConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SecretboxConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
13
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.defaults.go
generated
vendored
13
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/zz_generated.defaults.go
generated
vendored
@ -29,5 +29,18 @@ 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(&EncryptionConfiguration{}, func(obj interface{}) { SetObjectDefaults_EncryptionConfiguration(obj.(*EncryptionConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_EncryptionConfiguration(in *EncryptionConfiguration) {
|
||||
for i := range in.Resources {
|
||||
a := &in.Resources[i]
|
||||
for j := range a.Providers {
|
||||
b := &a.Providers[j]
|
||||
if b.KMS != nil {
|
||||
SetDefaults_KMSConfiguration(b.KMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
81
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go
generated
vendored
81
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go
generated
vendored
@ -176,6 +176,14 @@ type AuthenticationConfiguration struct {
|
||||
// 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.
|
||||
//
|
||||
// The minimum valid JWT payload must contain the following claims:
|
||||
// {
|
||||
// "iss": "https://issuer.example.com",
|
||||
// "aud": ["audience"],
|
||||
// "exp": 1234567890,
|
||||
// "<username claim>": "username"
|
||||
// }
|
||||
JWT []JWTAuthenticator `json:"jwt"`
|
||||
}
|
||||
|
||||
@ -201,17 +209,45 @@ type JWTAuthenticator struct {
|
||||
UserValidationRules []UserValidationRule `json:"userValidationRules,omitempty"`
|
||||
}
|
||||
|
||||
// Issuer provides the configuration for a external provider specific settings.
|
||||
// Issuer provides the configuration for an external provider's 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.
|
||||
// Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +required
|
||||
URL string `json:"url"`
|
||||
|
||||
// discoveryURL, if specified, overrides the URL used to fetch discovery
|
||||
// information instead of using "{url}/.well-known/openid-configuration".
|
||||
// The exact value specified is used, so "/.well-known/openid-configuration"
|
||||
// must be included in discoveryURL if needed.
|
||||
//
|
||||
// The "issuer" field in the fetched discovery information must match the "issuer.url" field
|
||||
// in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
|
||||
// This is for scenarios where the well-known and jwks endpoints are hosted at a different
|
||||
// location than the issuer (such as locally in the cluster).
|
||||
//
|
||||
// Example:
|
||||
// A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
|
||||
// and discovery information is available at '/.well-known/openid-configuration'.
|
||||
// discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
|
||||
// certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
|
||||
// must be set to 'oidc.oidc-namespace'.
|
||||
//
|
||||
// curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
|
||||
// {
|
||||
// issuer: "https://oidc.example.com" (.url field)
|
||||
// }
|
||||
//
|
||||
// discoveryURL must be different from url.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +optional
|
||||
DiscoveryURL *string `json:"discoveryURL,omitempty"`
|
||||
|
||||
// certificateAuthority contains PEM-encoded certificate authority certificates
|
||||
// used to validate the connection when fetching discovery information.
|
||||
// If unset, the system verifier is used.
|
||||
@ -225,8 +261,32 @@ type Issuer struct {
|
||||
// Required to be non-empty.
|
||||
// +required
|
||||
Audiences []string `json:"audiences"`
|
||||
|
||||
// audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT.
|
||||
// Allowed values are:
|
||||
// 1. "MatchAny" when multiple audiences are specified and
|
||||
// 2. empty (or unset) or "MatchAny" when a single audience is specified.
|
||||
//
|
||||
// - MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
|
||||
// For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both).
|
||||
//
|
||||
// - "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others).
|
||||
//
|
||||
// For more nuanced audience validation, use claimValidationRules.
|
||||
// example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match.
|
||||
// +optional
|
||||
AudienceMatchPolicy AudienceMatchPolicyType `json:"audienceMatchPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// AudienceMatchPolicyType is a set of valid values for issuer.audienceMatchPolicy
|
||||
type AudienceMatchPolicyType string
|
||||
|
||||
// Valid types for AudienceMatchPolicyType
|
||||
const (
|
||||
// MatchAny means the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
|
||||
AudienceMatchPolicyMatchAny AudienceMatchPolicyType = "MatchAny"
|
||||
)
|
||||
|
||||
// ClaimValidationRule provides the configuration for a single claim validation rule.
|
||||
type ClaimValidationRule struct {
|
||||
// claim is the name of a required claim.
|
||||
@ -249,7 +309,7 @@ type ClaimValidationRule struct {
|
||||
// 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'.
|
||||
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
|
||||
// Must return true for the validation to pass.
|
||||
//
|
||||
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
|
||||
@ -270,6 +330,10 @@ type ClaimMappings struct {
|
||||
// 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.
|
||||
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
|
||||
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
|
||||
// An example claim validation rule expression that matches the validation automatically
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
|
||||
//
|
||||
// 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.
|
||||
@ -279,7 +343,7 @@ type ClaimMappings struct {
|
||||
// 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>"
|
||||
// (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.
|
||||
@ -338,7 +402,7 @@ type PrefixedClaimOrExpression struct {
|
||||
// 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'.
|
||||
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
|
||||
//
|
||||
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
|
||||
//
|
||||
@ -360,7 +424,7 @@ type ClaimOrExpression struct {
|
||||
// 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'.
|
||||
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
|
||||
//
|
||||
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
|
||||
//
|
||||
@ -376,6 +440,7 @@ type ExtraMapping struct {
|
||||
// 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 to be unique.
|
||||
// +required
|
||||
Key string `json:"key"`
|
||||
|
||||
@ -387,7 +452,7 @@ type ExtraMapping struct {
|
||||
// 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'.
|
||||
// Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
|
||||
//
|
||||
// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
|
||||
//
|
||||
|
33
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go
generated
vendored
33
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.conversion.go
generated
vendored
@ -24,6 +24,7 @@ package v1alpha1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
apiserver "k8s.io/apiserver/pkg/apis/apiserver"
|
||||
@ -324,7 +325,17 @@ func Convert_apiserver_AdmissionPluginConfiguration_To_v1alpha1_AdmissionPluginC
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
|
||||
out.JWT = *(*[]apiserver.JWTAuthenticator)(unsafe.Pointer(&in.JWT))
|
||||
if in.JWT != nil {
|
||||
in, out := &in.JWT, &out.JWT
|
||||
*out = make([]apiserver.JWTAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha1_JWTAuthenticator_To_apiserver_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JWT = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -334,7 +345,17 @@ func Convert_v1alpha1_AuthenticationConfiguration_To_apiserver_AuthenticationCon
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
|
||||
out.JWT = *(*[]JWTAuthenticator)(unsafe.Pointer(&in.JWT))
|
||||
if in.JWT != nil {
|
||||
in, out := &in.JWT, &out.JWT
|
||||
*out = make([]JWTAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiserver_JWTAuthenticator_To_v1alpha1_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JWT = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -580,8 +601,12 @@ func Convert_apiserver_ExtraMapping_To_v1alpha1_ExtraMapping(in *apiserver.Extra
|
||||
|
||||
func autoConvert_v1alpha1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
|
||||
out.URL = in.URL
|
||||
if err := v1.Convert_Pointer_string_To_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificateAuthority = in.CertificateAuthority
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
out.AudienceMatchPolicy = apiserver.AudienceMatchPolicyType(in.AudienceMatchPolicy)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -592,8 +617,12 @@ func Convert_v1alpha1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issu
|
||||
|
||||
func autoConvert_apiserver_Issuer_To_v1alpha1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
|
||||
out.URL = in.URL
|
||||
if err := v1.Convert_string_To_Pointer_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificateAuthority = in.CertificateAuthority
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
out.AudienceMatchPolicy = AudienceMatchPolicyType(in.AudienceMatchPolicy)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
5
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go
generated
vendored
5
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/zz_generated.deepcopy.go
generated
vendored
@ -308,6 +308,11 @@ func (in *ExtraMapping) DeepCopy() *ExtraMapping {
|
||||
// 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.DiscoveryURL != nil {
|
||||
in, out := &in.DiscoveryURL, &out.DiscoveryURL
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Audiences != nil {
|
||||
in, out := &in.Audiences, &out.Audiences
|
||||
*out = make([]string, len(*in))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
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.
|
||||
@ -14,10 +14,23 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:conversion-gen=k8s.io/apiserver/pkg/apis/config
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
package v1beta1
|
||||
|
||||
// Package v1 is the v1 version of the API.
|
||||
package v1
|
||||
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
|
||||
}
|
||||
}
|
4
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/register.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/register.go
generated
vendored
@ -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.
|
||||
@ -52,6 +52,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
&EgressSelectorConfiguration{},
|
||||
)
|
||||
scheme.AddKnownTypes(ConfigSchemeGroupVersion,
|
||||
&AuthenticationConfiguration{},
|
||||
&AuthorizationConfiguration{},
|
||||
&TracingConfiguration{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
|
441
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go
generated
vendored
441
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go
generated
vendored
@ -129,3 +129,444 @@ type TracingConfiguration struct {
|
||||
// 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.
|
||||
//
|
||||
// The minimum valid JWT payload must contain the following claims:
|
||||
// {
|
||||
// "iss": "https://issuer.example.com",
|
||||
// "aud": ["audience"],
|
||||
// "exp": 1234567890,
|
||||
// "<username claim>": "username"
|
||||
// }
|
||||
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 an external provider's 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.
|
||||
// Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +required
|
||||
URL string `json:"url"`
|
||||
|
||||
// discoveryURL, if specified, overrides the URL used to fetch discovery
|
||||
// information instead of using "{url}/.well-known/openid-configuration".
|
||||
// The exact value specified is used, so "/.well-known/openid-configuration"
|
||||
// must be included in discoveryURL if needed.
|
||||
//
|
||||
// The "issuer" field in the fetched discovery information must match the "issuer.url" field
|
||||
// in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT.
|
||||
// This is for scenarios where the well-known and jwks endpoints are hosted at a different
|
||||
// location than the issuer (such as locally in the cluster).
|
||||
//
|
||||
// Example:
|
||||
// A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace'
|
||||
// and discovery information is available at '/.well-known/openid-configuration'.
|
||||
// discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration"
|
||||
// certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate
|
||||
// must be set to 'oidc.oidc-namespace'.
|
||||
//
|
||||
// curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field)
|
||||
// {
|
||||
// issuer: "https://oidc.example.com" (.url field)
|
||||
// }
|
||||
//
|
||||
// discoveryURL must be different from url.
|
||||
// Required to be unique across all JWT authenticators.
|
||||
// Note that egress selection configuration is not used for this network connection.
|
||||
// +optional
|
||||
DiscoveryURL *string `json:"discoveryURL,omitempty"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT.
|
||||
// Allowed values are:
|
||||
// 1. "MatchAny" when multiple audiences are specified and
|
||||
// 2. empty (or unset) or "MatchAny" when a single audience is specified.
|
||||
//
|
||||
// - MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
|
||||
// For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both).
|
||||
//
|
||||
// - "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others).
|
||||
//
|
||||
// For more nuanced audience validation, use claimValidationRules.
|
||||
// example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match.
|
||||
// +optional
|
||||
AudienceMatchPolicy AudienceMatchPolicyType `json:"audienceMatchPolicy,omitempty"`
|
||||
}
|
||||
|
||||
// AudienceMatchPolicyType is a set of valid values for issuer.audienceMatchPolicy
|
||||
type AudienceMatchPolicyType string
|
||||
|
||||
// Valid types for AudienceMatchPolicyType
|
||||
const (
|
||||
// MatchAny means the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field.
|
||||
AudienceMatchPolicyMatchAny AudienceMatchPolicyType = "MatchAny"
|
||||
)
|
||||
|
||||
// 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.foo.bar'.
|
||||
// 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.
|
||||
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
|
||||
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
|
||||
// An example claim validation rule expression that matches the validation automatically
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
|
||||
//
|
||||
// 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.foo.bar'.
|
||||
//
|
||||
// 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.foo.bar'.
|
||||
//
|
||||
// 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 to be unique.
|
||||
// +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.foo.bar'.
|
||||
//
|
||||
// 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"`
|
||||
}
|
||||
|
525
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.conversion.go
generated
vendored
525
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.conversion.go
generated
vendored
@ -24,6 +24,7 @@ package v1beta1
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
apiserver "k8s.io/apiserver/pkg/apis/apiserver"
|
||||
@ -36,6 +37,66 @@ func init() {
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*AuthenticationConfiguration)(nil), (*apiserver.AuthenticationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_Connection_To_apiserver_Connection(a.(*Connection), b.(*apiserver.Connection), scope)
|
||||
}); err != nil {
|
||||
@ -61,6 +122,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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_TCPTransport_To_apiserver_TCPTransport(a.(*TCPTransport), b.(*apiserver.TCPTransport), scope)
|
||||
}); err != nil {
|
||||
@ -111,6 +212,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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_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_v1beta1_EgressSelection_To_apiserver_EgressSelection(a.(*EgressSelection), b.(*apiserver.EgressSelection), scope)
|
||||
}); err != nil {
|
||||
@ -119,6 +260,176 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
|
||||
if in.JWT != nil {
|
||||
in, out := &in.JWT, &out.JWT
|
||||
*out = make([]apiserver.JWTAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JWTAuthenticator_To_apiserver_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JWT = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in *AuthenticationConfiguration, out *apiserver.AuthenticationConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_AuthenticationConfiguration_To_apiserver_AuthenticationConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_AuthenticationConfiguration_To_v1beta1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
|
||||
if in.JWT != nil {
|
||||
in, out := &in.JWT, &out.JWT
|
||||
*out = make([]JWTAuthenticator, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiserver_JWTAuthenticator_To_v1beta1_JWTAuthenticator(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JWT = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_AuthenticationConfiguration_To_v1beta1_AuthenticationConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_AuthenticationConfiguration_To_v1beta1_AuthenticationConfiguration(in *apiserver.AuthenticationConfiguration, out *AuthenticationConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_AuthenticationConfiguration_To_v1beta1_AuthenticationConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
|
||||
out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
|
||||
out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_AuthorizationConfiguration_To_v1beta1_AuthorizationConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_AuthorizerConfiguration_To_v1beta1_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_v1beta1_AuthorizerConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_AuthorizerConfiguration_To_v1beta1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_AuthorizerConfiguration_To_v1beta1_AuthorizerConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_ClaimOrExpression_To_apiserver_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Extra = *(*[]apiserver.ExtraMapping)(unsafe.Pointer(&in.Extra))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ClaimMappings_To_apiserver_ClaimMappings is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ClaimMappings_To_apiserver_ClaimMappings(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ClaimMappings_To_v1beta1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
|
||||
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1beta1_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_apiserver_PrefixedClaimOrExpression_To_v1beta1_PrefixedClaimOrExpression(&in.Groups, &out.Groups, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_apiserver_ClaimOrExpression_To_v1beta1_ClaimOrExpression(&in.UID, &out.UID, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Extra = *(*[]ExtraMapping)(unsafe.Pointer(&in.Extra))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_ClaimMappings_To_v1beta1_ClaimMappings is an autogenerated conversion function.
|
||||
func Convert_apiserver_ClaimMappings_To_v1beta1_ClaimMappings(in *apiserver.ClaimMappings, out *ClaimMappings, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ClaimMappings_To_v1beta1_ClaimMappings(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
|
||||
out.Claim = in.Claim
|
||||
out.Expression = in.Expression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ClaimOrExpression_To_apiserver_ClaimOrExpression is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in *ClaimOrExpression, out *apiserver.ClaimOrExpression, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ClaimOrExpression_To_apiserver_ClaimOrExpression(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ClaimOrExpression_To_v1beta1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
|
||||
out.Claim = in.Claim
|
||||
out.Expression = in.Expression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_ClaimOrExpression_To_v1beta1_ClaimOrExpression is an autogenerated conversion function.
|
||||
func Convert_apiserver_ClaimOrExpression_To_v1beta1_ClaimOrExpression(in *apiserver.ClaimOrExpression, out *ClaimOrExpression, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ClaimOrExpression_To_v1beta1_ClaimOrExpression(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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_v1beta1_ClaimValidationRule_To_apiserver_ClaimValidationRule is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in *ClaimValidationRule, out *apiserver.ClaimValidationRule, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ClaimValidationRule_To_apiserver_ClaimValidationRule(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ClaimValidationRule_To_v1beta1_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_v1beta1_ClaimValidationRule is an autogenerated conversion function.
|
||||
func Convert_apiserver_ClaimValidationRule_To_v1beta1_ClaimValidationRule(in *apiserver.ClaimValidationRule, out *ClaimValidationRule, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ClaimValidationRule_To_v1beta1_ClaimValidationRule(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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))
|
||||
@ -202,6 +513,118 @@ func Convert_apiserver_EgressSelectorConfiguration_To_v1beta1_EgressSelectorConf
|
||||
return autoConvert_apiserver_EgressSelectorConfiguration_To_v1beta1_EgressSelectorConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
|
||||
out.Key = in.Key
|
||||
out.ValueExpression = in.ValueExpression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExtraMapping_To_apiserver_ExtraMapping is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExtraMapping_To_apiserver_ExtraMapping(in *ExtraMapping, out *apiserver.ExtraMapping, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExtraMapping_To_apiserver_ExtraMapping(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_ExtraMapping_To_v1beta1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
|
||||
out.Key = in.Key
|
||||
out.ValueExpression = in.ValueExpression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_ExtraMapping_To_v1beta1_ExtraMapping is an autogenerated conversion function.
|
||||
func Convert_apiserver_ExtraMapping_To_v1beta1_ExtraMapping(in *apiserver.ExtraMapping, out *ExtraMapping, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_ExtraMapping_To_v1beta1_ExtraMapping(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
|
||||
out.URL = in.URL
|
||||
if err := v1.Convert_Pointer_string_To_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificateAuthority = in.CertificateAuthority
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
out.AudienceMatchPolicy = apiserver.AudienceMatchPolicyType(in.AudienceMatchPolicy)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_Issuer_To_apiserver_Issuer is an autogenerated conversion function.
|
||||
func Convert_v1beta1_Issuer_To_apiserver_Issuer(in *Issuer, out *apiserver.Issuer, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_Issuer_To_apiserver_Issuer(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_Issuer_To_v1beta1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
|
||||
out.URL = in.URL
|
||||
if err := v1.Convert_string_To_Pointer_string(&in.DiscoveryURL, &out.DiscoveryURL, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.CertificateAuthority = in.CertificateAuthority
|
||||
out.Audiences = *(*[]string)(unsafe.Pointer(&in.Audiences))
|
||||
out.AudienceMatchPolicy = AudienceMatchPolicyType(in.AudienceMatchPolicy)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_Issuer_To_v1beta1_Issuer is an autogenerated conversion function.
|
||||
func Convert_apiserver_Issuer_To_v1beta1_Issuer(in *apiserver.Issuer, out *Issuer, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_Issuer_To_v1beta1_Issuer(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_Issuer_To_apiserver_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.ClaimValidationRules = *(*[]apiserver.ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
|
||||
if err := Convert_v1beta1_ClaimMappings_To_apiserver_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.UserValidationRules = *(*[]apiserver.UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JWTAuthenticator_To_apiserver_JWTAuthenticator is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in *JWTAuthenticator, out *apiserver.JWTAuthenticator, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JWTAuthenticator_To_apiserver_JWTAuthenticator(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_JWTAuthenticator_To_v1beta1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
|
||||
if err := Convert_apiserver_Issuer_To_v1beta1_Issuer(&in.Issuer, &out.Issuer, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.ClaimValidationRules = *(*[]ClaimValidationRule)(unsafe.Pointer(&in.ClaimValidationRules))
|
||||
if err := Convert_apiserver_ClaimMappings_To_v1beta1_ClaimMappings(&in.ClaimMappings, &out.ClaimMappings, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.UserValidationRules = *(*[]UserValidationRule)(unsafe.Pointer(&in.UserValidationRules))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_JWTAuthenticator_To_v1beta1_JWTAuthenticator is an autogenerated conversion function.
|
||||
func Convert_apiserver_JWTAuthenticator_To_v1beta1_JWTAuthenticator(in *apiserver.JWTAuthenticator, out *JWTAuthenticator, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_JWTAuthenticator_To_v1beta1_JWTAuthenticator(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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_v1beta1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression is an autogenerated conversion function.
|
||||
func Convert_v1beta1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in *PrefixedClaimOrExpression, out *apiserver.PrefixedClaimOrExpression, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_PrefixedClaimOrExpression_To_v1beta1_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_v1beta1_PrefixedClaimOrExpression is an autogenerated conversion function.
|
||||
func Convert_apiserver_PrefixedClaimOrExpression_To_v1beta1_PrefixedClaimOrExpression(in *apiserver.PrefixedClaimOrExpression, out *PrefixedClaimOrExpression, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_PrefixedClaimOrExpression_To_v1beta1_PrefixedClaimOrExpression(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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))
|
||||
@ -309,3 +732,105 @@ func autoConvert_apiserver_UDSTransport_To_v1beta1_UDSTransport(in *apiserver.UD
|
||||
func Convert_apiserver_UDSTransport_To_v1beta1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_UDSTransport_To_v1beta1_UDSTransport(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
|
||||
out.Expression = in.Expression
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_UserValidationRule_To_apiserver_UserValidationRule is an autogenerated conversion function.
|
||||
func Convert_v1beta1_UserValidationRule_To_apiserver_UserValidationRule(in *UserValidationRule, out *apiserver.UserValidationRule, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_UserValidationRule_To_apiserver_UserValidationRule(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_UserValidationRule_To_v1beta1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
|
||||
out.Expression = in.Expression
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_UserValidationRule_To_v1beta1_UserValidationRule is an autogenerated conversion function.
|
||||
func Convert_apiserver_UserValidationRule_To_v1beta1_UserValidationRule(in *apiserver.UserValidationRule, out *UserValidationRule, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_UserValidationRule_To_v1beta1_UserValidationRule(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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_v1beta1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.MatchConditions = *(*[]apiserver.WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_WebhookConfiguration_To_v1beta1_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_v1beta1_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.MatchConditions = *(*[]WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_WebhookConfiguration_To_v1beta1_WebhookConfiguration is an autogenerated conversion function.
|
||||
func Convert_apiserver_WebhookConfiguration_To_v1beta1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_WebhookConfiguration_To_v1beta1_WebhookConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_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_v1beta1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo is an autogenerated conversion function.
|
||||
func Convert_v1beta1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in *WebhookConnectionInfo, out *apiserver.WebhookConnectionInfo, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_WebhookConnectionInfo_To_v1beta1_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_v1beta1_WebhookConnectionInfo is an autogenerated conversion function.
|
||||
func Convert_apiserver_WebhookConnectionInfo_To_v1beta1_WebhookConnectionInfo(in *apiserver.WebhookConnectionInfo, out *WebhookConnectionInfo, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_WebhookConnectionInfo_To_v1beta1_WebhookConnectionInfo(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
|
||||
out.Expression = in.Expression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition is an autogenerated conversion function.
|
||||
func Convert_v1beta1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiserver_WebhookMatchCondition_To_v1beta1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
|
||||
out.Expression = in.Expression
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiserver_WebhookMatchCondition_To_v1beta1_WebhookMatchCondition is an autogenerated conversion function.
|
||||
func Convert_apiserver_WebhookMatchCondition_To_v1beta1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
|
||||
return autoConvert_apiserver_WebhookMatchCondition_To_v1beta1_WebhookMatchCondition(in, out, s)
|
||||
}
|
||||
|
310
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.deepcopy.go
generated
vendored
310
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.deepcopy.go
generated
vendored
@ -25,6 +25,147 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// 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
|
||||
@ -95,6 +236,97 @@ 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.DiscoveryURL != nil {
|
||||
in, out := &in.DiscoveryURL, &out.DiscoveryURL
|
||||
*out = new(string)
|
||||
**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
|
||||
@ -199,3 +431,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
|
||||
}
|
||||
|
10
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.defaults.go
generated
vendored
10
vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/zz_generated.defaults.go
generated
vendored
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
287
vendor/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go
generated
vendored
287
vendor/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go
generated
vendored
@ -25,6 +25,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
celgo "github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/operators"
|
||||
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
|
||||
v1 "k8s.io/api/authorization/v1"
|
||||
"k8s.io/api/authorization/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -40,44 +44,38 @@ import (
|
||||
"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 {
|
||||
func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration, disallowedIssuers []string) field.ErrorList {
|
||||
root := field.NewPath("jwt")
|
||||
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)))
|
||||
// We allow 0 authenticators in the authentication configuration.
|
||||
// This allows us to support scenarios where the API server is initially set up without
|
||||
// any authenticators and then authenticators are added later via dynamic config.
|
||||
|
||||
if len(c.JWT) > 64 {
|
||||
allErrs = append(allErrs, field.TooMany(root, len(c.JWT), 64))
|
||||
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.
|
||||
seenIssuers := sets.New[string]()
|
||||
seenDiscoveryURLs := sets.New[string]()
|
||||
for i, a := range c.JWT {
|
||||
fldPath := root.Index(i)
|
||||
_, errs := validateJWTAuthenticator(a, fldPath, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration))
|
||||
_, errs := validateJWTAuthenticator(a, fldPath, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration))
|
||||
allErrs = append(allErrs, errs...)
|
||||
|
||||
if seenIssuers.Has(a.Issuer.URL) {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath.Child("issuer").Child("url"), a.Issuer.URL))
|
||||
}
|
||||
seenIssuers.Insert(a.Issuer.URL)
|
||||
|
||||
if len(a.Issuer.DiscoveryURL) > 0 {
|
||||
if seenDiscoveryURLs.Has(a.Issuer.DiscoveryURL) {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath.Child("issuer").Child("discoveryURL"), a.Issuer.DiscoveryURL))
|
||||
}
|
||||
seenDiscoveryURLs.Insert(a.Issuer.DiscoveryURL)
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
@ -86,40 +84,70 @@ func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration) fie
|
||||
// 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 CompileAndValidateJWTAuthenticator(authenticator api.JWTAuthenticator, disallowedIssuers []string) (authenticationcel.CELMapper, field.ErrorList) {
|
||||
return validateJWTAuthenticator(authenticator, nil, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration))
|
||||
}
|
||||
|
||||
func validateJWTAuthenticator(authenticator api.JWTAuthenticator, fldPath *field.Path, structuredAuthnFeatureEnabled bool) (authenticationcel.CELMapper, field.ErrorList) {
|
||||
func validateJWTAuthenticator(authenticator api.JWTAuthenticator, fldPath *field.Path, disallowedIssuers sets.Set[string], structuredAuthnFeatureEnabled bool) (authenticationcel.CELMapper, field.ErrorList) {
|
||||
var allErrs field.ErrorList
|
||||
|
||||
compiler := authenticationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
|
||||
mapper := &authenticationcel.CELMapper{}
|
||||
state := &validationState{}
|
||||
|
||||
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)...)
|
||||
allErrs = append(allErrs, validateIssuer(authenticator.Issuer, disallowedIssuers, fldPath.Child("issuer"))...)
|
||||
allErrs = append(allErrs, validateClaimValidationRules(compiler, state, authenticator.ClaimValidationRules, fldPath.Child("claimValidationRules"), structuredAuthnFeatureEnabled)...)
|
||||
allErrs = append(allErrs, validateClaimMappings(compiler, state, authenticator.ClaimMappings, fldPath.Child("claimMappings"), structuredAuthnFeatureEnabled)...)
|
||||
allErrs = append(allErrs, validateUserValidationRules(compiler, state, authenticator.UserValidationRules, fldPath.Child("userValidationRules"), structuredAuthnFeatureEnabled)...)
|
||||
|
||||
return *mapper, allErrs
|
||||
return state.mapper, allErrs
|
||||
}
|
||||
|
||||
func validateIssuer(issuer api.Issuer, fldPath *field.Path) field.ErrorList {
|
||||
type validationState struct {
|
||||
mapper authenticationcel.CELMapper
|
||||
usesEmailClaim bool
|
||||
usesEmailVerifiedClaim bool
|
||||
}
|
||||
|
||||
func validateIssuer(issuer api.Issuer, disallowedIssuers sets.Set[string], 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, validateIssuerURL(issuer.URL, disallowedIssuers, fldPath.Child("url"))...)
|
||||
allErrs = append(allErrs, validateIssuerDiscoveryURL(issuer.URL, issuer.DiscoveryURL, fldPath.Child("discoveryURL"))...)
|
||||
allErrs = append(allErrs, validateAudiences(issuer.Audiences, issuer.AudienceMatchPolicy, fldPath.Child("audiences"), fldPath.Child("audienceMatchPolicy"))...)
|
||||
allErrs = append(allErrs, validateCertificateAuthority(issuer.CertificateAuthority, fldPath.Child("certificateAuthority"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateURL(issuerURL string, fldPath *field.Path) field.ErrorList {
|
||||
func validateIssuerURL(issuerURL string, disallowedIssuers sets.Set[string], fldPath *field.Path) field.ErrorList {
|
||||
if len(issuerURL) == 0 {
|
||||
return field.ErrorList{field.Required(fldPath, "URL is required")}
|
||||
}
|
||||
|
||||
return validateURL(issuerURL, disallowedIssuers, fldPath)
|
||||
}
|
||||
|
||||
func validateIssuerDiscoveryURL(issuerURL, issuerDiscoveryURL 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
|
||||
if len(issuerDiscoveryURL) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(issuerURL) > 0 && strings.TrimRight(issuerURL, "/") == strings.TrimRight(issuerDiscoveryURL, "/") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, issuerDiscoveryURL, "discoveryURL must be different from URL"))
|
||||
}
|
||||
|
||||
// issuerDiscoveryURL is not an issuer URL and does not need to validated against any set of disallowed issuers
|
||||
allErrs = append(allErrs, validateURL(issuerDiscoveryURL, nil, fldPath)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateURL(issuerURL string, disallowedIssuers sets.Set[string], fldPath *field.Path) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
|
||||
if disallowedIssuers.Has(issuerURL) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, issuerURL, fmt.Sprintf("URL must not overlap with disallowed issuers: %s", sets.List(disallowedIssuers))))
|
||||
}
|
||||
|
||||
u, err := url.Parse(issuerURL)
|
||||
@ -143,25 +171,31 @@ func validateURL(issuerURL string, fldPath *field.Path) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateAudiences(audiences []string, fldPath *field.Path) field.ErrorList {
|
||||
func validateAudiences(audiences []string, audienceMatchPolicy api.AudienceMatchPolicyType, fldPath, audienceMatchPolicyFldPath *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
|
||||
}
|
||||
|
||||
seenAudiences := sets.NewString()
|
||||
for i, audience := range audiences {
|
||||
fldPath := fldPath.Index(i)
|
||||
if len(audience) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath, "audience can't be empty"))
|
||||
}
|
||||
if seenAudiences.Has(audience) {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath, audience))
|
||||
}
|
||||
seenAudiences.Insert(audience)
|
||||
}
|
||||
|
||||
if len(audiences) > 1 && audienceMatchPolicy != api.AudienceMatchPolicyMatchAny {
|
||||
allErrs = append(allErrs, field.Invalid(audienceMatchPolicyFldPath, audienceMatchPolicy, "audienceMatchPolicy must be MatchAny for multiple audiences"))
|
||||
}
|
||||
if len(audiences) == 1 && (len(audienceMatchPolicy) > 0 && audienceMatchPolicy != api.AudienceMatchPolicyMatchAny) {
|
||||
allErrs = append(allErrs, field.Invalid(audienceMatchPolicyFldPath, audienceMatchPolicy, "audienceMatchPolicy must be empty or MatchAny for single audience"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
@ -181,7 +215,7 @@ func validateCertificateAuthority(certificateAuthority string, fldPath *field.Pa
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateClaimValidationRules(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, rules []api.ClaimValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
func validateClaimValidationRules(compiler authenticationcel.Compiler, state *validationState, rules []api.ClaimValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
|
||||
seenClaims := sets.NewString()
|
||||
@ -220,6 +254,7 @@ func validateClaimValidationRules(compiler authenticationcel.Compiler, celMapper
|
||||
|
||||
compilationResult, err := compileClaimsCELExpression(compiler, &authenticationcel.ClaimValidationCondition{
|
||||
Expression: rule.Expression,
|
||||
Message: rule.Message,
|
||||
}, fldPath.Child("expression"))
|
||||
|
||||
if err != nil {
|
||||
@ -233,13 +268,14 @@ func validateClaimValidationRules(compiler authenticationcel.Compiler, celMapper
|
||||
}
|
||||
|
||||
if structuredAuthnFeatureEnabled && len(compilationResults) > 0 {
|
||||
celMapper.ClaimValidationRules = authenticationcel.NewClaimsMapper(compilationResults)
|
||||
state.mapper.ClaimValidationRules = authenticationcel.NewClaimsMapper(compilationResults)
|
||||
state.usesEmailVerifiedClaim = state.usesEmailVerifiedClaim || anyUsesEmailVerifiedClaim(compilationResults)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateClaimMappings(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, m api.ClaimMappings, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
func validateClaimMappings(compiler authenticationcel.Compiler, state *validationState, m api.ClaimMappings, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
|
||||
if !structuredAuthnFeatureEnabled {
|
||||
@ -257,18 +293,20 @@ func validateClaimMappings(compiler authenticationcel.Compiler, celMapper *authe
|
||||
}
|
||||
}
|
||||
|
||||
compilationResult, err := validatePrefixClaimOrExpression(compiler, m.Username, fldPath.Child("username"), true, structuredAuthnFeatureEnabled)
|
||||
compilationResult, err := validatePrefixClaimOrExpression(compiler, m.Username, fldPath.Child("username"), true)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, err...)
|
||||
} else if compilationResult != nil && structuredAuthnFeatureEnabled {
|
||||
celMapper.Username = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
state.usesEmailClaim = state.usesEmailClaim || usesEmailClaim(compilationResult.AST)
|
||||
state.usesEmailVerifiedClaim = state.usesEmailVerifiedClaim || usesEmailVerifiedClaim(compilationResult.AST)
|
||||
state.mapper.Username = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
}
|
||||
|
||||
compilationResult, err = validatePrefixClaimOrExpression(compiler, m.Groups, fldPath.Child("groups"), false, structuredAuthnFeatureEnabled)
|
||||
compilationResult, err = validatePrefixClaimOrExpression(compiler, m.Groups, fldPath.Child("groups"), false)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, err...)
|
||||
} else if compilationResult != nil && structuredAuthnFeatureEnabled {
|
||||
celMapper.Groups = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
state.mapper.Groups = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
}
|
||||
|
||||
switch {
|
||||
@ -282,7 +320,7 @@ func validateClaimMappings(compiler authenticationcel.Compiler, celMapper *authe
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, err)
|
||||
} else if structuredAuthnFeatureEnabled && compilationResult != nil {
|
||||
celMapper.UID = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
state.mapper.UID = authenticationcel.NewClaimsMapper([]authenticationcel.CompilationResult{*compilationResult})
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,13 +364,124 @@ func validateClaimMappings(compiler authenticationcel.Compiler, celMapper *authe
|
||||
}
|
||||
|
||||
if structuredAuthnFeatureEnabled && len(extraCompilationResults) > 0 {
|
||||
celMapper.Extra = authenticationcel.NewClaimsMapper(extraCompilationResults)
|
||||
state.mapper.Extra = authenticationcel.NewClaimsMapper(extraCompilationResults)
|
||||
state.usesEmailVerifiedClaim = state.usesEmailVerifiedClaim || anyUsesEmailVerifiedClaim(extraCompilationResults)
|
||||
}
|
||||
|
||||
if structuredAuthnFeatureEnabled && state.usesEmailClaim && !state.usesEmailVerifiedClaim {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("username", "expression"), m.Username.Expression,
|
||||
"claims.email_verified must be used in claimMappings.username.expression or claimMappings.extra[*].valueExpression or claimValidationRules[*].expression when claims.email is used in claimMappings.username.expression"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validatePrefixClaimOrExpression(compiler authenticationcel.Compiler, mapping api.PrefixedClaimOrExpression, fldPath *field.Path, claimOrExpressionRequired, structuredAuthnFeatureEnabled bool) (*authenticationcel.CompilationResult, field.ErrorList) {
|
||||
func usesEmailClaim(ast *celgo.Ast) bool {
|
||||
return hasSelectExp(ast.Expr(), "claims", "email")
|
||||
}
|
||||
|
||||
func anyUsesEmailVerifiedClaim(results []authenticationcel.CompilationResult) bool {
|
||||
for _, result := range results {
|
||||
if usesEmailVerifiedClaim(result.AST) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func usesEmailVerifiedClaim(ast *celgo.Ast) bool {
|
||||
return hasSelectExp(ast.Expr(), "claims", "email_verified")
|
||||
}
|
||||
|
||||
func hasSelectExp(exp *exprpb.Expr, operand, field string) bool {
|
||||
if exp == nil {
|
||||
return false
|
||||
}
|
||||
switch e := exp.ExprKind.(type) {
|
||||
case *exprpb.Expr_ConstExpr,
|
||||
*exprpb.Expr_IdentExpr:
|
||||
return false
|
||||
case *exprpb.Expr_SelectExpr:
|
||||
s := e.SelectExpr
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
if isIdentOperand(s.Operand, operand) && s.Field == field {
|
||||
return true
|
||||
}
|
||||
return hasSelectExp(s.Operand, operand, field)
|
||||
case *exprpb.Expr_CallExpr:
|
||||
c := e.CallExpr
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
if c.Target == nil && c.Function == operators.OptSelect && len(c.Args) == 2 &&
|
||||
isIdentOperand(c.Args[0], operand) && isConstField(c.Args[1], field) {
|
||||
return true
|
||||
}
|
||||
for _, arg := range c.Args {
|
||||
if hasSelectExp(arg, operand, field) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return hasSelectExp(c.Target, operand, field)
|
||||
case *exprpb.Expr_ListExpr:
|
||||
l := e.ListExpr
|
||||
if l == nil {
|
||||
return false
|
||||
}
|
||||
for _, element := range l.Elements {
|
||||
if hasSelectExp(element, operand, field) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case *exprpb.Expr_StructExpr:
|
||||
s := e.StructExpr
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
for _, entry := range s.Entries {
|
||||
if hasSelectExp(entry.GetMapKey(), operand, field) {
|
||||
return true
|
||||
}
|
||||
if hasSelectExp(entry.Value, operand, field) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case *exprpb.Expr_ComprehensionExpr:
|
||||
c := e.ComprehensionExpr
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
return hasSelectExp(c.IterRange, operand, field) ||
|
||||
hasSelectExp(c.AccuInit, operand, field) ||
|
||||
hasSelectExp(c.LoopCondition, operand, field) ||
|
||||
hasSelectExp(c.LoopStep, operand, field) ||
|
||||
hasSelectExp(c.Result, operand, field)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isIdentOperand(exp *exprpb.Expr, operand string) bool {
|
||||
if len(operand) == 0 {
|
||||
return false // sanity check against default values
|
||||
}
|
||||
id := exp.GetIdentExpr() // does not panic even if exp is nil
|
||||
return id != nil && id.Name == operand
|
||||
}
|
||||
|
||||
func isConstField(exp *exprpb.Expr, field string) bool {
|
||||
if len(field) == 0 {
|
||||
return false // sanity check against default values
|
||||
}
|
||||
c := exp.GetConstExpr() // does not panic even if exp is nil
|
||||
return c != nil && c.GetStringValue() == field // does not panic even if c is not a string
|
||||
}
|
||||
|
||||
func validatePrefixClaimOrExpression(compiler authenticationcel.Compiler, mapping api.PrefixedClaimOrExpression, fldPath *field.Path, claimOrExpressionRequired bool) (*authenticationcel.CompilationResult, field.ErrorList) {
|
||||
var allErrs field.ErrorList
|
||||
|
||||
var compilationResult *authenticationcel.CompilationResult
|
||||
@ -364,7 +513,7 @@ func validatePrefixClaimOrExpression(compiler authenticationcel.Compiler, mappin
|
||||
return compilationResult, allErrs
|
||||
}
|
||||
|
||||
func validateUserValidationRules(compiler authenticationcel.Compiler, celMapper *authenticationcel.CELMapper, rules []api.UserValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
func validateUserValidationRules(compiler authenticationcel.Compiler, state *validationState, rules []api.UserValidationRule, fldPath *field.Path, structuredAuthnFeatureEnabled bool) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
var compilationResults []authenticationcel.CompilationResult
|
||||
|
||||
@ -403,7 +552,7 @@ func validateUserValidationRules(compiler authenticationcel.Compiler, celMapper
|
||||
}
|
||||
|
||||
if structuredAuthnFeatureEnabled && len(compilationResults) > 0 {
|
||||
celMapper.UserValidationRules = authenticationcel.NewUserMapper(compilationResults)
|
||||
state.mapper.UserValidationRules = authenticationcel.NewUserMapper(compilationResults)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
@ -412,7 +561,7 @@ func validateUserValidationRules(compiler authenticationcel.Compiler, celMapper
|
||||
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 nil, convertCELErrorToValidationError(fldPath, expression.GetExpression(), err)
|
||||
}
|
||||
return &compilationResult, nil
|
||||
}
|
||||
@ -420,7 +569,7 @@ func compileClaimsCELExpression(compiler authenticationcel.Compiler, expression
|
||||
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 nil, convertCELErrorToValidationError(fldPath, expression.GetExpression(), err)
|
||||
}
|
||||
return &compilationResult, nil
|
||||
}
|
||||
@ -609,19 +758,19 @@ func compileMatchConditionsExpression(fldPath *field.Path, compiler authorizatio
|
||||
}
|
||||
compilationResult, err := compiler.CompileCELExpression(authzExpression)
|
||||
if err != nil {
|
||||
return compilationResult, convertCELErrorToValidationError(fldPath, authzExpression, err)
|
||||
return compilationResult, convertCELErrorToValidationError(fldPath, authzExpression.GetExpression(), err)
|
||||
}
|
||||
return compilationResult, nil
|
||||
}
|
||||
|
||||
func convertCELErrorToValidationError(fldPath *field.Path, expression authorizationcel.ExpressionAccessor, err error) *field.Error {
|
||||
func convertCELErrorToValidationError(fldPath *field.Path, expression string, 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)
|
||||
return field.Invalid(fldPath, expression, celErr.Detail)
|
||||
default:
|
||||
return field.InternalError(fldPath, celErr)
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"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"
|
||||
"k8s.io/apiserver/pkg/apis/apiserver"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -59,12 +59,11 @@ var (
|
||||
|
||||
// See https://godoc.org/golang.org/x/crypto/nacl/secretbox#Open for details on the supported key sizes for Secretbox.
|
||||
secretBoxKeySizes = []int{32}
|
||||
|
||||
root = field.NewPath("resources")
|
||||
)
|
||||
|
||||
// ValidateEncryptionConfiguration validates a v1.EncryptionConfiguration.
|
||||
func ValidateEncryptionConfiguration(c *config.EncryptionConfiguration, reload bool) field.ErrorList {
|
||||
func ValidateEncryptionConfiguration(c *apiserver.EncryptionConfiguration, reload bool) field.ErrorList {
|
||||
root := field.NewPath("resources")
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if c == nil {
|
||||
@ -78,7 +77,7 @@ func ValidateEncryptionConfiguration(c *config.EncryptionConfiguration, reload b
|
||||
}
|
||||
|
||||
// kmsProviderNames is used to track config names to ensure they are unique.
|
||||
kmsProviderNames := sets.NewString()
|
||||
kmsProviderNames := sets.New[string]()
|
||||
for i, conf := range c.Resources {
|
||||
r := root.Index(i).Child("resources")
|
||||
p := root.Index(i).Child("providers")
|
||||
@ -284,7 +283,7 @@ func validateResourceNames(resources []string, fieldPath *field.Path) field.Erro
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateSingleProvider(provider config.ProviderConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
func validateSingleProvider(provider apiserver.ProviderConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
found := 0
|
||||
|
||||
@ -315,7 +314,7 @@ func validateSingleProvider(provider config.ProviderConfiguration, fieldPath *fi
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKeys(keys []config.Key, fieldPath *field.Path, expectedLen []int) field.ErrorList {
|
||||
func validateKeys(keys []apiserver.Key, fieldPath *field.Path, expectedLen []int) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(keys) == 0 {
|
||||
@ -330,7 +329,7 @@ func validateKeys(keys []config.Key, fieldPath *field.Path, expectedLen []int) f
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKey(key config.Key, fieldPath *field.Path, expectedLen []int) field.ErrorList {
|
||||
func validateKey(key apiserver.Key, fieldPath *field.Path, expectedLen []int) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if key.Name == "" {
|
||||
@ -363,7 +362,7 @@ func validateKey(key config.Key, fieldPath *field.Path, expectedLen []int) field
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSConfiguration(c *config.KMSConfiguration, fieldPath *field.Path, kmsProviderNames sets.String, reload bool) field.ErrorList {
|
||||
func validateKMSConfiguration(c *apiserver.KMSConfiguration, fieldPath *field.Path, kmsProviderNames sets.Set[string], reload bool) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
allErrs = append(allErrs, validateKMSConfigName(c, fieldPath.Child("name"), kmsProviderNames, reload)...)
|
||||
@ -374,7 +373,7 @@ func validateKMSConfiguration(c *config.KMSConfiguration, fieldPath *field.Path,
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSCacheSize(c *config.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
func validateKMSCacheSize(c *apiserver.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// In defaulting, we set the cache size to the default value only when API version is v1.
|
||||
@ -389,7 +388,7 @@ func validateKMSCacheSize(c *config.KMSConfiguration, fieldPath *field.Path) fie
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSTimeout(c *config.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
func validateKMSTimeout(c *apiserver.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if c.Timeout.Duration <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath, c.Timeout, fmt.Sprintf(zeroOrNegativeErrFmt, "timeout")))
|
||||
@ -398,7 +397,7 @@ func validateKMSTimeout(c *config.KMSConfiguration, fieldPath *field.Path) field
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSEndpoint(c *config.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
func validateKMSEndpoint(c *apiserver.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(c.Endpoint) == 0 {
|
||||
return append(allErrs, field.Invalid(fieldPath, "", fmt.Sprintf(mandatoryFieldErrFmt, "endpoint", "kms")))
|
||||
@ -416,7 +415,7 @@ func validateKMSEndpoint(c *config.KMSConfiguration, fieldPath *field.Path) fiel
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSAPIVersion(c *config.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
func validateKMSAPIVersion(c *apiserver.KMSConfiguration, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if c.APIVersion != "v1" && c.APIVersion != "v2" {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath, c.APIVersion, fmt.Sprintf(unsupportedKMSAPIVersionErrFmt, "apiVersion")))
|
||||
@ -425,7 +424,7 @@ func validateKMSAPIVersion(c *config.KMSConfiguration, fieldPath *field.Path) fi
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateKMSConfigName(c *config.KMSConfiguration, fieldPath *field.Path, kmsProviderNames sets.String, reload bool) field.ErrorList {
|
||||
func validateKMSConfigName(c *apiserver.KMSConfiguration, fieldPath *field.Path, kmsProviderNames sets.Set[string], reload bool) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if c.Name == "" {
|
||||
allErrs = append(allErrs, field.Required(fieldPath, fmt.Sprintf(mandatoryFieldErrFmt, "name", "provider")))
|
202
vendor/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go
generated
vendored
202
vendor/k8s.io/apiserver/pkg/apis/apiserver/zz_generated.deepcopy.go
generated
vendored
@ -22,9 +22,31 @@ limitations under the License.
|
||||
package apiserver
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AESConfiguration) DeepCopyInto(out *AESConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AESConfiguration.
|
||||
func (in *AESConfiguration) DeepCopy() *AESConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AESConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AdmissionConfiguration) DeepCopyInto(out *AdmissionConfiguration) {
|
||||
*out = *in
|
||||
@ -289,6 +311,38 @@ 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 *EncryptionConfiguration) DeepCopyInto(out *EncryptionConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]ResourceConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EncryptionConfiguration.
|
||||
func (in *EncryptionConfiguration) DeepCopy() *EncryptionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EncryptionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *EncryptionConfiguration) 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 *ExtraMapping) DeepCopyInto(out *ExtraMapping) {
|
||||
*out = *in
|
||||
@ -305,6 +359,22 @@ func (in *ExtraMapping) DeepCopy() *ExtraMapping {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IdentityConfiguration) DeepCopyInto(out *IdentityConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfiguration.
|
||||
func (in *IdentityConfiguration) DeepCopy() *IdentityConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IdentityConfiguration)
|
||||
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
|
||||
@ -354,6 +424,48 @@ func (in *JWTAuthenticator) DeepCopy() *JWTAuthenticator {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KMSConfiguration) DeepCopyInto(out *KMSConfiguration) {
|
||||
*out = *in
|
||||
if in.CacheSize != nil {
|
||||
in, out := &in.CacheSize, &out.CacheSize
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSConfiguration.
|
||||
func (in *KMSConfiguration) DeepCopy() *KMSConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KMSConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Key) DeepCopyInto(out *Key) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Key.
|
||||
func (in *Key) DeepCopy() *Key {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Key)
|
||||
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
|
||||
@ -375,6 +487,96 @@ func (in *PrefixedClaimOrExpression) DeepCopy() *PrefixedClaimOrExpression {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) {
|
||||
*out = *in
|
||||
if in.AESGCM != nil {
|
||||
in, out := &in.AESGCM, &out.AESGCM
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AESCBC != nil {
|
||||
in, out := &in.AESCBC, &out.AESCBC
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Secretbox != nil {
|
||||
in, out := &in.Secretbox, &out.Secretbox
|
||||
*out = new(SecretboxConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Identity != nil {
|
||||
in, out := &in.Identity, &out.Identity
|
||||
*out = new(IdentityConfiguration)
|
||||
**out = **in
|
||||
}
|
||||
if in.KMS != nil {
|
||||
in, out := &in.KMS, &out.KMS
|
||||
*out = new(KMSConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfiguration.
|
||||
func (in *ProviderConfiguration) DeepCopy() *ProviderConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProviderConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceConfiguration) DeepCopyInto(out *ResourceConfiguration) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Providers != nil {
|
||||
in, out := &in.Providers, &out.Providers
|
||||
*out = make([]ProviderConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceConfiguration.
|
||||
func (in *ResourceConfiguration) DeepCopy() *ResourceConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SecretboxConfiguration) DeepCopyInto(out *SecretboxConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretboxConfiguration.
|
||||
func (in *SecretboxConfiguration) DeepCopy() *SecretboxConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SecretboxConfiguration)
|
||||
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
|
||||
|
183
vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.pb.go
generated
vendored
183
vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.pb.go
generated
vendored
@ -15,7 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.proto
|
||||
// source: k8s.io/apiserver/pkg/apis/audit/v1/generated.proto
|
||||
|
||||
package v1
|
||||
|
||||
@ -52,7 +52,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
func (m *Event) Reset() { *m = Event{} }
|
||||
func (*Event) ProtoMessage() {}
|
||||
func (*Event) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{0}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{0}
|
||||
}
|
||||
func (m *Event) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -80,7 +80,7 @@ var xxx_messageInfo_Event proto.InternalMessageInfo
|
||||
func (m *EventList) Reset() { *m = EventList{} }
|
||||
func (*EventList) ProtoMessage() {}
|
||||
func (*EventList) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{1}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{1}
|
||||
}
|
||||
func (m *EventList) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -108,7 +108,7 @@ var xxx_messageInfo_EventList proto.InternalMessageInfo
|
||||
func (m *GroupResources) Reset() { *m = GroupResources{} }
|
||||
func (*GroupResources) ProtoMessage() {}
|
||||
func (*GroupResources) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{2}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{2}
|
||||
}
|
||||
func (m *GroupResources) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -136,7 +136,7 @@ var xxx_messageInfo_GroupResources proto.InternalMessageInfo
|
||||
func (m *ObjectReference) Reset() { *m = ObjectReference{} }
|
||||
func (*ObjectReference) ProtoMessage() {}
|
||||
func (*ObjectReference) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{3}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{3}
|
||||
}
|
||||
func (m *ObjectReference) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -164,7 +164,7 @@ var xxx_messageInfo_ObjectReference proto.InternalMessageInfo
|
||||
func (m *Policy) Reset() { *m = Policy{} }
|
||||
func (*Policy) ProtoMessage() {}
|
||||
func (*Policy) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{4}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{4}
|
||||
}
|
||||
func (m *Policy) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -192,7 +192,7 @@ var xxx_messageInfo_Policy proto.InternalMessageInfo
|
||||
func (m *PolicyList) Reset() { *m = PolicyList{} }
|
||||
func (*PolicyList) ProtoMessage() {}
|
||||
func (*PolicyList) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{5}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{5}
|
||||
}
|
||||
func (m *PolicyList) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -220,7 +220,7 @@ var xxx_messageInfo_PolicyList proto.InternalMessageInfo
|
||||
func (m *PolicyRule) Reset() { *m = PolicyRule{} }
|
||||
func (*PolicyRule) ProtoMessage() {}
|
||||
func (*PolicyRule) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4982ac40a460d730, []int{6}
|
||||
return fileDescriptor_62937bb89ca7b6dd, []int{6}
|
||||
}
|
||||
func (m *PolicyRule) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
@ -257,92 +257,91 @@ func init() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.proto", fileDescriptor_4982ac40a460d730)
|
||||
proto.RegisterFile("k8s.io/apiserver/pkg/apis/audit/v1/generated.proto", fileDescriptor_62937bb89ca7b6dd)
|
||||
}
|
||||
|
||||
var fileDescriptor_4982ac40a460d730 = []byte{
|
||||
// 1288 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0xcf, 0xc6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x99, 0x16, 0xba, 0xe4, 0x60, 0x1b, 0x23, 0xa1,
|
||||
0x00, 0x61, 0xb7, 0x0d, 0x85, 0x56, 0x95, 0x40, 0xb2, 0x69, 0x69, 0x2d, 0x9a, 0x3f, 0x1a, 0xe3,
|
||||
0x1e, 0x10, 0x87, 0xae, 0xd7, 0x2f, 0xf6, 0x62, 0x7b, 0x76, 0xbb, 0x33, 0x6b, 0x94, 0x1b, 0x5f,
|
||||
0x00, 0x89, 0x3b, 0xdf, 0x82, 0x1b, 0xe2, 0xc4, 0x2d, 0xc7, 0x1e, 0x7b, 0xb2, 0x88, 0xe1, 0x53,
|
||||
0xe4, 0x80, 0xd0, 0xcc, 0xce, 0xfe, 0xb1, 0x13, 0x2b, 0x0e, 0x07, 0x6e, 0x9e, 0xf7, 0x7e, 0xbf,
|
||||
0xdf, 0x7b, 0xfb, 0xf6, 0xbd, 0x37, 0x6b, 0xf4, 0xf5, 0xe0, 0x21, 0x33, 0x1c, 0xd7, 0x1c, 0x04,
|
||||
0x1d, 0xf0, 0x29, 0x70, 0x60, 0xe6, 0x18, 0x68, 0xd7, 0xf5, 0x4d, 0xe5, 0xb0, 0x3c, 0x87, 0x81,
|
||||
0x3f, 0x06, 0xdf, 0xf4, 0x06, 0x3d, 0x79, 0x32, 0xad, 0xa0, 0xeb, 0x70, 0x73, 0x7c, 0xcf, 0xec,
|
||||
0x01, 0x05, 0xdf, 0xe2, 0xd0, 0x35, 0x3c, 0xdf, 0xe5, 0x2e, 0xae, 0x85, 0x1c, 0x23, 0xe6, 0x18,
|
||||
0xde, 0xa0, 0x27, 0x4f, 0x86, 0xe4, 0x18, 0xe3, 0x7b, 0xdb, 0x1f, 0xf7, 0x1c, 0xde, 0x0f, 0x3a,
|
||||
0x86, 0xed, 0x8e, 0xcc, 0x9e, 0xdb, 0x73, 0x4d, 0x49, 0xed, 0x04, 0xc7, 0xf2, 0x24, 0x0f, 0xf2,
|
||||
0x57, 0x28, 0xb9, 0xbd, 0x9b, 0xa4, 0x61, 0x5a, 0x01, 0xef, 0x03, 0xe5, 0x8e, 0x6d, 0x71, 0xc7,
|
||||
0xa5, 0x97, 0x24, 0xb0, 0x7d, 0x3f, 0x41, 0x8f, 0x2c, 0xbb, 0xef, 0x50, 0xf0, 0x4f, 0x92, 0xbc,
|
||||
0x47, 0xc0, 0xad, 0xcb, 0x58, 0xe6, 0x22, 0x96, 0x1f, 0x50, 0xee, 0x8c, 0xe0, 0x02, 0xe1, 0xb3,
|
||||
0xab, 0x08, 0xcc, 0xee, 0xc3, 0xc8, 0x9a, 0xe7, 0xd5, 0xfe, 0x46, 0x28, 0xfb, 0x64, 0x0c, 0x94,
|
||||
0xe3, 0x5d, 0x94, 0x1d, 0xc2, 0x18, 0x86, 0xba, 0x56, 0xd5, 0x76, 0xf2, 0x8d, 0xb7, 0x4f, 0x27,
|
||||
0x95, 0x95, 0xe9, 0xa4, 0x92, 0x7d, 0x2e, 0x8c, 0xe7, 0xd1, 0x0f, 0x12, 0x82, 0xf0, 0x01, 0x5a,
|
||||
0x97, 0xf5, 0x6b, 0x3e, 0xd6, 0x57, 0x25, 0xfe, 0xbe, 0xc2, 0xaf, 0xd7, 0x43, 0xf3, 0xf9, 0xa4,
|
||||
0xf2, 0xee, 0xa2, 0x9c, 0xf8, 0x89, 0x07, 0xcc, 0x68, 0x37, 0x1f, 0x93, 0x48, 0x44, 0x44, 0x67,
|
||||
0xdc, 0xea, 0x81, 0x9e, 0x99, 0x8d, 0xde, 0x12, 0xc6, 0xf3, 0xe8, 0x07, 0x09, 0x41, 0x78, 0x0f,
|
||||
0x21, 0x1f, 0x5e, 0x05, 0xc0, 0x78, 0x9b, 0x34, 0xf5, 0x35, 0x49, 0xc1, 0x8a, 0x82, 0x48, 0xec,
|
||||
0x21, 0x29, 0x14, 0xae, 0xa2, 0xb5, 0x31, 0xf8, 0x1d, 0x3d, 0x2b, 0xd1, 0x37, 0x15, 0x7a, 0xed,
|
||||
0x05, 0xf8, 0x1d, 0x22, 0x3d, 0xf8, 0x19, 0x5a, 0x0b, 0x18, 0xf8, 0xfa, 0x8d, 0xaa, 0xb6, 0x53,
|
||||
0xd8, 0x7b, 0xdf, 0x48, 0x5a, 0xc7, 0x98, 0x7d, 0xcf, 0xc6, 0xf8, 0x9e, 0xd1, 0x66, 0xe0, 0x37,
|
||||
0xe9, 0xb1, 0x9b, 0x28, 0x09, 0x0b, 0x91, 0x0a, 0xb8, 0x8f, 0x4a, 0xce, 0xc8, 0x03, 0x9f, 0xb9,
|
||||
0x54, 0xd4, 0x5a, 0x78, 0xf4, 0xf5, 0x6b, 0xa9, 0xde, 0x9e, 0x4e, 0x2a, 0xa5, 0xe6, 0x9c, 0x06,
|
||||
0xb9, 0xa0, 0x8a, 0x3f, 0x42, 0x79, 0xe6, 0x06, 0xbe, 0x0d, 0xcd, 0x23, 0xa6, 0xe7, 0xaa, 0x99,
|
||||
0x9d, 0x7c, 0x63, 0x63, 0x3a, 0xa9, 0xe4, 0x5b, 0x91, 0x91, 0x24, 0x7e, 0x6c, 0xa2, 0xbc, 0x48,
|
||||
0xaf, 0xde, 0x03, 0xca, 0xf5, 0x92, 0xac, 0xc3, 0x96, 0xca, 0x3e, 0xdf, 0x8e, 0x1c, 0x24, 0xc1,
|
||||
0xe0, 0x97, 0x28, 0xef, 0x76, 0xbe, 0x07, 0x9b, 0x13, 0x38, 0xd6, 0xf3, 0xf2, 0x01, 0x3e, 0x31,
|
||||
0xae, 0x9e, 0x28, 0xe3, 0x30, 0x22, 0x81, 0x0f, 0xd4, 0x86, 0x30, 0xa5, 0xd8, 0x48, 0x12, 0x51,
|
||||
0xdc, 0x47, 0x45, 0x1f, 0x98, 0xe7, 0x52, 0x06, 0x2d, 0x6e, 0xf1, 0x80, 0xe9, 0x48, 0x86, 0xd9,
|
||||
0x4d, 0x85, 0x89, 0x9b, 0x27, 0x89, 0x24, 0xe6, 0x46, 0x04, 0x0a, 0x39, 0x0d, 0x3c, 0x9d, 0x54,
|
||||
0x8a, 0x64, 0x46, 0x87, 0xcc, 0xe9, 0x62, 0x0b, 0x6d, 0xa8, 0x6e, 0x08, 0x13, 0xd1, 0x0b, 0x32,
|
||||
0xd0, 0xce, 0xc2, 0x40, 0x6a, 0x72, 0x8c, 0x36, 0x1d, 0x50, 0xf7, 0x07, 0xda, 0xd8, 0x9a, 0x4e,
|
||||
0x2a, 0x1b, 0x24, 0x2d, 0x41, 0x66, 0x15, 0x71, 0x37, 0x79, 0x18, 0x15, 0xe3, 0xe6, 0x35, 0x63,
|
||||
0xcc, 0x3c, 0x88, 0x0a, 0x32, 0xa7, 0x89, 0x7f, 0xd2, 0x90, 0xae, 0xe2, 0x12, 0xb0, 0xc1, 0x19,
|
||||
0x43, 0xf7, 0x1b, 0x67, 0x04, 0x8c, 0x5b, 0x23, 0x4f, 0xdf, 0x90, 0x01, 0xcd, 0xe5, 0xaa, 0xb7,
|
||||
0xef, 0xd8, 0xbe, 0x2b, 0xb8, 0x8d, 0xaa, 0x6a, 0x03, 0x9d, 0x2c, 0x10, 0x26, 0x0b, 0x43, 0x62,
|
||||
0x17, 0x15, 0xe5, 0x54, 0x26, 0x49, 0x14, 0xff, 0x5b, 0x12, 0xd1, 0xd0, 0x17, 0x5b, 0x33, 0x72,
|
||||
0x64, 0x4e, 0x1e, 0xbf, 0x42, 0x05, 0x8b, 0x52, 0x97, 0xcb, 0xa9, 0x61, 0xfa, 0x66, 0x35, 0xb3,
|
||||
0x53, 0xd8, 0x7b, 0xb4, 0x4c, 0x5f, 0xca, 0x4d, 0x67, 0xd4, 0x13, 0xf2, 0x13, 0xca, 0xfd, 0x93,
|
||||
0xc6, 0x2d, 0x15, 0xb8, 0x90, 0xf2, 0x90, 0x74, 0x8c, 0xed, 0x2f, 0x50, 0x69, 0x9e, 0x85, 0x4b,
|
||||
0x28, 0x33, 0x80, 0x93, 0x70, 0x5d, 0x12, 0xf1, 0x13, 0xdf, 0x46, 0xd9, 0xb1, 0x35, 0x0c, 0x20,
|
||||
0x5c, 0x89, 0x24, 0x3c, 0x3c, 0x5a, 0x7d, 0xa8, 0xd5, 0x7e, 0xd3, 0x50, 0x5e, 0x06, 0x7f, 0xee,
|
||||
0x30, 0x8e, 0xbf, 0x43, 0x39, 0xf1, 0xf4, 0x5d, 0x8b, 0x5b, 0x92, 0x5e, 0xd8, 0x33, 0x96, 0xab,
|
||||
0x95, 0x60, 0xef, 0x03, 0xb7, 0x1a, 0x25, 0x95, 0x71, 0x2e, 0xb2, 0x90, 0x58, 0x11, 0x1f, 0xa0,
|
||||
0xac, 0xc3, 0x61, 0xc4, 0xf4, 0x55, 0x59, 0x98, 0x0f, 0x96, 0x2e, 0x4c, 0x63, 0x23, 0xda, 0xba,
|
||||
0x4d, 0xc1, 0x27, 0xa1, 0x4c, 0xed, 0x17, 0x0d, 0x15, 0x9f, 0xfa, 0x6e, 0xe0, 0x11, 0x08, 0x57,
|
||||
0x09, 0xc3, 0xef, 0xa1, 0x6c, 0x4f, 0x58, 0xd4, 0x5d, 0x11, 0xf3, 0x42, 0x58, 0xe8, 0x13, 0xab,
|
||||
0xc9, 0x8f, 0x18, 0x32, 0x17, 0xb5, 0x9a, 0x62, 0x19, 0x92, 0xf8, 0xf1, 0x03, 0x31, 0x9d, 0xe1,
|
||||
0xe1, 0xc0, 0x1a, 0x01, 0xd3, 0x33, 0x92, 0xa0, 0x66, 0x2e, 0xe5, 0x20, 0xb3, 0xb8, 0xda, 0xaf,
|
||||
0x19, 0xb4, 0x39, 0xb7, 0x6e, 0xf0, 0x2e, 0xca, 0x45, 0x20, 0x95, 0x61, 0x5c, 0xaf, 0x48, 0x8b,
|
||||
0xc4, 0x08, 0xb1, 0x15, 0xa9, 0x90, 0xf2, 0x2c, 0x5b, 0xbd, 0xb9, 0x64, 0x2b, 0x1e, 0x44, 0x0e,
|
||||
0x92, 0x60, 0xc4, 0x4d, 0x22, 0x0e, 0xea, 0xaa, 0x8a, 0xf7, 0xbf, 0xc0, 0x12, 0xe9, 0xc1, 0x0d,
|
||||
0x94, 0x09, 0x9c, 0xae, 0xba, 0x98, 0xee, 0x2a, 0x40, 0xa6, 0xbd, 0xec, 0xad, 0x28, 0xc8, 0xe2,
|
||||
0x21, 0x2c, 0xcf, 0x91, 0x15, 0x55, 0x77, 0x56, 0xfc, 0x10, 0xf5, 0xa3, 0x66, 0x58, 0xe9, 0x18,
|
||||
0x21, 0x6e, 0x44, 0xcb, 0x73, 0x5e, 0x80, 0xcf, 0x1c, 0x97, 0xca, 0x1b, 0x2c, 0x75, 0x23, 0xd6,
|
||||
0x8f, 0x9a, 0xca, 0x43, 0x52, 0x28, 0x5c, 0x47, 0x9b, 0x51, 0x11, 0x22, 0xe2, 0xba, 0x24, 0xde,
|
||||
0x51, 0xc4, 0x4d, 0x32, 0xeb, 0x26, 0xf3, 0x78, 0xfc, 0x29, 0x2a, 0xb0, 0xa0, 0x13, 0x17, 0x3b,
|
||||
0x27, 0xe9, 0xf1, 0x38, 0xb5, 0x12, 0x17, 0x49, 0xe3, 0x6a, 0x7f, 0xac, 0xa2, 0x1b, 0x47, 0xee,
|
||||
0xd0, 0xb1, 0x4f, 0xf0, 0xcb, 0x0b, 0xb3, 0x70, 0x77, 0xb9, 0x59, 0x08, 0x5f, 0xba, 0x9c, 0x86,
|
||||
0xf8, 0x41, 0x13, 0x5b, 0x6a, 0x1e, 0x5a, 0x28, 0xeb, 0x07, 0x43, 0x88, 0xe6, 0xc1, 0x58, 0x66,
|
||||
0x1e, 0xc2, 0xe4, 0x48, 0x30, 0x84, 0xa4, 0xb9, 0xc5, 0x89, 0x91, 0x50, 0x0b, 0x3f, 0x40, 0xc8,
|
||||
0x1d, 0x39, 0x5c, 0x6e, 0xaa, 0xa8, 0x59, 0xef, 0xc8, 0x14, 0x62, 0x6b, 0xf2, 0xd5, 0x92, 0x82,
|
||||
0xe2, 0xa7, 0x68, 0x4b, 0x9c, 0xf6, 0x2d, 0x6a, 0xf5, 0xa0, 0xfb, 0x95, 0x03, 0xc3, 0x2e, 0x93,
|
||||
0x8d, 0x92, 0x6b, 0xbc, 0xa3, 0x22, 0x6d, 0x1d, 0xce, 0x03, 0xc8, 0x45, 0x4e, 0xed, 0x77, 0x0d,
|
||||
0xa1, 0x30, 0xcd, 0xff, 0x61, 0xa7, 0x1c, 0xce, 0xee, 0x94, 0x0f, 0x97, 0xaf, 0xe1, 0x82, 0xa5,
|
||||
0xf2, 0x4f, 0x26, 0xca, 0x5e, 0x94, 0xf5, 0x9a, 0x1f, 0x9f, 0x15, 0x94, 0x15, 0xdf, 0x28, 0xd1,
|
||||
0x56, 0xc9, 0x0b, 0xa4, 0xf8, 0x7e, 0x61, 0x24, 0xb4, 0x63, 0x03, 0x21, 0xf1, 0x43, 0x8e, 0x46,
|
||||
0xf4, 0x76, 0x8a, 0xe2, 0xed, 0xb4, 0x63, 0x2b, 0x49, 0x21, 0x84, 0xa0, 0xf8, 0x02, 0x14, 0x2f,
|
||||
0x22, 0x16, 0x14, 0x1f, 0x86, 0x8c, 0x84, 0x76, 0x6c, 0xa7, 0x77, 0x59, 0x56, 0xd6, 0x60, 0x6f,
|
||||
0x99, 0x1a, 0xcc, 0xee, 0xcd, 0x64, 0xaf, 0x5c, 0xba, 0x03, 0x0d, 0x84, 0xe2, 0x25, 0xc3, 0xf4,
|
||||
0x1b, 0x49, 0xd6, 0xf1, 0x16, 0x62, 0x24, 0x85, 0xc0, 0x9f, 0xa3, 0x4d, 0xea, 0xd2, 0x48, 0xaa,
|
||||
0x4d, 0x9e, 0x33, 0x7d, 0x5d, 0x92, 0x6e, 0x89, 0xd9, 0x3d, 0x98, 0x75, 0x91, 0x79, 0xec, 0x5c,
|
||||
0x0b, 0xe7, 0x96, 0x6f, 0xe1, 0x2f, 0x2f, 0x6b, 0xe1, 0xbc, 0x6c, 0xe1, 0xb7, 0x96, 0x6d, 0xdf,
|
||||
0xc6, 0xb3, 0xd3, 0xb3, 0xf2, 0xca, 0xeb, 0xb3, 0xf2, 0xca, 0x9b, 0xb3, 0xf2, 0xca, 0x8f, 0xd3,
|
||||
0xb2, 0x76, 0x3a, 0x2d, 0x6b, 0xaf, 0xa7, 0x65, 0xed, 0xcd, 0xb4, 0xac, 0xfd, 0x39, 0x2d, 0x6b,
|
||||
0x3f, 0xff, 0x55, 0x5e, 0xf9, 0xb6, 0x76, 0xf5, 0x5f, 0xbe, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff,
|
||||
0xef, 0x9b, 0x7d, 0x75, 0x30, 0x0e, 0x00, 0x00,
|
||||
var fileDescriptor_62937bb89ca7b6dd = []byte{
|
||||
// 1275 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xcf, 0x6f, 0x1b, 0xd5,
|
||||
0x13, 0xcf, 0xc6, 0x71, 0x63, 0x8f, 0x1b, 0xc7, 0x79, 0xed, 0xf7, 0xdb, 0x25, 0x07, 0xdb, 0x18,
|
||||
0x09, 0x05, 0x08, 0xeb, 0xd6, 0x14, 0x5a, 0x55, 0x02, 0xc9, 0xa6, 0xa5, 0xb5, 0xd4, 0xa6, 0xd1,
|
||||
0x33, 0xee, 0x01, 0x71, 0xe8, 0x7a, 0x3d, 0xb5, 0x97, 0xd8, 0xbb, 0xdb, 0x7d, 0x6f, 0x8d, 0x72,
|
||||
0xe3, 0x1f, 0x40, 0xe2, 0xce, 0x7f, 0xc1, 0x0d, 0x71, 0xe2, 0x96, 0x63, 0x8f, 0x3d, 0x59, 0xc4,
|
||||
0xf0, 0x57, 0xe4, 0x80, 0xd0, 0x7b, 0xfb, 0xf6, 0x87, 0x9d, 0x58, 0x71, 0x38, 0x70, 0xf3, 0x9b,
|
||||
0xf9, 0x7c, 0x3e, 0x33, 0x3b, 0x3b, 0x33, 0x6f, 0x0d, 0x8d, 0xa3, 0xfb, 0xcc, 0xb0, 0xdd, 0xba,
|
||||
0xe9, 0xd9, 0x0c, 0xfd, 0x09, 0xfa, 0x75, 0xef, 0x68, 0x20, 0x4f, 0x75, 0x33, 0xe8, 0xdb, 0xbc,
|
||||
0x3e, 0xb9, 0x53, 0x1f, 0xa0, 0x83, 0xbe, 0xc9, 0xb1, 0x6f, 0x78, 0xbe, 0xcb, 0x5d, 0x52, 0x0b,
|
||||
0x39, 0x46, 0xcc, 0x31, 0xbc, 0xa3, 0x81, 0x3c, 0x19, 0x92, 0x63, 0x4c, 0xee, 0xec, 0x7e, 0x3c,
|
||||
0xb0, 0xf9, 0x30, 0xe8, 0x19, 0x96, 0x3b, 0xae, 0x0f, 0xdc, 0x81, 0x5b, 0x97, 0xd4, 0x5e, 0xf0,
|
||||
0x4a, 0x9e, 0xe4, 0x41, 0xfe, 0x0a, 0x25, 0x77, 0xf7, 0x93, 0x34, 0xea, 0x66, 0xc0, 0x87, 0xe8,
|
||||
0x70, 0xdb, 0x32, 0xb9, 0xed, 0x3a, 0x17, 0x24, 0xb0, 0x7b, 0x37, 0x41, 0x8f, 0x4d, 0x6b, 0x68,
|
||||
0x3b, 0xe8, 0x1f, 0x27, 0x79, 0x8f, 0x91, 0x9b, 0x17, 0xb1, 0xea, 0xcb, 0x58, 0x7e, 0xe0, 0x70,
|
||||
0x7b, 0x8c, 0xe7, 0x08, 0x9f, 0x5d, 0x46, 0x60, 0xd6, 0x10, 0xc7, 0xe6, 0x22, 0xaf, 0xf6, 0x17,
|
||||
0x40, 0xf6, 0xd1, 0x04, 0x1d, 0x4e, 0xf6, 0x21, 0x3b, 0xc2, 0x09, 0x8e, 0x74, 0xad, 0xaa, 0xed,
|
||||
0xe5, 0x5b, 0xff, 0x3f, 0x99, 0x56, 0xd6, 0x66, 0xd3, 0x4a, 0xf6, 0xa9, 0x30, 0x9e, 0x45, 0x3f,
|
||||
0x68, 0x08, 0x22, 0x07, 0xb0, 0x29, 0xeb, 0xd7, 0x7e, 0xa8, 0xaf, 0x4b, 0xfc, 0x5d, 0x85, 0xdf,
|
||||
0x6c, 0x86, 0xe6, 0xb3, 0x69, 0xe5, 0xdd, 0x65, 0x39, 0xf1, 0x63, 0x0f, 0x99, 0xd1, 0x6d, 0x3f,
|
||||
0xa4, 0x91, 0x88, 0x88, 0xce, 0xb8, 0x39, 0x40, 0x3d, 0x33, 0x1f, 0xbd, 0x23, 0x8c, 0x67, 0xd1,
|
||||
0x0f, 0x1a, 0x82, 0x48, 0x03, 0xc0, 0xc7, 0xd7, 0x01, 0x32, 0xde, 0xa5, 0x6d, 0x7d, 0x43, 0x52,
|
||||
0x88, 0xa2, 0x00, 0x8d, 0x3d, 0x34, 0x85, 0x22, 0x55, 0xd8, 0x98, 0xa0, 0xdf, 0xd3, 0xb3, 0x12,
|
||||
0x7d, 0x5d, 0xa1, 0x37, 0x5e, 0xa0, 0xdf, 0xa3, 0xd2, 0x43, 0x9e, 0xc0, 0x46, 0xc0, 0xd0, 0xd7,
|
||||
0xaf, 0x55, 0xb5, 0xbd, 0x42, 0xe3, 0x7d, 0x23, 0x69, 0x1d, 0x63, 0xfe, 0x3d, 0x1b, 0x93, 0x3b,
|
||||
0x46, 0x97, 0xa1, 0xdf, 0x76, 0x5e, 0xb9, 0x89, 0x92, 0xb0, 0x50, 0xa9, 0x40, 0x86, 0x50, 0xb2,
|
||||
0xc7, 0x1e, 0xfa, 0xcc, 0x75, 0x44, 0xad, 0x85, 0x47, 0xdf, 0xbc, 0x92, 0xea, 0xcd, 0xd9, 0xb4,
|
||||
0x52, 0x6a, 0x2f, 0x68, 0xd0, 0x73, 0xaa, 0xe4, 0x23, 0xc8, 0x33, 0x37, 0xf0, 0x2d, 0x6c, 0x1f,
|
||||
0x32, 0x3d, 0x57, 0xcd, 0xec, 0xe5, 0x5b, 0x5b, 0xb3, 0x69, 0x25, 0xdf, 0x89, 0x8c, 0x34, 0xf1,
|
||||
0x93, 0x3a, 0xe4, 0x45, 0x7a, 0xcd, 0x01, 0x3a, 0x5c, 0x2f, 0xc9, 0x3a, 0xec, 0xa8, 0xec, 0xf3,
|
||||
0xdd, 0xc8, 0x41, 0x13, 0x0c, 0x79, 0x09, 0x79, 0xb7, 0xf7, 0x1d, 0x5a, 0x9c, 0xe2, 0x2b, 0x3d,
|
||||
0x2f, 0x1f, 0xe0, 0x13, 0xe3, 0xf2, 0x89, 0x32, 0x9e, 0x47, 0x24, 0xf4, 0xd1, 0xb1, 0x30, 0x4c,
|
||||
0x29, 0x36, 0xd2, 0x44, 0x94, 0x0c, 0xa1, 0xe8, 0x23, 0xf3, 0x5c, 0x87, 0x61, 0x87, 0x9b, 0x3c,
|
||||
0x60, 0x3a, 0xc8, 0x30, 0xfb, 0xa9, 0x30, 0x71, 0xf3, 0x24, 0x91, 0xc4, 0xdc, 0x88, 0x40, 0x21,
|
||||
0xa7, 0x45, 0x66, 0xd3, 0x4a, 0x91, 0xce, 0xe9, 0xd0, 0x05, 0x5d, 0x62, 0xc2, 0x96, 0xea, 0x86,
|
||||
0x30, 0x11, 0xbd, 0x20, 0x03, 0xed, 0x2d, 0x0d, 0xa4, 0x26, 0xc7, 0xe8, 0x3a, 0x47, 0x8e, 0xfb,
|
||||
0xbd, 0xd3, 0xda, 0x99, 0x4d, 0x2b, 0x5b, 0x34, 0x2d, 0x41, 0xe7, 0x15, 0x49, 0x3f, 0x79, 0x18,
|
||||
0x15, 0xe3, 0xfa, 0x15, 0x63, 0xcc, 0x3d, 0x88, 0x0a, 0xb2, 0xa0, 0x49, 0x7e, 0xd4, 0x40, 0x57,
|
||||
0x71, 0x29, 0x5a, 0x68, 0x4f, 0xb0, 0xff, 0xb5, 0x3d, 0x46, 0xc6, 0xcd, 0xb1, 0xa7, 0x6f, 0xc9,
|
||||
0x80, 0xf5, 0xd5, 0xaa, 0xf7, 0xcc, 0xb6, 0x7c, 0x57, 0x70, 0x5b, 0x55, 0xd5, 0x06, 0x3a, 0x5d,
|
||||
0x22, 0x4c, 0x97, 0x86, 0x24, 0x2e, 0x14, 0xe5, 0x54, 0x26, 0x49, 0x14, 0xff, 0x5d, 0x12, 0xd1,
|
||||
0xd0, 0x17, 0x3b, 0x73, 0x72, 0x74, 0x41, 0x9e, 0xbc, 0x86, 0x82, 0xe9, 0x38, 0x2e, 0x97, 0x53,
|
||||
0xc3, 0xf4, 0xed, 0x6a, 0x66, 0xaf, 0xd0, 0x78, 0xb0, 0x4a, 0x5f, 0xca, 0x4d, 0x67, 0x34, 0x13,
|
||||
0xf2, 0x23, 0x87, 0xfb, 0xc7, 0xad, 0x1b, 0x2a, 0x70, 0x21, 0xe5, 0xa1, 0xe9, 0x18, 0xbb, 0x5f,
|
||||
0x40, 0x69, 0x91, 0x45, 0x4a, 0x90, 0x39, 0xc2, 0xe3, 0x70, 0x5d, 0x52, 0xf1, 0x93, 0xdc, 0x84,
|
||||
0xec, 0xc4, 0x1c, 0x05, 0x18, 0xae, 0x44, 0x1a, 0x1e, 0x1e, 0xac, 0xdf, 0xd7, 0x6a, 0xbf, 0x6a,
|
||||
0x90, 0x97, 0xc1, 0x9f, 0xda, 0x8c, 0x93, 0x6f, 0x21, 0x27, 0x9e, 0xbe, 0x6f, 0x72, 0x53, 0xd2,
|
||||
0x0b, 0x0d, 0x63, 0xb5, 0x5a, 0x09, 0xf6, 0x33, 0xe4, 0x66, 0xab, 0xa4, 0x32, 0xce, 0x45, 0x16,
|
||||
0x1a, 0x2b, 0x92, 0x03, 0xc8, 0xda, 0x1c, 0xc7, 0x4c, 0x5f, 0x97, 0x85, 0xf9, 0x60, 0xe5, 0xc2,
|
||||
0xb4, 0xb6, 0xa2, 0xad, 0xdb, 0x16, 0x7c, 0x1a, 0xca, 0xd4, 0x7e, 0xd6, 0xa0, 0xf8, 0xd8, 0x77,
|
||||
0x03, 0x8f, 0x62, 0xb8, 0x4a, 0x18, 0x79, 0x0f, 0xb2, 0x03, 0x61, 0x51, 0x77, 0x45, 0xcc, 0x0b,
|
||||
0x61, 0xa1, 0x4f, 0xac, 0x26, 0x3f, 0x62, 0xc8, 0x5c, 0xd4, 0x6a, 0x8a, 0x65, 0x68, 0xe2, 0x27,
|
||||
0xf7, 0xc4, 0x74, 0x86, 0x87, 0x03, 0x73, 0x8c, 0x4c, 0xcf, 0x48, 0x82, 0x9a, 0xb9, 0x94, 0x83,
|
||||
0xce, 0xe3, 0x6a, 0xbf, 0x64, 0x60, 0x7b, 0x61, 0xdd, 0x90, 0x7d, 0xc8, 0x45, 0x20, 0x95, 0x61,
|
||||
0x5c, 0xaf, 0x48, 0x8b, 0xc6, 0x08, 0xb1, 0x15, 0x1d, 0x21, 0xe5, 0x99, 0x96, 0x7a, 0x73, 0xc9,
|
||||
0x56, 0x3c, 0x88, 0x1c, 0x34, 0xc1, 0x88, 0x9b, 0x44, 0x1c, 0xd4, 0x55, 0x15, 0xef, 0x7f, 0x81,
|
||||
0xa5, 0xd2, 0x43, 0x5a, 0x90, 0x09, 0xec, 0xbe, 0xba, 0x98, 0x6e, 0x2b, 0x40, 0xa6, 0xbb, 0xea,
|
||||
0xad, 0x28, 0xc8, 0xe2, 0x21, 0x4c, 0xcf, 0x96, 0x15, 0x55, 0x77, 0x56, 0xfc, 0x10, 0xcd, 0xc3,
|
||||
0x76, 0x58, 0xe9, 0x18, 0x21, 0x6e, 0x44, 0xd3, 0xb3, 0x5f, 0xa0, 0xcf, 0x6c, 0xd7, 0x91, 0x37,
|
||||
0x58, 0xea, 0x46, 0x6c, 0x1e, 0xb6, 0x95, 0x87, 0xa6, 0x50, 0xa4, 0x09, 0xdb, 0x51, 0x11, 0x22,
|
||||
0xe2, 0xa6, 0x24, 0xde, 0x52, 0xc4, 0x6d, 0x3a, 0xef, 0xa6, 0x8b, 0x78, 0xf2, 0x29, 0x14, 0x58,
|
||||
0xd0, 0x8b, 0x8b, 0x9d, 0x93, 0xf4, 0x78, 0x9c, 0x3a, 0x89, 0x8b, 0xa6, 0x71, 0xb5, 0xdf, 0xd7,
|
||||
0xe1, 0xda, 0xa1, 0x3b, 0xb2, 0xad, 0x63, 0xf2, 0xf2, 0xdc, 0x2c, 0xdc, 0x5e, 0x6d, 0x16, 0xc2,
|
||||
0x97, 0x2e, 0xa7, 0x21, 0x7e, 0xd0, 0xc4, 0x96, 0x9a, 0x87, 0x0e, 0x64, 0xfd, 0x60, 0x84, 0xd1,
|
||||
0x3c, 0x18, 0xab, 0xcc, 0x43, 0x98, 0x1c, 0x0d, 0x46, 0x98, 0x34, 0xb7, 0x38, 0x31, 0x1a, 0x6a,
|
||||
0x91, 0x7b, 0x00, 0xee, 0xd8, 0xe6, 0x72, 0x53, 0x45, 0xcd, 0x7a, 0x4b, 0xa6, 0x10, 0x5b, 0x93,
|
||||
0xaf, 0x96, 0x14, 0x94, 0x3c, 0x86, 0x1d, 0x71, 0x7a, 0x66, 0x3a, 0xe6, 0x00, 0xfb, 0x5f, 0xd9,
|
||||
0x38, 0xea, 0x33, 0xd9, 0x28, 0xb9, 0xd6, 0x3b, 0x2a, 0xd2, 0xce, 0xf3, 0x45, 0x00, 0x3d, 0xcf,
|
||||
0xa9, 0xfd, 0xa6, 0x01, 0x84, 0x69, 0xfe, 0x07, 0x3b, 0xe5, 0xf9, 0xfc, 0x4e, 0xf9, 0x70, 0xf5,
|
||||
0x1a, 0x2e, 0x59, 0x2a, 0x7f, 0x67, 0xa2, 0xec, 0x45, 0x59, 0xaf, 0xf8, 0xf1, 0x59, 0x81, 0xac,
|
||||
0xf8, 0x46, 0x89, 0xb6, 0x4a, 0x5e, 0x20, 0xc5, 0xf7, 0x0b, 0xa3, 0xa1, 0x9d, 0x18, 0x00, 0xe2,
|
||||
0x87, 0x1c, 0x8d, 0xe8, 0xed, 0x14, 0xc5, 0xdb, 0xe9, 0xc6, 0x56, 0x9a, 0x42, 0x08, 0x41, 0xf1,
|
||||
0x05, 0x28, 0x5e, 0x44, 0x2c, 0x28, 0x3e, 0x0c, 0x19, 0x0d, 0xed, 0xc4, 0x4a, 0xef, 0xb2, 0xac,
|
||||
0xac, 0x41, 0x63, 0x95, 0x1a, 0xcc, 0xef, 0xcd, 0x64, 0xaf, 0x5c, 0xb8, 0x03, 0x0d, 0x80, 0x78,
|
||||
0xc9, 0x30, 0xfd, 0x5a, 0x92, 0x75, 0xbc, 0x85, 0x18, 0x4d, 0x21, 0xc8, 0xe7, 0xb0, 0xed, 0xb8,
|
||||
0x4e, 0x24, 0xd5, 0xa5, 0x4f, 0x99, 0xbe, 0x29, 0x49, 0x37, 0xc4, 0xec, 0x1e, 0xcc, 0xbb, 0xe8,
|
||||
0x22, 0x76, 0xa1, 0x85, 0x73, 0xab, 0xb7, 0xf0, 0x97, 0x17, 0xb5, 0x70, 0x5e, 0xb6, 0xf0, 0xff,
|
||||
0x56, 0x6d, 0xdf, 0xd6, 0x93, 0x93, 0xd3, 0xf2, 0xda, 0x9b, 0xd3, 0xf2, 0xda, 0xdb, 0xd3, 0xf2,
|
||||
0xda, 0x0f, 0xb3, 0xb2, 0x76, 0x32, 0x2b, 0x6b, 0x6f, 0x66, 0x65, 0xed, 0xed, 0xac, 0xac, 0xfd,
|
||||
0x31, 0x2b, 0x6b, 0x3f, 0xfd, 0x59, 0x5e, 0xfb, 0xa6, 0x76, 0xf9, 0x5f, 0xbe, 0x7f, 0x02, 0x00,
|
||||
0x00, 0xff, 0xff, 0x81, 0x06, 0x4f, 0x58, 0x17, 0x0e, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Event) Marshal() (dAtA []byte, err error) {
|
||||
|
12
vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.proto
generated
vendored
12
vendor/k8s.io/apiserver/pkg/apis/audit/v1/generated.proto
generated
vendored
@ -62,6 +62,7 @@ message Event {
|
||||
// IP in the list up to here (X-Forwarded-For or X-Real-Ip).
|
||||
// Note: All but the last IP can be arbitrarily set by the client.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string sourceIPs = 8;
|
||||
|
||||
// UserAgent records the user agent string reported by the client.
|
||||
@ -140,12 +141,14 @@ message GroupResources {
|
||||
//
|
||||
// An empty list implies all resources and subresources in this API groups apply.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string resources = 2;
|
||||
|
||||
// ResourceNames is a list of resource instance names that the policy matches.
|
||||
// Using this field requires Resources to be specified.
|
||||
// An empty list implies that every instance of the resource is matched.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string resourceNames = 3;
|
||||
}
|
||||
|
||||
@ -190,11 +193,13 @@ message Policy {
|
||||
// A request may match multiple rules, in which case the FIRST matching rule is used.
|
||||
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
|
||||
// PolicyRules are strictly ordered.
|
||||
// +listType=atomic
|
||||
repeated PolicyRule rules = 2;
|
||||
|
||||
// OmitStages is a list of stages for which no events are created. Note that this can also
|
||||
// be specified per rule in which case the union of both are omitted.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string omitStages = 3;
|
||||
|
||||
// OmitManagedFields indicates whether to omit the managed fields of the request
|
||||
@ -224,27 +229,32 @@ message PolicyRule {
|
||||
// The users (by authenticated user name) this rule applies to.
|
||||
// An empty list implies every user.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string users = 2;
|
||||
|
||||
// The user groups this rule applies to. A user is considered matching
|
||||
// if it is a member of any of the UserGroups.
|
||||
// An empty list implies every user group.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string userGroups = 3;
|
||||
|
||||
// The verbs that match this rule.
|
||||
// An empty list implies every verb.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string verbs = 4;
|
||||
|
||||
// Resources that this rule matches. An empty list implies all kinds in all API groups.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated GroupResources resources = 5;
|
||||
|
||||
// Namespaces that this rule matches.
|
||||
// The empty string "" matches non-namespaced resources.
|
||||
// An empty list implies every namespace.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string namespaces = 6;
|
||||
|
||||
// NonResourceURLs is a set of URL paths that should be audited.
|
||||
@ -253,12 +263,14 @@ message PolicyRule {
|
||||
// - `/metrics` - Log requests for apiserver metrics
|
||||
// - `/healthz*` - Log all health checks
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string nonResourceURLs = 7;
|
||||
|
||||
// OmitStages is a list of stages for which no events are created. Note that this can also
|
||||
// be specified policy wide in which case the union of both are omitted.
|
||||
// An empty list means no restrictions will apply.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
repeated string omitStages = 8;
|
||||
|
||||
// OmitManagedFields indicates whether to omit the managed fields of the request
|
||||
|
12
vendor/k8s.io/apiserver/pkg/apis/audit/v1/types.go
generated
vendored
12
vendor/k8s.io/apiserver/pkg/apis/audit/v1/types.go
generated
vendored
@ -98,6 +98,7 @@ type Event struct {
|
||||
// IP in the list up to here (X-Forwarded-For or X-Real-Ip).
|
||||
// Note: All but the last IP can be arbitrarily set by the client.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
SourceIPs []string `json:"sourceIPs,omitempty" protobuf:"bytes,8,rep,name=sourceIPs"`
|
||||
// UserAgent records the user agent string reported by the client.
|
||||
// Note that the UserAgent is provided by the client, and must not be trusted.
|
||||
@ -166,11 +167,13 @@ type Policy struct {
|
||||
// A request may match multiple rules, in which case the FIRST matching rule is used.
|
||||
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
|
||||
// PolicyRules are strictly ordered.
|
||||
// +listType=atomic
|
||||
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
|
||||
|
||||
// OmitStages is a list of stages for which no events are created. Note that this can also
|
||||
// be specified per rule in which case the union of both are omitted.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,3,rep,name=omitStages"`
|
||||
|
||||
// OmitManagedFields indicates whether to omit the managed fields of the request
|
||||
@ -203,16 +206,19 @@ type PolicyRule struct {
|
||||
// The users (by authenticated user name) this rule applies to.
|
||||
// An empty list implies every user.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Users []string `json:"users,omitempty" protobuf:"bytes,2,rep,name=users"`
|
||||
// The user groups this rule applies to. A user is considered matching
|
||||
// if it is a member of any of the UserGroups.
|
||||
// An empty list implies every user group.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
UserGroups []string `json:"userGroups,omitempty" protobuf:"bytes,3,rep,name=userGroups"`
|
||||
|
||||
// The verbs that match this rule.
|
||||
// An empty list implies every verb.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Verbs []string `json:"verbs,omitempty" protobuf:"bytes,4,rep,name=verbs"`
|
||||
|
||||
// Rules can apply to API resources (such as "pods" or "secrets"),
|
||||
@ -221,11 +227,13 @@ type PolicyRule struct {
|
||||
|
||||
// Resources that this rule matches. An empty list implies all kinds in all API groups.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Resources []GroupResources `json:"resources,omitempty" protobuf:"bytes,5,rep,name=resources"`
|
||||
// Namespaces that this rule matches.
|
||||
// The empty string "" matches non-namespaced resources.
|
||||
// An empty list implies every namespace.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Namespaces []string `json:"namespaces,omitempty" protobuf:"bytes,6,rep,name=namespaces"`
|
||||
|
||||
// NonResourceURLs is a set of URL paths that should be audited.
|
||||
@ -234,12 +242,14 @@ type PolicyRule struct {
|
||||
// - `/metrics` - Log requests for apiserver metrics
|
||||
// - `/healthz*` - Log all health checks
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"`
|
||||
|
||||
// OmitStages is a list of stages for which no events are created. Note that this can also
|
||||
// be specified policy wide in which case the union of both are omitted.
|
||||
// An empty list means no restrictions will apply.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"`
|
||||
|
||||
// OmitManagedFields indicates whether to omit the managed fields of the request
|
||||
@ -274,11 +284,13 @@ type GroupResources struct {
|
||||
//
|
||||
// An empty list implies all resources and subresources in this API groups apply.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Resources []string `json:"resources,omitempty" protobuf:"bytes,2,rep,name=resources"`
|
||||
// ResourceNames is a list of resource instance names that the policy matches.
|
||||
// Using this field requires Resources to be specified.
|
||||
// An empty list implies that every instance of the resource is matched.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
ResourceNames []string `json:"resourceNames,omitempty" protobuf:"bytes,3,rep,name=resourceNames"`
|
||||
}
|
||||
|
||||
|
53
vendor/k8s.io/apiserver/pkg/apis/config/v1/register.go
generated
vendored
53
vendor/k8s.io/apiserver/pkg/apis/config/v1/register.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package.
|
||||
const GroupName = "apiserver.config.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects.
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme adds this group to a scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
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(addDefaultingFuncs)
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&EncryptionConfiguration{},
|
||||
)
|
||||
// also register into the v1 group as EncryptionConfig (due to a docs bug)
|
||||
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "EncryptionConfig"}, &EncryptionConfiguration{})
|
||||
return nil
|
||||
}
|
299
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.conversion.go
generated
vendored
299
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.conversion.go
generated
vendored
@ -1,299 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
config "k8s.io/apiserver/pkg/apis/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*AESConfiguration)(nil), (*config.AESConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_AESConfiguration_To_config_AESConfiguration(a.(*AESConfiguration), b.(*config.AESConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.AESConfiguration)(nil), (*AESConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_AESConfiguration_To_v1_AESConfiguration(a.(*config.AESConfiguration), b.(*AESConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*EncryptionConfiguration)(nil), (*config.EncryptionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_EncryptionConfiguration_To_config_EncryptionConfiguration(a.(*EncryptionConfiguration), b.(*config.EncryptionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.EncryptionConfiguration)(nil), (*EncryptionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_EncryptionConfiguration_To_v1_EncryptionConfiguration(a.(*config.EncryptionConfiguration), b.(*EncryptionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*IdentityConfiguration)(nil), (*config.IdentityConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_IdentityConfiguration_To_config_IdentityConfiguration(a.(*IdentityConfiguration), b.(*config.IdentityConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.IdentityConfiguration)(nil), (*IdentityConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_IdentityConfiguration_To_v1_IdentityConfiguration(a.(*config.IdentityConfiguration), b.(*IdentityConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*KMSConfiguration)(nil), (*config.KMSConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_KMSConfiguration_To_config_KMSConfiguration(a.(*KMSConfiguration), b.(*config.KMSConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.KMSConfiguration)(nil), (*KMSConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_KMSConfiguration_To_v1_KMSConfiguration(a.(*config.KMSConfiguration), b.(*KMSConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Key)(nil), (*config.Key)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_Key_To_config_Key(a.(*Key), b.(*config.Key), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.Key)(nil), (*Key)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_Key_To_v1_Key(a.(*config.Key), b.(*Key), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ProviderConfiguration)(nil), (*config.ProviderConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ProviderConfiguration_To_config_ProviderConfiguration(a.(*ProviderConfiguration), b.(*config.ProviderConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ProviderConfiguration)(nil), (*ProviderConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ProviderConfiguration_To_v1_ProviderConfiguration(a.(*config.ProviderConfiguration), b.(*ProviderConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ResourceConfiguration)(nil), (*config.ResourceConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_ResourceConfiguration_To_config_ResourceConfiguration(a.(*ResourceConfiguration), b.(*config.ResourceConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.ResourceConfiguration)(nil), (*ResourceConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ResourceConfiguration_To_v1_ResourceConfiguration(a.(*config.ResourceConfiguration), b.(*ResourceConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*SecretboxConfiguration)(nil), (*config.SecretboxConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_SecretboxConfiguration_To_config_SecretboxConfiguration(a.(*SecretboxConfiguration), b.(*config.SecretboxConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*config.SecretboxConfiguration)(nil), (*SecretboxConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_SecretboxConfiguration_To_v1_SecretboxConfiguration(a.(*config.SecretboxConfiguration), b.(*SecretboxConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_AESConfiguration_To_config_AESConfiguration(in *AESConfiguration, out *config.AESConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]config.Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_AESConfiguration_To_config_AESConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_AESConfiguration_To_config_AESConfiguration(in *AESConfiguration, out *config.AESConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_AESConfiguration_To_config_AESConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_AESConfiguration_To_v1_AESConfiguration(in *config.AESConfiguration, out *AESConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_AESConfiguration_To_v1_AESConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_AESConfiguration_To_v1_AESConfiguration(in *config.AESConfiguration, out *AESConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_AESConfiguration_To_v1_AESConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_EncryptionConfiguration_To_config_EncryptionConfiguration(in *EncryptionConfiguration, out *config.EncryptionConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]config.ResourceConfiguration)(unsafe.Pointer(&in.Resources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_EncryptionConfiguration_To_config_EncryptionConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_EncryptionConfiguration_To_config_EncryptionConfiguration(in *EncryptionConfiguration, out *config.EncryptionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_EncryptionConfiguration_To_config_EncryptionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_EncryptionConfiguration_To_v1_EncryptionConfiguration(in *config.EncryptionConfiguration, out *EncryptionConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]ResourceConfiguration)(unsafe.Pointer(&in.Resources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_EncryptionConfiguration_To_v1_EncryptionConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_EncryptionConfiguration_To_v1_EncryptionConfiguration(in *config.EncryptionConfiguration, out *EncryptionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_EncryptionConfiguration_To_v1_EncryptionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_IdentityConfiguration_To_config_IdentityConfiguration(in *IdentityConfiguration, out *config.IdentityConfiguration, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_IdentityConfiguration_To_config_IdentityConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_IdentityConfiguration_To_config_IdentityConfiguration(in *IdentityConfiguration, out *config.IdentityConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_IdentityConfiguration_To_config_IdentityConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_IdentityConfiguration_To_v1_IdentityConfiguration(in *config.IdentityConfiguration, out *IdentityConfiguration, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_IdentityConfiguration_To_v1_IdentityConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_IdentityConfiguration_To_v1_IdentityConfiguration(in *config.IdentityConfiguration, out *IdentityConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_IdentityConfiguration_To_v1_IdentityConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_KMSConfiguration_To_config_KMSConfiguration(in *KMSConfiguration, out *config.KMSConfiguration, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Name = in.Name
|
||||
out.CacheSize = (*int32)(unsafe.Pointer(in.CacheSize))
|
||||
out.Endpoint = in.Endpoint
|
||||
out.Timeout = (*metav1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_KMSConfiguration_To_config_KMSConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_KMSConfiguration_To_config_KMSConfiguration(in *KMSConfiguration, out *config.KMSConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_KMSConfiguration_To_config_KMSConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_KMSConfiguration_To_v1_KMSConfiguration(in *config.KMSConfiguration, out *KMSConfiguration, s conversion.Scope) error {
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Name = in.Name
|
||||
out.CacheSize = (*int32)(unsafe.Pointer(in.CacheSize))
|
||||
out.Endpoint = in.Endpoint
|
||||
out.Timeout = (*metav1.Duration)(unsafe.Pointer(in.Timeout))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_KMSConfiguration_To_v1_KMSConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_KMSConfiguration_To_v1_KMSConfiguration(in *config.KMSConfiguration, out *KMSConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_KMSConfiguration_To_v1_KMSConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Key_To_config_Key(in *Key, out *config.Key, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_Key_To_config_Key is an autogenerated conversion function.
|
||||
func Convert_v1_Key_To_config_Key(in *Key, out *config.Key, s conversion.Scope) error {
|
||||
return autoConvert_v1_Key_To_config_Key(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_Key_To_v1_Key(in *config.Key, out *Key, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Secret = in.Secret
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_Key_To_v1_Key is an autogenerated conversion function.
|
||||
func Convert_config_Key_To_v1_Key(in *config.Key, out *Key, s conversion.Scope) error {
|
||||
return autoConvert_config_Key_To_v1_Key(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ProviderConfiguration_To_config_ProviderConfiguration(in *ProviderConfiguration, out *config.ProviderConfiguration, s conversion.Scope) error {
|
||||
out.AESGCM = (*config.AESConfiguration)(unsafe.Pointer(in.AESGCM))
|
||||
out.AESCBC = (*config.AESConfiguration)(unsafe.Pointer(in.AESCBC))
|
||||
out.Secretbox = (*config.SecretboxConfiguration)(unsafe.Pointer(in.Secretbox))
|
||||
out.Identity = (*config.IdentityConfiguration)(unsafe.Pointer(in.Identity))
|
||||
out.KMS = (*config.KMSConfiguration)(unsafe.Pointer(in.KMS))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ProviderConfiguration_To_config_ProviderConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_ProviderConfiguration_To_config_ProviderConfiguration(in *ProviderConfiguration, out *config.ProviderConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_ProviderConfiguration_To_config_ProviderConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ProviderConfiguration_To_v1_ProviderConfiguration(in *config.ProviderConfiguration, out *ProviderConfiguration, s conversion.Scope) error {
|
||||
out.AESGCM = (*AESConfiguration)(unsafe.Pointer(in.AESGCM))
|
||||
out.AESCBC = (*AESConfiguration)(unsafe.Pointer(in.AESCBC))
|
||||
out.Secretbox = (*SecretboxConfiguration)(unsafe.Pointer(in.Secretbox))
|
||||
out.Identity = (*IdentityConfiguration)(unsafe.Pointer(in.Identity))
|
||||
out.KMS = (*KMSConfiguration)(unsafe.Pointer(in.KMS))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ProviderConfiguration_To_v1_ProviderConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_ProviderConfiguration_To_v1_ProviderConfiguration(in *config.ProviderConfiguration, out *ProviderConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_ProviderConfiguration_To_v1_ProviderConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ResourceConfiguration_To_config_ResourceConfiguration(in *ResourceConfiguration, out *config.ResourceConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
|
||||
out.Providers = *(*[]config.ProviderConfiguration)(unsafe.Pointer(&in.Providers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_ResourceConfiguration_To_config_ResourceConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_ResourceConfiguration_To_config_ResourceConfiguration(in *ResourceConfiguration, out *config.ResourceConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_ResourceConfiguration_To_config_ResourceConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_ResourceConfiguration_To_v1_ResourceConfiguration(in *config.ResourceConfiguration, out *ResourceConfiguration, s conversion.Scope) error {
|
||||
out.Resources = *(*[]string)(unsafe.Pointer(&in.Resources))
|
||||
out.Providers = *(*[]ProviderConfiguration)(unsafe.Pointer(&in.Providers))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_ResourceConfiguration_To_v1_ResourceConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_ResourceConfiguration_To_v1_ResourceConfiguration(in *config.ResourceConfiguration, out *ResourceConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_ResourceConfiguration_To_v1_ResourceConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_SecretboxConfiguration_To_config_SecretboxConfiguration(in *SecretboxConfiguration, out *config.SecretboxConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]config.Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_SecretboxConfiguration_To_config_SecretboxConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1_SecretboxConfiguration_To_config_SecretboxConfiguration(in *SecretboxConfiguration, out *config.SecretboxConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1_SecretboxConfiguration_To_config_SecretboxConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_config_SecretboxConfiguration_To_v1_SecretboxConfiguration(in *config.SecretboxConfiguration, out *SecretboxConfiguration, s conversion.Scope) error {
|
||||
out.Keys = *(*[]Key)(unsafe.Pointer(&in.Keys))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_config_SecretboxConfiguration_To_v1_SecretboxConfiguration is an autogenerated conversion function.
|
||||
func Convert_config_SecretboxConfiguration_To_v1_SecretboxConfiguration(in *config.SecretboxConfiguration, out *SecretboxConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_SecretboxConfiguration_To_v1_SecretboxConfiguration(in, out, s)
|
||||
}
|
228
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.deepcopy.go
generated
vendored
228
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.deepcopy.go
generated
vendored
@ -1,228 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AESConfiguration) DeepCopyInto(out *AESConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AESConfiguration.
|
||||
func (in *AESConfiguration) DeepCopy() *AESConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AESConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EncryptionConfiguration) DeepCopyInto(out *EncryptionConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]ResourceConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EncryptionConfiguration.
|
||||
func (in *EncryptionConfiguration) DeepCopy() *EncryptionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EncryptionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *EncryptionConfiguration) 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 *IdentityConfiguration) DeepCopyInto(out *IdentityConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfiguration.
|
||||
func (in *IdentityConfiguration) DeepCopy() *IdentityConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IdentityConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KMSConfiguration) DeepCopyInto(out *KMSConfiguration) {
|
||||
*out = *in
|
||||
if in.CacheSize != nil {
|
||||
in, out := &in.CacheSize, &out.CacheSize
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(metav1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSConfiguration.
|
||||
func (in *KMSConfiguration) DeepCopy() *KMSConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KMSConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Key) DeepCopyInto(out *Key) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Key.
|
||||
func (in *Key) DeepCopy() *Key {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Key)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) {
|
||||
*out = *in
|
||||
if in.AESGCM != nil {
|
||||
in, out := &in.AESGCM, &out.AESGCM
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AESCBC != nil {
|
||||
in, out := &in.AESCBC, &out.AESCBC
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Secretbox != nil {
|
||||
in, out := &in.Secretbox, &out.Secretbox
|
||||
*out = new(SecretboxConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Identity != nil {
|
||||
in, out := &in.Identity, &out.Identity
|
||||
*out = new(IdentityConfiguration)
|
||||
**out = **in
|
||||
}
|
||||
if in.KMS != nil {
|
||||
in, out := &in.KMS, &out.KMS
|
||||
*out = new(KMSConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfiguration.
|
||||
func (in *ProviderConfiguration) DeepCopy() *ProviderConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProviderConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceConfiguration) DeepCopyInto(out *ResourceConfiguration) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Providers != nil {
|
||||
in, out := &in.Providers, &out.Providers
|
||||
*out = make([]ProviderConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceConfiguration.
|
||||
func (in *ResourceConfiguration) DeepCopy() *ResourceConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SecretboxConfiguration) DeepCopyInto(out *SecretboxConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretboxConfiguration.
|
||||
func (in *SecretboxConfiguration) DeepCopy() *SecretboxConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SecretboxConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
46
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.defaults.go
generated
vendored
46
vendor/k8s.io/apiserver/pkg/apis/config/v1/zz_generated.defaults.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&EncryptionConfiguration{}, func(obj interface{}) { SetObjectDefaults_EncryptionConfiguration(obj.(*EncryptionConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_EncryptionConfiguration(in *EncryptionConfiguration) {
|
||||
for i := range in.Resources {
|
||||
a := &in.Resources[i]
|
||||
for j := range a.Providers {
|
||||
b := &a.Providers[j]
|
||||
if b.KMS != nil {
|
||||
SetDefaults_KMSConfiguration(b.KMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
228
vendor/k8s.io/apiserver/pkg/apis/config/zz_generated.deepcopy.go
generated
vendored
228
vendor/k8s.io/apiserver/pkg/apis/config/zz_generated.deepcopy.go
generated
vendored
@ -1,228 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AESConfiguration) DeepCopyInto(out *AESConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AESConfiguration.
|
||||
func (in *AESConfiguration) DeepCopy() *AESConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AESConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EncryptionConfiguration) DeepCopyInto(out *EncryptionConfiguration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]ResourceConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EncryptionConfiguration.
|
||||
func (in *EncryptionConfiguration) DeepCopy() *EncryptionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EncryptionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *EncryptionConfiguration) 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 *IdentityConfiguration) DeepCopyInto(out *IdentityConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfiguration.
|
||||
func (in *IdentityConfiguration) DeepCopy() *IdentityConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IdentityConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KMSConfiguration) DeepCopyInto(out *KMSConfiguration) {
|
||||
*out = *in
|
||||
if in.CacheSize != nil {
|
||||
in, out := &in.CacheSize, &out.CacheSize
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
*out = new(v1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSConfiguration.
|
||||
func (in *KMSConfiguration) DeepCopy() *KMSConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KMSConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Key) DeepCopyInto(out *Key) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Key.
|
||||
func (in *Key) DeepCopy() *Key {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Key)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) {
|
||||
*out = *in
|
||||
if in.AESGCM != nil {
|
||||
in, out := &in.AESGCM, &out.AESGCM
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.AESCBC != nil {
|
||||
in, out := &in.AESCBC, &out.AESCBC
|
||||
*out = new(AESConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Secretbox != nil {
|
||||
in, out := &in.Secretbox, &out.Secretbox
|
||||
*out = new(SecretboxConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Identity != nil {
|
||||
in, out := &in.Identity, &out.Identity
|
||||
*out = new(IdentityConfiguration)
|
||||
**out = **in
|
||||
}
|
||||
if in.KMS != nil {
|
||||
in, out := &in.KMS, &out.KMS
|
||||
*out = new(KMSConfiguration)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfiguration.
|
||||
func (in *ProviderConfiguration) DeepCopy() *ProviderConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProviderConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceConfiguration) DeepCopyInto(out *ResourceConfiguration) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Providers != nil {
|
||||
in, out := &in.Providers, &out.Providers
|
||||
*out = make([]ProviderConfiguration, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceConfiguration.
|
||||
func (in *ResourceConfiguration) DeepCopy() *ResourceConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SecretboxConfiguration) DeepCopyInto(out *SecretboxConfiguration) {
|
||||
*out = *in
|
||||
if in.Keys != nil {
|
||||
in, out := &in.Keys, &out.Keys
|
||||
*out = make([]Key, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretboxConfiguration.
|
||||
func (in *SecretboxConfiguration) DeepCopy() *SecretboxConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SecretboxConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
1
vendor/k8s.io/apiserver/pkg/authentication/cel/compile.go
generated
vendored
1
vendor/k8s.io/apiserver/pkg/authentication/cel/compile.go
generated
vendored
@ -106,6 +106,7 @@ func (c compiler) compile(expressionAccessor ExpressionAccessor, envVarName stri
|
||||
|
||||
return CompilationResult{
|
||||
Program: prog,
|
||||
AST: ast,
|
||||
ExpressionAccessor: expressionAccessor,
|
||||
}, nil
|
||||
}
|
||||
|
1
vendor/k8s.io/apiserver/pkg/authentication/cel/interface.go
generated
vendored
1
vendor/k8s.io/apiserver/pkg/authentication/cel/interface.go
generated
vendored
@ -35,6 +35,7 @@ type ExpressionAccessor interface {
|
||||
// CompilationResult represents a compiled validations expression.
|
||||
type CompilationResult struct {
|
||||
Program celgo.Program
|
||||
AST *celgo.Ast
|
||||
ExpressionAccessor ExpressionAccessor
|
||||
}
|
||||
|
||||
|
6
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
generated
vendored
6
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
generated
vendored
@ -39,6 +39,12 @@ const (
|
||||
// CredentialIDKey is the key used in a user's "extra" to specify the unique
|
||||
// identifier for this identity document).
|
||||
CredentialIDKey = "authentication.kubernetes.io/credential-id"
|
||||
// IssuedCredentialIDAuditAnnotationKey is the annotation key used in the audit event that is persisted to the
|
||||
// '/token' endpoint for service accounts.
|
||||
// This annotation indicates the generated credential identifier for the service account token being issued.
|
||||
// This is useful when tracing back the origin of tokens that have gone on to make request that have persisted
|
||||
// their credential-identifier into the audit log via the user's extra info stored on subsequent audit events.
|
||||
IssuedCredentialIDAuditAnnotationKey = "authentication.kubernetes.io/issued-credential-id"
|
||||
// PodNameKey is the key used in a user's "extra" to specify the pod name of
|
||||
// the authenticating request.
|
||||
PodNameKey = "authentication.kubernetes.io/pod-name"
|
||||
|
2
vendor/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go
generated
vendored
@ -153,7 +153,7 @@ const (
|
||||
DecisionDeny Decision = iota
|
||||
// DecisionAllow means that an authorizer decided to allow the action.
|
||||
DecisionAllow
|
||||
// DecisionNoOpionion means that an authorizer has no opinion on whether
|
||||
// DecisionNoOpinion means that an authorizer has no opinion on whether
|
||||
// to allow or deny an action.
|
||||
DecisionNoOpinion
|
||||
)
|
||||
|
7
vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go
generated
vendored
7
vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go
generated
vendored
@ -26,7 +26,7 @@ import (
|
||||
authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1"
|
||||
)
|
||||
|
||||
// DelegatingAuthorizerConfig is the minimal configuration needed to create an authenticator
|
||||
// DelegatingAuthorizerConfig is the minimal configuration needed to create an authorizer
|
||||
// built to delegate authorization to a kube API server
|
||||
type DelegatingAuthorizerConfig struct {
|
||||
SubjectAccessReviewClient authorizationclient.AuthorizationV1Interface
|
||||
@ -55,9 +55,6 @@ func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) {
|
||||
c.DenyCacheTTL,
|
||||
*c.WebhookRetryBackoff,
|
||||
authorizer.DecisionNoOpinion,
|
||||
webhook.AuthorizerMetrics{
|
||||
RecordRequestTotal: RecordRequestTotal,
|
||||
RecordRequestLatency: RecordRequestLatency,
|
||||
},
|
||||
NewDelegatingAuthorizerMetrics(),
|
||||
)
|
||||
}
|
||||
|
39
vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory/metrics.go
generated
vendored
39
vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory/metrics.go
generated
vendored
@ -18,18 +18,22 @@ package authorizerfactory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
celmetrics "k8s.io/apiserver/pkg/authorization/cel"
|
||||
webhookmetrics "k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics"
|
||||
compbasemetrics "k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
type registerables []compbasemetrics.Registerable
|
||||
var registerMetrics sync.Once
|
||||
|
||||
// init registers all metrics
|
||||
func init() {
|
||||
for _, metric := range metrics {
|
||||
legacyregistry.MustRegister(metric)
|
||||
}
|
||||
// RegisterMetrics registers authorizer metrics.
|
||||
func RegisterMetrics() {
|
||||
registerMetrics.Do(func() {
|
||||
legacyregistry.MustRegister(requestTotal)
|
||||
legacyregistry.MustRegister(requestLatency)
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
@ -51,19 +55,28 @@ var (
|
||||
},
|
||||
[]string{"code"},
|
||||
)
|
||||
|
||||
metrics = registerables{
|
||||
requestTotal,
|
||||
requestLatency,
|
||||
}
|
||||
)
|
||||
|
||||
var _ = webhookmetrics.AuthorizerMetrics(delegatingAuthorizerMetrics{})
|
||||
|
||||
type delegatingAuthorizerMetrics struct {
|
||||
// no-op for webhook metrics for now, delegating authorization reports original total/latency metrics
|
||||
webhookmetrics.NoopWebhookMetrics
|
||||
// no-op for matchCondition metrics for now, delegating authorization doesn't configure match conditions
|
||||
celmetrics.NoopMatcherMetrics
|
||||
}
|
||||
|
||||
func NewDelegatingAuthorizerMetrics() delegatingAuthorizerMetrics {
|
||||
RegisterMetrics()
|
||||
return delegatingAuthorizerMetrics{}
|
||||
}
|
||||
|
||||
// RecordRequestTotal increments the total number of requests for the delegated authorization.
|
||||
func RecordRequestTotal(ctx context.Context, code string) {
|
||||
func (delegatingAuthorizerMetrics) RecordRequestTotal(ctx context.Context, code string) {
|
||||
requestTotal.WithContext(ctx).WithLabelValues(code).Add(1)
|
||||
}
|
||||
|
||||
// RecordRequestLatency measures request latency in seconds for the delegated authorization. Broken down by status code.
|
||||
func RecordRequestLatency(ctx context.Context, code string, latency float64) {
|
||||
func (delegatingAuthorizerMetrics) RecordRequestLatency(ctx context.Context, code string, latency float64) {
|
||||
requestLatency.WithContext(ctx).WithLabelValues(code).Observe(latency)
|
||||
}
|
||||
|
20
vendor/k8s.io/apiserver/pkg/authorization/cel/matcher.go
generated
vendored
20
vendor/k8s.io/apiserver/pkg/authorization/cel/matcher.go
generated
vendored
@ -19,6 +19,7 @@ package cel
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
celgo "github.com/google/cel-go/cel"
|
||||
|
||||
@ -28,11 +29,29 @@ import (
|
||||
|
||||
type CELMatcher struct {
|
||||
CompilationResults []CompilationResult
|
||||
|
||||
// These are optional fields which can be populated if metrics reporting is desired
|
||||
Metrics MatcherMetrics
|
||||
AuthorizerType string
|
||||
AuthorizerName string
|
||||
}
|
||||
|
||||
// eval evaluates the given SubjectAccessReview against all cel matchCondition expression
|
||||
func (c *CELMatcher) Eval(ctx context.Context, r *authorizationv1.SubjectAccessReview) (bool, error) {
|
||||
var evalErrors []error
|
||||
|
||||
metrics := c.Metrics
|
||||
if metrics == nil {
|
||||
metrics = NoopMatcherMetrics{}
|
||||
}
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
metrics.RecordAuthorizationMatchConditionEvaluation(ctx, c.AuthorizerType, c.AuthorizerName, time.Since(start))
|
||||
if len(evalErrors) > 0 {
|
||||
metrics.RecordAuthorizationMatchConditionEvaluationFailure(ctx, c.AuthorizerType, c.AuthorizerName)
|
||||
}
|
||||
}()
|
||||
|
||||
va := map[string]interface{}{
|
||||
"request": convertObjectToUnstructured(&r.Spec),
|
||||
}
|
||||
@ -54,6 +73,7 @@ func (c *CELMatcher) Eval(ctx context.Context, r *authorizationv1.SubjectAccessR
|
||||
// If at least one matchCondition successfully evaluates to FALSE,
|
||||
// return early
|
||||
if !match {
|
||||
metrics.RecordAuthorizationMatchConditionExclusion(ctx, c.AuthorizerType, c.AuthorizerName)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
120
vendor/k8s.io/apiserver/pkg/authorization/cel/metrics.go
generated
vendored
Normal file
120
vendor/k8s.io/apiserver/pkg/authorization/cel/metrics.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2024 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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
// MatcherMetrics defines methods for reporting matchCondition metrics
|
||||
type MatcherMetrics interface {
|
||||
// RecordAuthorizationMatchConditionEvaluation records the total time taken to evaluate matchConditions for an Authorize() call to the given authorizer
|
||||
RecordAuthorizationMatchConditionEvaluation(ctx context.Context, authorizerType, authorizerName string, elapsed time.Duration)
|
||||
// RecordAuthorizationMatchConditionEvaluationFailure increments if any evaluation error was encountered evaluating matchConditions for an Authorize() call to the given authorizer
|
||||
RecordAuthorizationMatchConditionEvaluationFailure(ctx context.Context, authorizerType, authorizerName string)
|
||||
// RecordAuthorizationMatchConditionExclusion records increments when at least one matchCondition evaluates to false and excludes an Authorize() call to the given authorizer
|
||||
RecordAuthorizationMatchConditionExclusion(ctx context.Context, authorizerType, authorizerName string)
|
||||
}
|
||||
|
||||
type NoopMatcherMetrics struct{}
|
||||
|
||||
func (NoopMatcherMetrics) RecordAuthorizationMatchConditionEvaluation(ctx context.Context, authorizerType, authorizerName string, elapsed time.Duration) {
|
||||
}
|
||||
func (NoopMatcherMetrics) RecordAuthorizationMatchConditionEvaluationFailure(ctx context.Context, authorizerType, authorizerName string) {
|
||||
}
|
||||
func (NoopMatcherMetrics) RecordAuthorizationMatchConditionExclusion(ctx context.Context, authorizerType, authorizerName string) {
|
||||
}
|
||||
|
||||
type matcherMetrics struct{}
|
||||
|
||||
func NewMatcherMetrics() MatcherMetrics {
|
||||
RegisterMetrics()
|
||||
return matcherMetrics{}
|
||||
}
|
||||
|
||||
const (
|
||||
namespace = "apiserver"
|
||||
subsystem = "authorization"
|
||||
)
|
||||
|
||||
var (
|
||||
authorizationMatchConditionEvaluationErrorsTotal = metrics.NewCounterVec(
|
||||
&metrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "match_condition_evaluation_errors_total",
|
||||
Help: "Total number of errors when an authorization webhook encounters a match condition error split by authorizer type and name.",
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
},
|
||||
[]string{"type", "name"},
|
||||
)
|
||||
authorizationMatchConditionExclusionsTotal = metrics.NewCounterVec(
|
||||
&metrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "match_condition_exclusions_total",
|
||||
Help: "Total number of exclusions when an authorization webhook is skipped because match conditions exclude it.",
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
},
|
||||
[]string{"type", "name"},
|
||||
)
|
||||
authorizationMatchConditionEvaluationSeconds = metrics.NewHistogramVec(
|
||||
&metrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "match_condition_evaluation_seconds",
|
||||
Help: "Authorization match condition evaluation time in seconds, split by authorizer type and name.",
|
||||
Buckets: []float64{0.001, 0.005, 0.01, 0.025, 0.1, 0.2, 0.25},
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
},
|
||||
[]string{"type", "name"},
|
||||
)
|
||||
)
|
||||
|
||||
var registerMetrics sync.Once
|
||||
|
||||
func RegisterMetrics() {
|
||||
registerMetrics.Do(func() {
|
||||
legacyregistry.MustRegister(authorizationMatchConditionEvaluationErrorsTotal)
|
||||
legacyregistry.MustRegister(authorizationMatchConditionExclusionsTotal)
|
||||
legacyregistry.MustRegister(authorizationMatchConditionEvaluationSeconds)
|
||||
})
|
||||
}
|
||||
|
||||
func ResetMetricsForTest() {
|
||||
authorizationMatchConditionEvaluationErrorsTotal.Reset()
|
||||
authorizationMatchConditionExclusionsTotal.Reset()
|
||||
authorizationMatchConditionEvaluationSeconds.Reset()
|
||||
}
|
||||
|
||||
func (matcherMetrics) RecordAuthorizationMatchConditionEvaluationFailure(ctx context.Context, authorizerType, authorizerName string) {
|
||||
authorizationMatchConditionEvaluationErrorsTotal.WithContext(ctx).WithLabelValues(authorizerType, authorizerName).Inc()
|
||||
}
|
||||
|
||||
func (matcherMetrics) RecordAuthorizationMatchConditionExclusion(ctx context.Context, authorizerType, authorizerName string) {
|
||||
authorizationMatchConditionExclusionsTotal.WithContext(ctx).WithLabelValues(authorizerType, authorizerName).Inc()
|
||||
}
|
||||
|
||||
func (matcherMetrics) RecordAuthorizationMatchConditionEvaluation(ctx context.Context, authorizerType, authorizerName string, elapsed time.Duration) {
|
||||
elapsedSeconds := elapsed.Seconds()
|
||||
authorizationMatchConditionEvaluationSeconds.WithContext(ctx).WithLabelValues(authorizerType, authorizerName).Observe(elapsedSeconds)
|
||||
}
|
87
vendor/k8s.io/apiserver/pkg/cel/cidr.go
generated
vendored
Normal file
87
vendor/k8s.io/apiserver/pkg/cel/cidr.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/netip"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
)
|
||||
|
||||
// CIDR provides a CEL representation of an network address.
|
||||
type CIDR struct {
|
||||
netip.Prefix
|
||||
}
|
||||
|
||||
var (
|
||||
CIDRType = cel.OpaqueType("net.CIDR")
|
||||
)
|
||||
|
||||
// ConvertToNative implements ref.Val.ConvertToNative.
|
||||
func (d CIDR) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
||||
if reflect.TypeOf(d.Prefix).AssignableTo(typeDesc) {
|
||||
return d.Prefix, nil
|
||||
}
|
||||
if reflect.TypeOf("").AssignableTo(typeDesc) {
|
||||
return d.Prefix.String(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("type conversion error from 'CIDR' to '%v'", typeDesc)
|
||||
}
|
||||
|
||||
// ConvertToType implements ref.Val.ConvertToType.
|
||||
func (d CIDR) ConvertToType(typeVal ref.Type) ref.Val {
|
||||
switch typeVal {
|
||||
case CIDRType:
|
||||
return d
|
||||
case types.TypeType:
|
||||
return CIDRType
|
||||
case types.StringType:
|
||||
return types.String(d.Prefix.String())
|
||||
}
|
||||
return types.NewErr("type conversion error from '%s' to '%s'", CIDRType, typeVal)
|
||||
}
|
||||
|
||||
// Equal implements ref.Val.Equal.
|
||||
func (d CIDR) Equal(other ref.Val) ref.Val {
|
||||
otherD, ok := other.(CIDR)
|
||||
if !ok {
|
||||
return types.ValOrErr(other, "no such overload")
|
||||
}
|
||||
|
||||
return types.Bool(d.Prefix == otherD.Prefix)
|
||||
}
|
||||
|
||||
// Type implements ref.Val.Type.
|
||||
func (d CIDR) Type() ref.Type {
|
||||
return CIDRType
|
||||
}
|
||||
|
||||
// Value implements ref.Val.Value.
|
||||
func (d CIDR) Value() any {
|
||||
return d.Prefix
|
||||
}
|
||||
|
||||
// Size returns the size of the CIDR prefix address in bytes.
|
||||
// Used in the size estimation of the runtime cost.
|
||||
func (d CIDR) Size() ref.Val {
|
||||
return types.Int(int(math.Ceil(float64(d.Prefix.Bits()) / 8)))
|
||||
}
|
9
vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
9
vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
@ -43,7 +43,7 @@ import (
|
||||
// desirable because it means that CEL expressions are portable across a wider range
|
||||
// of Kubernetes versions.
|
||||
func DefaultCompatibilityVersion() *version.Version {
|
||||
return version.MajorMinor(1, 28)
|
||||
return version.MajorMinor(1, 29)
|
||||
}
|
||||
|
||||
var baseOpts = []VersionedOptions{
|
||||
@ -123,6 +123,13 @@ var baseOpts = []VersionedOptions{
|
||||
ext.Sets(),
|
||||
},
|
||||
},
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 30),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
library.IP(),
|
||||
library.CIDR(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// MustBaseEnvSet returns the common CEL base environments for Kubernetes for Version, or panics
|
||||
|
86
vendor/k8s.io/apiserver/pkg/cel/ip.go
generated
vendored
Normal file
86
vendor/k8s.io/apiserver/pkg/cel/ip.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/netip"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
)
|
||||
|
||||
// IP provides a CEL representation of an IP address.
|
||||
type IP struct {
|
||||
netip.Addr
|
||||
}
|
||||
|
||||
var (
|
||||
IPType = cel.OpaqueType("net.IP")
|
||||
)
|
||||
|
||||
// ConvertToNative implements ref.Val.ConvertToNative.
|
||||
func (d IP) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
||||
if reflect.TypeOf(d.Addr).AssignableTo(typeDesc) {
|
||||
return d.Addr, nil
|
||||
}
|
||||
if reflect.TypeOf("").AssignableTo(typeDesc) {
|
||||
return d.Addr.String(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("type conversion error from 'IP' to '%v'", typeDesc)
|
||||
}
|
||||
|
||||
// ConvertToType implements ref.Val.ConvertToType.
|
||||
func (d IP) ConvertToType(typeVal ref.Type) ref.Val {
|
||||
switch typeVal {
|
||||
case IPType:
|
||||
return d
|
||||
case types.TypeType:
|
||||
return IPType
|
||||
case types.StringType:
|
||||
return types.String(d.Addr.String())
|
||||
}
|
||||
return types.NewErr("type conversion error from '%s' to '%s'", IPType, typeVal)
|
||||
}
|
||||
|
||||
// Equal implements ref.Val.Equal.
|
||||
func (d IP) Equal(other ref.Val) ref.Val {
|
||||
otherD, ok := other.(IP)
|
||||
if !ok {
|
||||
return types.ValOrErr(other, "no such overload")
|
||||
}
|
||||
return types.Bool(d.Addr == otherD.Addr)
|
||||
}
|
||||
|
||||
// Type implements ref.Val.Type.
|
||||
func (d IP) Type() ref.Type {
|
||||
return IPType
|
||||
}
|
||||
|
||||
// Value implements ref.Val.Value.
|
||||
func (d IP) Value() any {
|
||||
return d.Addr
|
||||
}
|
||||
|
||||
// Size returns the size of the IP address in bytes.
|
||||
// Used in the size estimation of the runtime cost.
|
||||
func (d IP) Size() ref.Val {
|
||||
return types.Int(int(math.Ceil(float64(d.Addr.BitLen()) / 8)))
|
||||
}
|
287
vendor/k8s.io/apiserver/pkg/cel/library/cidr.go
generated
vendored
Normal file
287
vendor/k8s.io/apiserver/pkg/cel/library/cidr.go
generated
vendored
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
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 library
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
|
||||
apiservercel "k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
|
||||
// CIDR provides a CEL function library extension of CIDR notation parsing functions.
|
||||
//
|
||||
// cidr
|
||||
//
|
||||
// Converts a string in CIDR notation to a network address representation or results in an error if the string is not a valid CIDR notation.
|
||||
// The CIDR must be an IPv4 or IPv6 subnet address with a mask.
|
||||
// Leading zeros in IPv4 address octets are not allowed.
|
||||
// IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4/24) are not allowed.
|
||||
//
|
||||
// cidr(<string>) <CIDR>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// cidr('192.168.0.0/16') // returns an IPv4 address with a CIDR mask
|
||||
// cidr('::1/128') // returns an IPv6 address with a CIDR mask
|
||||
// cidr('192.168.0.0/33') // error
|
||||
// cidr('::1/129') // error
|
||||
// cidr('192.168.0.1/16') // error, because there are non-0 bits after the prefix
|
||||
//
|
||||
// isCIDR
|
||||
//
|
||||
// Returns true if a string is a valid CIDR notation respresentation of a subnet with mask.
|
||||
// The CIDR must be an IPv4 or IPv6 subnet address with a mask.
|
||||
// Leading zeros in IPv4 address octets are not allowed.
|
||||
// IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4/24) are not allowed.
|
||||
//
|
||||
// isCIDR(<string>) <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// isCIDR('192.168.0.0/16') // returns true
|
||||
// isCIDR('::1/128') // returns true
|
||||
// isCIDR('192.168.0.0/33') // returns false
|
||||
// isCIDR('::1/129') // returns false
|
||||
//
|
||||
// containsIP / containerCIDR / ip / masked / prefixLength
|
||||
//
|
||||
// - containsIP: Returns true if a the CIDR contains the given IP address.
|
||||
// The IP address must be an IPv4 or IPv6 address.
|
||||
// May take either a string or IP address as an argument.
|
||||
//
|
||||
// - containsCIDR: Returns true if a the CIDR contains the given CIDR.
|
||||
// The CIDR must be an IPv4 or IPv6 subnet address with a mask.
|
||||
// May take either a string or CIDR as an argument.
|
||||
//
|
||||
// - ip: Returns the IP address representation of the CIDR.
|
||||
//
|
||||
// - masked: Returns the CIDR representation of the network address with a masked prefix.
|
||||
// This can be used to return the canonical form of the CIDR network.
|
||||
//
|
||||
// - prefixLength: Returns the prefix length of the CIDR in bits.
|
||||
// This is the number of bits in the mask.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// cidr('192.168.0.0/24').containsIP(ip('192.168.0.1')) // returns true
|
||||
// cidr('192.168.0.0/24').containsIP(ip('192.168.1.1')) // returns false
|
||||
// cidr('192.168.0.0/24').containsIP('192.168.0.1') // returns true
|
||||
// cidr('192.168.0.0/24').containsIP('192.168.1.1') // returns false
|
||||
// cidr('192.168.0.0/16').containsCIDR(cidr('192.168.10.0/24')) // returns true
|
||||
// cidr('192.168.1.0/24').containsCIDR(cidr('192.168.2.0/24')) // returns false
|
||||
// cidr('192.168.0.0/16').containsCIDR('192.168.10.0/24') // returns true
|
||||
// cidr('192.168.1.0/24').containsCIDR('192.168.2.0/24') // returns false
|
||||
// cidr('192.168.0.1/24').ip() // returns ipAddr('192.168.0.1')
|
||||
// cidr('192.168.0.1/24').ip().family() // returns '4'
|
||||
// cidr('::1/128').ip() // returns ipAddr('::1')
|
||||
// cidr('::1/128').ip().family() // returns '6'
|
||||
// cidr('192.168.0.0/24').masked() // returns cidr('192.168.0.0/24')
|
||||
// cidr('192.168.0.1/24').masked() // returns cidr('192.168.0.0/24')
|
||||
// cidr('192.168.0.0/24') == cidr('192.168.0.0/24').masked() // returns true, CIDR was already in canonical format
|
||||
// cidr('192.168.0.1/24') == cidr('192.168.0.1/24').masked() // returns false, CIDR was not in canonical format
|
||||
// cidr('192.168.0.0/16').prefixLength() // returns 16
|
||||
// cidr('::1/128').prefixLength() // returns 128
|
||||
func CIDR() cel.EnvOption {
|
||||
return cel.Lib(cidrsLib)
|
||||
}
|
||||
|
||||
var cidrsLib = &cidrs{}
|
||||
|
||||
type cidrs struct{}
|
||||
|
||||
func (*cidrs) LibraryName() string {
|
||||
return "net.cidr"
|
||||
}
|
||||
|
||||
var cidrLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
"cidr": {
|
||||
cel.Overload("string_to_cidr", []*cel.Type{cel.StringType}, apiservercel.CIDRType,
|
||||
cel.UnaryBinding(stringToCIDR)),
|
||||
},
|
||||
"containsIP": {
|
||||
cel.MemberOverload("cidr_contains_ip_string", []*cel.Type{apiservercel.CIDRType, cel.StringType}, cel.BoolType,
|
||||
cel.BinaryBinding(cidrContainsIPString)),
|
||||
cel.MemberOverload("cidr_contains_ip_ip", []*cel.Type{apiservercel.CIDRType, apiservercel.IPType}, cel.BoolType,
|
||||
cel.BinaryBinding(cidrContainsIP)),
|
||||
},
|
||||
"containsCIDR": {
|
||||
cel.MemberOverload("cidr_contains_cidr_string", []*cel.Type{apiservercel.CIDRType, cel.StringType}, cel.BoolType,
|
||||
cel.BinaryBinding(cidrContainsCIDRString)),
|
||||
cel.MemberOverload("cidr_contains_cidr", []*cel.Type{apiservercel.CIDRType, apiservercel.CIDRType}, cel.BoolType,
|
||||
cel.BinaryBinding(cidrContainsCIDR)),
|
||||
},
|
||||
"ip": {
|
||||
cel.MemberOverload("cidr_ip", []*cel.Type{apiservercel.CIDRType}, apiservercel.IPType,
|
||||
cel.UnaryBinding(cidrToIP)),
|
||||
},
|
||||
"prefixLength": {
|
||||
cel.MemberOverload("cidr_prefix_length", []*cel.Type{apiservercel.CIDRType}, cel.IntType,
|
||||
cel.UnaryBinding(prefixLength)),
|
||||
},
|
||||
"masked": {
|
||||
cel.MemberOverload("cidr_masked", []*cel.Type{apiservercel.CIDRType}, apiservercel.CIDRType,
|
||||
cel.UnaryBinding(masked)),
|
||||
},
|
||||
"isCIDR": {
|
||||
cel.Overload("is_cidr", []*cel.Type{cel.StringType}, cel.BoolType,
|
||||
cel.UnaryBinding(isCIDR)),
|
||||
},
|
||||
"string": {
|
||||
cel.Overload("cidr_to_string", []*cel.Type{apiservercel.CIDRType}, cel.StringType,
|
||||
cel.UnaryBinding(cidrToString)),
|
||||
},
|
||||
}
|
||||
|
||||
func (*cidrs) CompileOptions() []cel.EnvOption {
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.CIDRType),
|
||||
cel.Variable(apiservercel.CIDRType.TypeName(), types.NewTypeTypeWithParam(apiservercel.CIDRType)),
|
||||
}
|
||||
for name, overloads := range cidrLibraryDecls {
|
||||
options = append(options, cel.Function(name, overloads...))
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func (*cidrs) ProgramOptions() []cel.ProgramOption {
|
||||
return []cel.ProgramOption{}
|
||||
}
|
||||
|
||||
func stringToCIDR(arg ref.Val) ref.Val {
|
||||
s, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
net, err := parseCIDR(s)
|
||||
if err != nil {
|
||||
return types.NewErr("network address parse error during conversion from string: %v", err)
|
||||
}
|
||||
|
||||
return apiservercel.CIDR{
|
||||
Prefix: net,
|
||||
}
|
||||
}
|
||||
|
||||
func cidrToString(arg ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.String(cidr.Prefix.String())
|
||||
}
|
||||
|
||||
func cidrContainsIPString(arg ref.Val, other ref.Val) ref.Val {
|
||||
return cidrContainsIP(arg, stringToIP(other))
|
||||
}
|
||||
|
||||
func cidrContainsCIDRString(arg ref.Val, other ref.Val) ref.Val {
|
||||
return cidrContainsCIDR(arg, stringToCIDR(other))
|
||||
}
|
||||
|
||||
func cidrContainsIP(arg ref.Val, other ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
|
||||
ip, ok := other.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(cidr.Contains(ip.Addr))
|
||||
}
|
||||
|
||||
func cidrContainsCIDR(arg ref.Val, other ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
containsCIDR, ok := other.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
|
||||
equalMasked := cidr.Prefix.Masked() == netip.PrefixFrom(containsCIDR.Prefix.Addr(), cidr.Prefix.Bits())
|
||||
return types.Bool(equalMasked && cidr.Prefix.Bits() <= containsCIDR.Prefix.Bits())
|
||||
}
|
||||
|
||||
func prefixLength(arg ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Int(cidr.Prefix.Bits())
|
||||
}
|
||||
|
||||
func isCIDR(arg ref.Val) ref.Val {
|
||||
s, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
_, err := parseCIDR(s)
|
||||
return types.Bool(err == nil)
|
||||
}
|
||||
|
||||
func cidrToIP(arg ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return apiservercel.IP{
|
||||
Addr: cidr.Prefix.Addr(),
|
||||
}
|
||||
}
|
||||
|
||||
func masked(arg ref.Val) ref.Val {
|
||||
cidr, ok := arg.(apiservercel.CIDR)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
maskedCIDR := cidr.Prefix.Masked()
|
||||
return apiservercel.CIDR{
|
||||
Prefix: maskedCIDR,
|
||||
}
|
||||
}
|
||||
|
||||
// parseCIDR parses a string into an CIDR.
|
||||
// We use this function to parse CIDR notation in the CEL library
|
||||
// so that we can share the common logic of rejecting strings
|
||||
// that IPv4-mapped IPv6 addresses or contain non-zero bits after the mask.
|
||||
func parseCIDR(raw string) (netip.Prefix, error) {
|
||||
net, err := netip.ParsePrefix(raw)
|
||||
if err != nil {
|
||||
return netip.Prefix{}, fmt.Errorf("network address parse error during conversion from string: %v", err)
|
||||
}
|
||||
|
||||
if net.Addr().Is4In6() {
|
||||
return netip.Prefix{}, fmt.Errorf("IPv4-mapped IPv6 address %q is not allowed", raw)
|
||||
}
|
||||
|
||||
return net, nil
|
||||
}
|
150
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
150
vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
@ -79,6 +79,82 @@ func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, re
|
||||
cost := strCost * regexCost
|
||||
return &cost
|
||||
}
|
||||
case "cidr", "isIP", "isCIDR":
|
||||
// IP and CIDR parsing is a string traversal.
|
||||
if len(args) >= 1 {
|
||||
cost := uint64(math.Ceil(float64(actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
return &cost
|
||||
}
|
||||
case "ip":
|
||||
// IP and CIDR parsing is a string traversal.
|
||||
if len(args) >= 1 {
|
||||
if overloadId == "cidr_ip" {
|
||||
// The IP member of the CIDR object is just accessing a field.
|
||||
// Nominal cost.
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
}
|
||||
|
||||
cost := uint64(math.Ceil(float64(actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
return &cost
|
||||
}
|
||||
case "ip.isCanonical":
|
||||
if len(args) >= 1 {
|
||||
// We have to parse the string and then compare the parsed string to the original string.
|
||||
// So we double the cost of parsing the string.
|
||||
cost := uint64(math.Ceil(float64(actualSize(args[0])) * 2 * common.StringTraversalCostFactor))
|
||||
return &cost
|
||||
}
|
||||
case "masked", "prefixLength", "family", "isUnspecified", "isLoopback", "isLinkLocalMulticast", "isLinkLocalUnicast":
|
||||
// IP and CIDR accessors are nominal cost.
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
case "containsIP":
|
||||
if len(args) >= 2 {
|
||||
cidrSize := actualSize(args[0])
|
||||
otherSize := actualSize(args[1])
|
||||
|
||||
// This is the base cost of comparing two byte lists.
|
||||
// We will compare only up to the length of the CIDR prefix in bytes, so use the cidrSize twice.
|
||||
cost := uint64(math.Ceil(float64(cidrSize+cidrSize) * common.StringTraversalCostFactor))
|
||||
|
||||
if overloadId == "cidr_contains_ip_string" {
|
||||
// If we are comparing a string, we must parse the string to into the right type, so add the cost of traversing the string again.
|
||||
cost += uint64(math.Ceil(float64(otherSize) * common.StringTraversalCostFactor))
|
||||
|
||||
}
|
||||
|
||||
return &cost
|
||||
}
|
||||
case "containsCIDR":
|
||||
if len(args) >= 2 {
|
||||
cidrSize := actualSize(args[0])
|
||||
otherSize := actualSize(args[1])
|
||||
|
||||
// This is the base cost of comparing two byte lists.
|
||||
// We will compare only up to the length of the CIDR prefix in bytes, so use the cidrSize twice.
|
||||
cost := uint64(math.Ceil(float64(cidrSize+cidrSize) * common.StringTraversalCostFactor))
|
||||
|
||||
// As we are comparing if a CIDR is within another CIDR, we first mask the base CIDR and
|
||||
// also compare the CIDR bits.
|
||||
// This has an additional cost of the length of the IP being traversed again, plus 1.
|
||||
cost += uint64(math.Ceil(float64(cidrSize)*common.StringTraversalCostFactor)) + 1
|
||||
|
||||
if overloadId == "cidr_contains_cidr_string" {
|
||||
// If we are comparing a string, we must parse the string to into the right type, so add the cost of traversing the string again.
|
||||
cost += uint64(math.Ceil(float64(otherSize) * common.StringTraversalCostFactor))
|
||||
}
|
||||
|
||||
return &cost
|
||||
}
|
||||
case "quantity", "isQuantity":
|
||||
if len(args) >= 1 {
|
||||
cost := uint64(math.Ceil(float64(actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
return &cost
|
||||
}
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -225,6 +301,80 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
|
||||
// worst case size of result is that every char is returned as separate find result.
|
||||
return &checker.CallEstimate{CostEstimate: strCost.Multiply(regexCost), ResultSize: &checker.SizeEstimate{Min: 0, Max: sz.Max}}
|
||||
}
|
||||
case "cidr", "isIP", "isCIDR":
|
||||
if target != nil {
|
||||
sz := l.sizeEstimate(args[0])
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(common.StringTraversalCostFactor)}
|
||||
}
|
||||
case "ip":
|
||||
if target != nil && len(args) >= 1 {
|
||||
if overloadId == "cidr_ip" {
|
||||
// The IP member of the CIDR object is just accessing a field.
|
||||
// Nominal cost.
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
}
|
||||
|
||||
sz := l.sizeEstimate(args[0])
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(common.StringTraversalCostFactor)}
|
||||
} else if target != nil {
|
||||
// The IP member of a CIDR is a just accessing a field, nominal cost.
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
}
|
||||
case "ip.isCanonical":
|
||||
if target != nil && len(args) >= 1 {
|
||||
sz := l.sizeEstimate(args[0])
|
||||
// We have to parse the string and then compare the parsed string to the original string.
|
||||
// So we double the cost of parsing the string.
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(2 * common.StringTraversalCostFactor)}
|
||||
}
|
||||
case "masked", "prefixLength", "family", "isUnspecified", "isLoopback", "isLinkLocalMulticast", "isLinkLocalUnicast":
|
||||
// IP and CIDR accessors are nominal cost.
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
case "containsIP":
|
||||
if target != nil && len(args) >= 1 {
|
||||
// The base cost of the function is the cost of comparing two byte lists.
|
||||
// The byte lists will be either ipv4 or ipv6 so will have a length of 4, or 16 bytes.
|
||||
sz := checker.SizeEstimate{Min: 4, Max: 16}
|
||||
|
||||
// We have to compare the two strings to determine if the CIDR/IP is in the other CIDR.
|
||||
ipCompCost := sz.Add(sz).MultiplyByCostFactor(common.StringTraversalCostFactor)
|
||||
|
||||
if overloadId == "cidr_contains_ip_string" {
|
||||
// If we are comparing a string, we must parse the string to into the right type, so add the cost of traversing the string again.
|
||||
ipCompCost = ipCompCost.Add(checker.CostEstimate(l.sizeEstimate(args[0])).MultiplyByCostFactor(common.StringTraversalCostFactor))
|
||||
}
|
||||
|
||||
return &checker.CallEstimate{CostEstimate: ipCompCost}
|
||||
}
|
||||
case "containsCIDR":
|
||||
if target != nil && len(args) >= 1 {
|
||||
// The base cost of the function is the cost of comparing two byte lists.
|
||||
// The byte lists will be either ipv4 or ipv6 so will have a length of 4, or 16 bytes.
|
||||
sz := checker.SizeEstimate{Min: 4, Max: 16}
|
||||
|
||||
// We have to compare the two strings to determine if the CIDR/IP is in the other CIDR.
|
||||
ipCompCost := sz.Add(sz).MultiplyByCostFactor(common.StringTraversalCostFactor)
|
||||
|
||||
// As we are comparing if a CIDR is within another CIDR, we first mask the base CIDR and
|
||||
// also compare the CIDR bits.
|
||||
// This has an additional cost of the length of the IP being traversed again, plus 1.
|
||||
ipCompCost = ipCompCost.Add(sz.MultiplyByCostFactor(common.StringTraversalCostFactor))
|
||||
ipCompCost = ipCompCost.Add(checker.CostEstimate{Min: 1, Max: 1})
|
||||
|
||||
if overloadId == "cidr_contains_cidr_string" {
|
||||
// If we are comparing a string, we must parse the string to into the right type, so add the cost of traversing the string again.
|
||||
ipCompCost = ipCompCost.Add(checker.CostEstimate(l.sizeEstimate(args[0])).MultiplyByCostFactor(common.StringTraversalCostFactor))
|
||||
}
|
||||
|
||||
return &checker.CallEstimate{CostEstimate: ipCompCost}
|
||||
}
|
||||
case "quantity", "isQuantity":
|
||||
if target != nil {
|
||||
sz := l.sizeEstimate(args[0])
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(common.StringTraversalCostFactor)}
|
||||
}
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
329
vendor/k8s.io/apiserver/pkg/cel/library/ip.go
generated
vendored
Normal file
329
vendor/k8s.io/apiserver/pkg/cel/library/ip.go
generated
vendored
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
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 library
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
|
||||
apiservercel "k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
|
||||
// IP provides a CEL function library extension of IP address parsing functions.
|
||||
//
|
||||
// ip
|
||||
//
|
||||
// Converts a string to an IP address or results in an error if the string is not a valid IP address.
|
||||
// The IP address must be an IPv4 or IPv6 address.
|
||||
// IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4) are not allowed.
|
||||
// IP addresses with zones (e.g. fe80::1%eth0) are not allowed.
|
||||
// Leading zeros in IPv4 address octets are not allowed.
|
||||
//
|
||||
// ip(<string>) <IPAddr>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ip('127.0.0.1') // returns an IPv4 address
|
||||
// ip('::1') // returns an IPv6 address
|
||||
// ip('127.0.0.256') // error
|
||||
// ip(':::1') // error
|
||||
//
|
||||
// isIP
|
||||
//
|
||||
// Returns true if a string is a valid IP address.
|
||||
// The IP address must be an IPv4 or IPv6 address.
|
||||
// IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4) are not allowed.
|
||||
// IP addresses with zones (e.g. fe80::1%eth0) are not allowed.
|
||||
// Leading zeros in IPv4 address octets are not allowed.
|
||||
//
|
||||
// isIP(<string>) <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// isIP('127.0.0.1') // returns true
|
||||
// isIP('::1') // returns true
|
||||
// isIP('127.0.0.256') // returns false
|
||||
// isIP(':::1') // returns false
|
||||
//
|
||||
// ip.isCanonical
|
||||
//
|
||||
// Returns true if the IP address is in its canonical form.
|
||||
// There is exactly one canonical form for every IP address, so fields containing
|
||||
// IPs in canonical form can just be treated as strings when checking for equality or uniqueness.
|
||||
//
|
||||
// ip.isCanonical(<string>) <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ip.isCanonical('127.0.0.1') // returns true; all valid IPv4 addresses are canonical
|
||||
// ip.isCanonical('2001:db8::abcd') // returns true
|
||||
// ip.isCanonical('2001:DB8::ABCD') // returns false
|
||||
// ip.isCanonical('2001:db8::0:0:0:abcd') // returns false
|
||||
//
|
||||
// family / isUnspecified / isLoopback / isLinkLocalMulticast / isLinkLocalUnicast / isGlobalUnicast
|
||||
//
|
||||
// - family: returns the IP addresses' family (IPv4 or IPv6) as an integer, either '4' or '6'.
|
||||
//
|
||||
// - isUnspecified: returns true if the IP address is the unspecified address.
|
||||
// Either the IPv4 address "0.0.0.0" or the IPv6 address "::".
|
||||
//
|
||||
// - isLoopback: returns true if the IP address is the loopback address.
|
||||
// Either an IPv4 address with a value of 127.x.x.x or an IPv6 address with a value of ::1.
|
||||
//
|
||||
// - isLinkLocalMulticast: returns true if the IP address is a link-local multicast address.
|
||||
// Either an IPv4 address with a value of 224.0.0.x or an IPv6 address in the network ff00::/8.
|
||||
//
|
||||
// - isLinkLocalUnicast: returns true if the IP address is a link-local unicast address.
|
||||
// Either an IPv4 address with a value of 169.254.x.x or an IPv6 address in the network fe80::/10.
|
||||
//
|
||||
// - isGlobalUnicast: returns true if the IP address is a global unicast address.
|
||||
// Either an IPv4 address that is not zero or 255.255.255.255 or an IPv6 address that is not a link-local unicast, loopback or multicast address.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// ip('127.0.0.1').family() // returns '4”
|
||||
// ip('::1').family() // returns '6'
|
||||
// ip('127.0.0.1').family() == 4 // returns true
|
||||
// ip('::1').family() == 6 // returns true
|
||||
// ip('0.0.0.0').isUnspecified() // returns true
|
||||
// ip('127.0.0.1').isUnspecified() // returns false
|
||||
// ip('::').isUnspecified() // returns true
|
||||
// ip('::1').isUnspecified() // returns false
|
||||
// ip('127.0.0.1').isLoopback() // returns true
|
||||
// ip('192.168.0.1').isLoopback() // returns false
|
||||
// ip('::1').isLoopback() // returns true
|
||||
// ip('2001:db8::abcd').isLoopback() // returns false
|
||||
// ip('224.0.0.1').isLinkLocalMulticast() // returns true
|
||||
// ip('224.0.1.1').isLinkLocalMulticast() // returns false
|
||||
// ip('ff02::1').isLinkLocalMulticast() // returns true
|
||||
// ip('fd00::1').isLinkLocalMulticast() // returns false
|
||||
// ip('169.254.169.254').isLinkLocalUnicast() // returns true
|
||||
// ip('192.168.0.1').isLinkLocalUnicast() // returns false
|
||||
// ip('fe80::1').isLinkLocalUnicast() // returns true
|
||||
// ip('fd80::1').isLinkLocalUnicast() // returns false
|
||||
// ip('192.168.0.1').isGlobalUnicast() // returns true
|
||||
// ip('255.255.255.255').isGlobalUnicast() // returns false
|
||||
// ip('2001:db8::abcd').isGlobalUnicast() // returns true
|
||||
// ip('ff00::1').isGlobalUnicast() // returns false
|
||||
func IP() cel.EnvOption {
|
||||
return cel.Lib(ipLib)
|
||||
}
|
||||
|
||||
var ipLib = &ip{}
|
||||
|
||||
type ip struct{}
|
||||
|
||||
func (*ip) LibraryName() string {
|
||||
return "net.ip"
|
||||
}
|
||||
|
||||
var ipLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
"ip": {
|
||||
cel.Overload("string_to_ip", []*cel.Type{cel.StringType}, apiservercel.IPType,
|
||||
cel.UnaryBinding(stringToIP)),
|
||||
},
|
||||
"family": {
|
||||
cel.MemberOverload("ip_family", []*cel.Type{apiservercel.IPType}, cel.IntType,
|
||||
cel.UnaryBinding(family)),
|
||||
},
|
||||
"ip.isCanonical": {
|
||||
cel.Overload("ip_is_canonical", []*cel.Type{cel.StringType}, cel.BoolType,
|
||||
cel.UnaryBinding(ipIsCanonical)),
|
||||
},
|
||||
"isUnspecified": {
|
||||
cel.MemberOverload("ip_is_unspecified", []*cel.Type{apiservercel.IPType}, cel.BoolType,
|
||||
cel.UnaryBinding(isUnspecified)),
|
||||
},
|
||||
"isLoopback": {
|
||||
cel.MemberOverload("ip_is_loopback", []*cel.Type{apiservercel.IPType}, cel.BoolType,
|
||||
cel.UnaryBinding(isLoopback)),
|
||||
},
|
||||
"isLinkLocalMulticast": {
|
||||
cel.MemberOverload("ip_is_link_local_multicast", []*cel.Type{apiservercel.IPType}, cel.BoolType,
|
||||
cel.UnaryBinding(isLinkLocalMulticast)),
|
||||
},
|
||||
"isLinkLocalUnicast": {
|
||||
cel.MemberOverload("ip_is_link_local_unicast", []*cel.Type{apiservercel.IPType}, cel.BoolType,
|
||||
cel.UnaryBinding(isLinkLocalUnicast)),
|
||||
},
|
||||
"isGlobalUnicast": {
|
||||
cel.MemberOverload("ip_is_global_unicast", []*cel.Type{apiservercel.IPType}, cel.BoolType,
|
||||
cel.UnaryBinding(isGlobalUnicast)),
|
||||
},
|
||||
"isIP": {
|
||||
cel.Overload("is_ip", []*cel.Type{cel.StringType}, cel.BoolType,
|
||||
cel.UnaryBinding(isIP)),
|
||||
},
|
||||
"string": {
|
||||
cel.Overload("ip_to_string", []*cel.Type{apiservercel.IPType}, cel.StringType,
|
||||
cel.UnaryBinding(ipToString)),
|
||||
},
|
||||
}
|
||||
|
||||
func (*ip) CompileOptions() []cel.EnvOption {
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.IPType),
|
||||
cel.Variable(apiservercel.IPType.TypeName(), types.NewTypeTypeWithParam(apiservercel.IPType)),
|
||||
}
|
||||
for name, overloads := range ipLibraryDecls {
|
||||
options = append(options, cel.Function(name, overloads...))
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func (*ip) ProgramOptions() []cel.ProgramOption {
|
||||
return []cel.ProgramOption{}
|
||||
}
|
||||
|
||||
func stringToIP(arg ref.Val) ref.Val {
|
||||
s, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
addr, err := parseIPAddr(s)
|
||||
if err != nil {
|
||||
// Don't add context, we control the error message already.
|
||||
return types.NewErr("%v", err)
|
||||
}
|
||||
|
||||
return apiservercel.IP{
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
func ipToString(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.String(ip.Addr.String())
|
||||
}
|
||||
|
||||
func family(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
switch {
|
||||
case ip.Addr.Is4():
|
||||
return types.Int(4)
|
||||
case ip.Addr.Is6():
|
||||
return types.Int(6)
|
||||
default:
|
||||
return types.NewErr("IP address %q is not an IPv4 or IPv6 address", ip.Addr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func ipIsCanonical(arg ref.Val) ref.Val {
|
||||
s, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
addr, err := parseIPAddr(s)
|
||||
if err != nil {
|
||||
// Don't add context, we control the error message already.
|
||||
return types.NewErr("%v", err)
|
||||
}
|
||||
|
||||
// Addr.String() always returns the canonical form of the IP address.
|
||||
// Therefore comparing this with the original string representation
|
||||
// will tell us if the IP address is in its canonical form.
|
||||
return types.Bool(addr.String() == s)
|
||||
}
|
||||
|
||||
func isIP(arg ref.Val) ref.Val {
|
||||
s, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
_, err := parseIPAddr(s)
|
||||
return types.Bool(err == nil)
|
||||
}
|
||||
|
||||
func isUnspecified(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(ip.Addr.IsUnspecified())
|
||||
}
|
||||
|
||||
func isLoopback(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(ip.Addr.IsLoopback())
|
||||
}
|
||||
|
||||
func isLinkLocalMulticast(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(ip.Addr.IsLinkLocalMulticast())
|
||||
}
|
||||
|
||||
func isLinkLocalUnicast(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(ip.Addr.IsLinkLocalUnicast())
|
||||
}
|
||||
|
||||
func isGlobalUnicast(arg ref.Val) ref.Val {
|
||||
ip, ok := arg.(apiservercel.IP)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
return types.Bool(ip.Addr.IsGlobalUnicast())
|
||||
}
|
||||
|
||||
// parseIPAddr parses a string into an IP address.
|
||||
// We use this function to parse IP addresses in the CEL library
|
||||
// so that we can share the common logic of rejecting IP addresses
|
||||
// that contain zones or are IPv4-mapped IPv6 addresses.
|
||||
func parseIPAddr(raw string) (netip.Addr, error) {
|
||||
addr, err := netip.ParseAddr(raw)
|
||||
if err != nil {
|
||||
return netip.Addr{}, fmt.Errorf("IP Address %q parse error during conversion from string: %v", raw, err)
|
||||
}
|
||||
|
||||
if addr.Zone() != "" {
|
||||
return netip.Addr{}, fmt.Errorf("IP address %q with zone value is not allowed", raw)
|
||||
}
|
||||
|
||||
if addr.Is4In6() {
|
||||
return netip.Addr{}, fmt.Errorf("IPv4-mapped IPv6 address %q is not allowed", raw)
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
4
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/etag.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/etag.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
@ -39,6 +40,7 @@ import (
|
||||
func ServeHTTPWithETag(
|
||||
object runtime.Object,
|
||||
hash string,
|
||||
targetGV schema.GroupVersion,
|
||||
serializer runtime.NegotiatedSerializer,
|
||||
w http.ResponseWriter,
|
||||
req *http.Request,
|
||||
@ -64,7 +66,7 @@ func ServeHTTPWithETag(
|
||||
responsewriters.WriteObjectNegotiated(
|
||||
serializer,
|
||||
DiscoveryEndpointRestrictions,
|
||||
AggregatedDiscoveryGV,
|
||||
targetGV,
|
||||
w,
|
||||
req,
|
||||
http.StatusOK,
|
||||
|
6
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/fake.go
generated
vendored
6
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/fake.go
generated
vendored
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
@ -122,7 +122,7 @@ func (f *recorderResourceManager) SetGroupVersionPriority(gv metav1.GroupVersion
|
||||
})
|
||||
}
|
||||
|
||||
func (f *recorderResourceManager) AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
||||
func (f *recorderResourceManager) AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
@ -153,7 +153,7 @@ func (f *recorderResourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
|
||||
})
|
||||
|
||||
}
|
||||
func (f *recorderResourceManager) SetGroups(values []apidiscoveryv2beta1.APIGroupDiscovery) {
|
||||
func (f *recorderResourceManager) SetGroups(values []apidiscoveryv2.APIGroupDiscovery) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
|
72
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/handler.go
generated
vendored
72
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/handler.go
generated
vendored
@ -17,15 +17,22 @@ limitations under the License.
|
||||
package aggregated
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
|
||||
"sync/atomic"
|
||||
@ -51,7 +58,7 @@ type ResourceManager interface {
|
||||
// Adds knowledge of the given groupversion to the discovery document
|
||||
// If it was already being tracked, updates the stored APIVersionDiscovery
|
||||
// Thread-safe
|
||||
AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery)
|
||||
AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery)
|
||||
|
||||
// Sets a priority to be used while sorting a specific group and
|
||||
// group-version. If two versions report different priorities for
|
||||
@ -72,7 +79,7 @@ type ResourceManager interface {
|
||||
// Resets the manager's known list of group-versions and replaces them
|
||||
// with the given groups
|
||||
// Thread-Safe
|
||||
SetGroups([]apidiscoveryv2beta1.APIGroupDiscovery)
|
||||
SetGroups([]apidiscoveryv2.APIGroupDiscovery)
|
||||
|
||||
// Returns the same resource manager using a different source
|
||||
// The source is used to decide how to de-duplicate groups.
|
||||
@ -87,7 +94,7 @@ type resourceManager struct {
|
||||
*resourceDiscoveryManager
|
||||
}
|
||||
|
||||
func (rm resourceManager) AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
||||
func (rm resourceManager) AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||
rm.resourceDiscoveryManager.AddGroupVersion(rm.source, groupName, value)
|
||||
}
|
||||
func (rm resourceManager) SetGroupVersionPriority(gv metav1.GroupVersion, grouppriority, versionpriority int) {
|
||||
@ -99,7 +106,7 @@ func (rm resourceManager) RemoveGroup(groupName string) {
|
||||
func (rm resourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
|
||||
rm.resourceDiscoveryManager.RemoveGroupVersion(rm.source, gv)
|
||||
}
|
||||
func (rm resourceManager) SetGroups(groups []apidiscoveryv2beta1.APIGroupDiscovery) {
|
||||
func (rm resourceManager) SetGroups(groups []apidiscoveryv2.APIGroupDiscovery) {
|
||||
rm.resourceDiscoveryManager.SetGroups(rm.source, groups)
|
||||
}
|
||||
|
||||
@ -133,7 +140,7 @@ type resourceDiscoveryManager struct {
|
||||
// Writes protected by the lock.
|
||||
// List of all apigroups & resources indexed by the resource manager
|
||||
lock sync.RWMutex
|
||||
apiGroups map[groupKey]*apidiscoveryv2beta1.APIGroupDiscovery
|
||||
apiGroups map[groupKey]*apidiscoveryv2.APIGroupDiscovery
|
||||
versionPriorities map[groupVersionKey]priorityInfo
|
||||
}
|
||||
|
||||
@ -144,8 +151,12 @@ type priorityInfo struct {
|
||||
|
||||
func NewResourceManager(path string) ResourceManager {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
utilruntime.Must(apidiscoveryv2.AddToScheme(scheme))
|
||||
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
||||
// Register conversion for apidiscovery
|
||||
utilruntime.Must(apidiscoveryv2conversion.RegisterConversions(scheme))
|
||||
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
rdm := &resourceDiscoveryManager{
|
||||
serializer: codecs,
|
||||
versionPriorities: make(map[groupVersionKey]priorityInfo),
|
||||
@ -181,7 +192,7 @@ func (rdm *resourceDiscoveryManager) SetGroupVersionPriority(source Source, gv m
|
||||
rdm.cache.Store(nil)
|
||||
}
|
||||
|
||||
func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscoveryv2beta1.APIGroupDiscovery) {
|
||||
func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscoveryv2.APIGroupDiscovery) {
|
||||
rdm.lock.Lock()
|
||||
defer rdm.lock.Unlock()
|
||||
|
||||
@ -221,17 +232,17 @@ func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscov
|
||||
}
|
||||
}
|
||||
|
||||
func (rdm *resourceDiscoveryManager) AddGroupVersion(source Source, groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
||||
func (rdm *resourceDiscoveryManager) AddGroupVersion(source Source, groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||
rdm.lock.Lock()
|
||||
defer rdm.lock.Unlock()
|
||||
|
||||
rdm.addGroupVersionLocked(source, groupName, value)
|
||||
}
|
||||
|
||||
func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
||||
func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||
|
||||
if rdm.apiGroups == nil {
|
||||
rdm.apiGroups = make(map[groupKey]*apidiscoveryv2beta1.APIGroupDiscovery)
|
||||
rdm.apiGroups = make(map[groupKey]*apidiscoveryv2.APIGroupDiscovery)
|
||||
}
|
||||
|
||||
key := groupKey{
|
||||
@ -264,11 +275,11 @@ func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupN
|
||||
}
|
||||
|
||||
} else {
|
||||
group := &apidiscoveryv2beta1.APIGroupDiscovery{
|
||||
group := &apidiscoveryv2.APIGroupDiscovery{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: groupName,
|
||||
},
|
||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{value},
|
||||
Versions: []apidiscoveryv2.APIVersionDiscovery{value},
|
||||
}
|
||||
rdm.apiGroups[key] = group
|
||||
}
|
||||
@ -354,12 +365,12 @@ func (rdm *resourceDiscoveryManager) RemoveGroup(source Source, groupName string
|
||||
|
||||
// Prepares the api group list for serving by converting them from map into
|
||||
// list and sorting them according to insertion order
|
||||
func (rdm *resourceDiscoveryManager) calculateAPIGroupsLocked() []apidiscoveryv2beta1.APIGroupDiscovery {
|
||||
func (rdm *resourceDiscoveryManager) calculateAPIGroupsLocked() []apidiscoveryv2.APIGroupDiscovery {
|
||||
regenerationCounter.Inc()
|
||||
// Re-order the apiGroups by their priority.
|
||||
groups := []apidiscoveryv2beta1.APIGroupDiscovery{}
|
||||
groups := []apidiscoveryv2.APIGroupDiscovery{}
|
||||
|
||||
groupsToUse := map[string]apidiscoveryv2beta1.APIGroupDiscovery{}
|
||||
groupsToUse := map[string]apidiscoveryv2.APIGroupDiscovery{}
|
||||
sourcesUsed := map[metav1.GroupVersion]Source{}
|
||||
|
||||
for key, group := range rdm.apiGroups {
|
||||
@ -475,7 +486,7 @@ func (rdm *resourceDiscoveryManager) fetchFromCache() *cachedGroupList {
|
||||
if cacheLoad != nil {
|
||||
return cacheLoad
|
||||
}
|
||||
response := apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||
response := apidiscoveryv2.APIGroupDiscoveryList{
|
||||
Items: rdm.calculateAPIGroupsLocked(),
|
||||
}
|
||||
etag, err := calculateETag(response)
|
||||
@ -492,7 +503,13 @@ func (rdm *resourceDiscoveryManager) fetchFromCache() *cachedGroupList {
|
||||
}
|
||||
|
||||
type cachedGroupList struct {
|
||||
cachedResponse apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||
cachedResponse apidiscoveryv2.APIGroupDiscoveryList
|
||||
// etag is calculated based on a SHA hash of only the JSON object.
|
||||
// A response via different Accept encodings (eg: protobuf, json) will
|
||||
// yield the same etag. This is okay because Accept is part of the Vary header.
|
||||
// Per RFC7231 a client must only cache a response etag pair if the header field
|
||||
// matches as indicated by the Vary field. Thus, protobuf and json and other Accept
|
||||
// encodings will not be cached as the same response despite having the same etag.
|
||||
cachedResponseETag string
|
||||
}
|
||||
|
||||
@ -505,11 +522,30 @@ func (rdm *resourceDiscoveryManager) serveHTTP(resp http.ResponseWriter, req *ht
|
||||
response := cache.cachedResponse
|
||||
etag := cache.cachedResponseETag
|
||||
|
||||
mediaType, _, err := negotiation.NegotiateOutputMediaType(req, rdm.serializer, DiscoveryEndpointRestrictions)
|
||||
if err != nil {
|
||||
// Should never happen. wrapper.go will only proxy requests to this
|
||||
// handler if the media type passes DiscoveryEndpointRestrictions
|
||||
utilruntime.HandleError(err)
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var targetGV schema.GroupVersion
|
||||
if mediaType.Convert == nil ||
|
||||
(mediaType.Convert.GroupVersion() != apidiscoveryv2.SchemeGroupVersion &&
|
||||
mediaType.Convert.GroupVersion() != apidiscoveryv2beta1.SchemeGroupVersion) {
|
||||
utilruntime.HandleError(fmt.Errorf("expected aggregated discovery group version, got group: %s, version %s", mediaType.Convert.Group, mediaType.Convert.Version))
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
targetGV = mediaType.Convert.GroupVersion()
|
||||
|
||||
if len(etag) > 0 {
|
||||
// Use proper e-tag headers if one is available
|
||||
ServeHTTPWithETag(
|
||||
&response,
|
||||
etag,
|
||||
targetGV,
|
||||
rdm.serializer,
|
||||
resp,
|
||||
req,
|
||||
@ -520,7 +556,7 @@ func (rdm *resourceDiscoveryManager) serveHTTP(resp http.ResponseWriter, req *ht
|
||||
responsewriters.WriteObjectNegotiated(
|
||||
rdm.serializer,
|
||||
DiscoveryEndpointRestrictions,
|
||||
AggregatedDiscoveryGV,
|
||||
targetGV,
|
||||
resp,
|
||||
req,
|
||||
http.StatusOK,
|
||||
|
4
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/negotiation.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/negotiation.go
generated
vendored
@ -20,8 +20,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
var AggregatedDiscoveryGV = schema.GroupVersion{Group: "apidiscovery.k8s.io", Version: "v2beta1"}
|
||||
|
||||
// Interface is from "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
|
||||
// DiscoveryEndpointRestrictions allows requests to /apis to provide a Content Negotiation GVK for aggregated discovery.
|
||||
@ -39,7 +37,7 @@ func (discoveryEndpointRestrictions) AllowsStreamSchema(s string) bool { return
|
||||
// IsAggregatedDiscoveryGVK checks if a provided GVK is the GVK for serving aggregated discovery.
|
||||
func IsAggregatedDiscoveryGVK(gvk *schema.GroupVersionKind) bool {
|
||||
if gvk != nil {
|
||||
return gvk.Group == "apidiscovery.k8s.io" && gvk.Version == "v2beta1" && gvk.Kind == "APIGroupDiscoveryList"
|
||||
return gvk.Group == "apidiscovery.k8s.io" && (gvk.Version == "v2beta1" || gvk.Version == "v2") && gvk.Kind == "APIGroupDiscoveryList"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
7
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go
generated
vendored
7
vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go
generated
vendored
@ -19,8 +19,10 @@ package aggregated
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -69,10 +71,11 @@ func (wrapped *WrappedHandler) GenerateWebService(prefix string, returnType inte
|
||||
// WrapAggregatedDiscoveryToHandler wraps a handler with an option to
|
||||
// emit the aggregated discovery by passing in the aggregated
|
||||
// discovery type in content negotiation headers: eg: (Accept:
|
||||
// application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList)
|
||||
// application/json;v=v2;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList)
|
||||
func WrapAggregatedDiscoveryToHandler(handler http.Handler, aggHandler http.Handler) *WrappedHandler {
|
||||
scheme := runtime.NewScheme()
|
||||
apidiscoveryv2beta1.AddToScheme(scheme)
|
||||
utilruntime.Must(apidiscoveryv2.AddToScheme(scheme))
|
||||
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
return &WrappedHandler{codecs, handler, aggHandler}
|
||||
}
|
||||
|
14
vendor/k8s.io/apiserver/pkg/endpoints/filters/request_deadline.go
generated
vendored
14
vendor/k8s.io/apiserver/pkg/endpoints/filters/request_deadline.go
generated
vendored
@ -58,7 +58,7 @@ func withRequestDeadline(handler http.Handler, sink audit.Sink, policy audit.Pol
|
||||
|
||||
requestInfo, ok := request.RequestInfoFrom(ctx)
|
||||
if !ok {
|
||||
handleError(w, req, http.StatusInternalServerError, fmt.Errorf("no RequestInfo found in context, handler chain must be wrong"))
|
||||
handleError(w, req, http.StatusInternalServerError, nil, "no RequestInfo found in context, handler chain must be wrong")
|
||||
return
|
||||
}
|
||||
if longRunning(req, requestInfo) {
|
||||
@ -166,8 +166,12 @@ func parseTimeout(req *http.Request) (time.Duration, bool, error) {
|
||||
return timeout, true, nil
|
||||
}
|
||||
|
||||
func handleError(w http.ResponseWriter, r *http.Request, code int, err error) {
|
||||
errorMsg := fmt.Sprintf("Error - %s: %#v", err.Error(), r.RequestURI)
|
||||
http.Error(w, errorMsg, code)
|
||||
klog.Errorf(errorMsg)
|
||||
// handleError does the following:
|
||||
// a) it writes the specified error code, and msg to the ResponseWriter
|
||||
// object, it does not print the given innerErr into the ResponseWriter object.
|
||||
// b) additionally, it prints the given msg, and innerErr to the log with other
|
||||
// request scoped data that helps identify the given request.
|
||||
func handleError(w http.ResponseWriter, r *http.Request, code int, innerErr error, msg string) {
|
||||
http.Error(w, msg, code)
|
||||
klog.ErrorSDepth(1, innerErr, msg, "method", r.Method, "URI", r.RequestURI, "auditID", audit.GetAuditIDTruncated(r.Context()))
|
||||
}
|
||||
|
3
vendor/k8s.io/apiserver/pkg/endpoints/filters/webhook_duration.go
generated
vendored
3
vendor/k8s.io/apiserver/pkg/endpoints/filters/webhook_duration.go
generated
vendored
@ -18,7 +18,6 @@ package filters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -39,7 +38,7 @@ func WithLatencyTrackers(handler http.Handler) http.Handler {
|
||||
ctx := req.Context()
|
||||
requestInfo, ok := request.RequestInfoFrom(ctx)
|
||||
if !ok {
|
||||
handleError(w, req, http.StatusInternalServerError, fmt.Errorf("no RequestInfo found in context, handler chain must be wrong"))
|
||||
handleError(w, req, http.StatusInternalServerError, nil, "no RequestInfo found in context, handler chain must be wrong")
|
||||
return
|
||||
}
|
||||
|
||||
|
4
vendor/k8s.io/apiserver/pkg/endpoints/groupversion.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/endpoints/groupversion.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@ -107,7 +107,7 @@ type APIGroupVersion struct {
|
||||
// InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container.
|
||||
// It is expected that the provided path root prefix will serve all operations. Root MUST NOT end
|
||||
// in a slash.
|
||||
func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]apidiscoveryv2beta1.APIResourceDiscovery, []*storageversion.ResourceInfo, error) {
|
||||
func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]apidiscoveryv2.APIResourceDiscovery, []*storageversion.ResourceInfo, error) {
|
||||
prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)
|
||||
installer := &APIInstaller{
|
||||
group: g,
|
||||
|
2
vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/node.yaml
generated
vendored
2
vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/node.yaml
generated
vendored
@ -120,7 +120,7 @@ status:
|
||||
type: PIDPressure
|
||||
- lastHeartbeatTime: "2019-09-20T19:32:50Z"
|
||||
lastTransitionTime: "2019-07-09T16:17:49Z"
|
||||
message: kubelet is posting ready status. AppArmor enabled
|
||||
message: kubelet is posting ready status
|
||||
reason: KubeletReady
|
||||
status: "True"
|
||||
type: Ready
|
||||
|
32
vendor/k8s.io/apiserver/pkg/endpoints/handlers/get.go
generated
vendored
32
vendor/k8s.io/apiserver/pkg/endpoints/handlers/get.go
generated
vendored
@ -41,6 +41,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericfilters "k8s.io/apiserver/pkg/server/filters"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/tracing"
|
||||
"k8s.io/klog/v2"
|
||||
@ -259,16 +260,37 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope *RequestScope, forceWatc
|
||||
}
|
||||
klog.V(3).InfoS("Starting watch", "path", req.URL.Path, "resourceVersion", opts.ResourceVersion, "labels", opts.LabelSelector, "fields", opts.FieldSelector, "timeout", timeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
defer func() { cancel() }()
|
||||
watcher, err := rw.Watch(ctx, &opts)
|
||||
if err != nil {
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
}
|
||||
requestInfo, _ := request.RequestInfoFrom(ctx)
|
||||
metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() {
|
||||
serveWatch(watcher, scope, outputMediaType, req, w, timeout, metrics.CleanListScope(ctx, &opts))
|
||||
})
|
||||
handler, err := serveWatchHandler(watcher, scope, outputMediaType, req, w, timeout, metrics.CleanListScope(ctx, &opts))
|
||||
if err != nil {
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
}
|
||||
// Invalidate cancel() to defer until serve() is complete.
|
||||
deferredCancel := cancel
|
||||
cancel = func() {}
|
||||
|
||||
serve := func() {
|
||||
defer deferredCancel()
|
||||
requestInfo, _ := request.RequestInfoFrom(ctx)
|
||||
metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() {
|
||||
defer watcher.Stop()
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
}
|
||||
|
||||
// Run watch serving in a separate goroutine to allow freeing current stack memory
|
||||
t := genericfilters.TaskFrom(req.Context())
|
||||
if t != nil {
|
||||
t.Func = serve
|
||||
} else {
|
||||
serve()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
141
vendor/k8s.io/apiserver/pkg/endpoints/handlers/watch.go
generated
vendored
141
vendor/k8s.io/apiserver/pkg/endpoints/handlers/watch.go
generated
vendored
@ -17,8 +17,9 @@ limitations under the License.
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -61,30 +62,25 @@ func (w *realTimeoutFactory) TimeoutCh() (<-chan time.Time, func() bool) {
|
||||
return t.C, t.Stop
|
||||
}
|
||||
|
||||
// serveWatch will serve a watch response.
|
||||
// serveWatchHandler returns a handle to serve a watch response.
|
||||
// TODO: the functionality in this method and in WatchServer.Serve is not cleanly decoupled.
|
||||
func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions negotiation.MediaTypeOptions, req *http.Request, w http.ResponseWriter, timeout time.Duration, metricsScope string) {
|
||||
defer watcher.Stop()
|
||||
|
||||
func serveWatchHandler(watcher watch.Interface, scope *RequestScope, mediaTypeOptions negotiation.MediaTypeOptions, req *http.Request, w http.ResponseWriter, timeout time.Duration, metricsScope string) (http.Handler, error) {
|
||||
options, err := optionsForTransform(mediaTypeOptions, req)
|
||||
if err != nil {
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// negotiate for the stream serializer from the scope's serializer
|
||||
serializer, err := negotiation.NegotiateOutputMediaTypeStream(req, scope.Serializer, scope)
|
||||
if err != nil {
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
framer := serializer.StreamSerializer.Framer
|
||||
streamSerializer := serializer.StreamSerializer.Serializer
|
||||
encoder := scope.Serializer.EncoderForVersion(streamSerializer, scope.Kind.GroupVersion())
|
||||
useTextFraming := serializer.EncodesAsText
|
||||
if framer == nil {
|
||||
scope.err(fmt.Errorf("no framer defined for %q available for embedded encoding", serializer.MediaType), w, req)
|
||||
return
|
||||
return nil, fmt.Errorf("no framer defined for %q available for embedded encoding", serializer.MediaType)
|
||||
}
|
||||
// TODO: next step, get back mediaTypeOptions from negotiate and return the exact value here
|
||||
mediaType := serializer.MediaType
|
||||
@ -100,8 +96,7 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
|
||||
if transform {
|
||||
info, ok := runtime.SerializerInfoForMediaType(contentSerializer.SupportedMediaTypes(), serializer.MediaType)
|
||||
if !ok {
|
||||
scope.err(fmt.Errorf("no encoder for %q exists in the requested target %#v", serializer.MediaType, contentSerializer), w, req)
|
||||
return
|
||||
return nil, fmt.Errorf("no encoder for %q exists in the requested target %#v", serializer.MediaType, contentSerializer)
|
||||
}
|
||||
embeddedEncoder = contentSerializer.EncoderForVersion(info.Serializer, contentKind.GroupVersion())
|
||||
} else {
|
||||
@ -114,7 +109,6 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
|
||||
// don't put the allocator inside the embeddedEncodeFn as that would allocate memory on every call.
|
||||
// instead, we allocate the buffer for the entire watch session and release it when we close the connection.
|
||||
memoryAllocator = runtime.AllocatorPool.Get().(*runtime.Allocator)
|
||||
defer runtime.AllocatorPool.Put(memoryAllocator)
|
||||
embeddedEncoder = runtime.NewEncoderWithAllocator(encoderWithAllocator, memoryAllocator)
|
||||
}
|
||||
var tableOptions *metav1.TableOptions
|
||||
@ -122,8 +116,7 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
|
||||
if passedOptions, ok := options.(*metav1.TableOptions); ok {
|
||||
tableOptions = passedOptions
|
||||
} else {
|
||||
scope.err(fmt.Errorf("unexpected options type: %T", options), w, req)
|
||||
return
|
||||
return nil, fmt.Errorf("unexpected options type: %T", options)
|
||||
}
|
||||
}
|
||||
embeddedEncoder = newWatchEmbeddedEncoder(ctx, embeddedEncoder, mediaTypeOptions.Convert, tableOptions, scope)
|
||||
@ -133,7 +126,6 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
|
||||
// don't put the allocator inside the embeddedEncodeFn as that would allocate memory on every call.
|
||||
// instead, we allocate the buffer for the entire watch session and release it when we close the connection.
|
||||
memoryAllocator = runtime.AllocatorPool.Get().(*runtime.Allocator)
|
||||
defer runtime.AllocatorPool.Put(memoryAllocator)
|
||||
}
|
||||
encoder = runtime.NewEncoderWithAllocator(encoderWithAllocator, memoryAllocator)
|
||||
}
|
||||
@ -153,13 +145,18 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
|
||||
Encoder: encoder,
|
||||
EmbeddedEncoder: embeddedEncoder,
|
||||
|
||||
MemoryAllocator: memoryAllocator,
|
||||
TimeoutFactory: &realTimeoutFactory{timeout},
|
||||
ServerShuttingDownCh: serverShuttingDownCh,
|
||||
|
||||
metricsScope: metricsScope,
|
||||
}
|
||||
|
||||
server.ServeHTTP(w, req)
|
||||
if wsstream.IsWebSocketRequest(req) {
|
||||
w.Header().Set("Content-Type", server.MediaType)
|
||||
return websocket.Handler(server.HandleWS), nil
|
||||
}
|
||||
return http.HandlerFunc(server.HandleHTTP), nil
|
||||
}
|
||||
|
||||
// WatchServer serves a watch.Interface over a websocket or vanilla HTTP.
|
||||
@ -178,22 +175,21 @@ type WatchServer struct {
|
||||
// used to encode the nested object in the watch stream
|
||||
EmbeddedEncoder runtime.Encoder
|
||||
|
||||
MemoryAllocator runtime.MemoryAllocator
|
||||
TimeoutFactory TimeoutFactory
|
||||
ServerShuttingDownCh <-chan struct{}
|
||||
|
||||
metricsScope string
|
||||
}
|
||||
|
||||
// ServeHTTP serves a series of encoded events via HTTP with Transfer-Encoding: chunked
|
||||
// HandleHTTP serves a series of encoded events via HTTP with Transfer-Encoding: chunked.
|
||||
// or over a websocket connection.
|
||||
func (s *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
kind := s.Scope.Kind
|
||||
|
||||
if wsstream.IsWebSocketRequest(req) {
|
||||
w.Header().Set("Content-Type", s.MediaType)
|
||||
websocket.Handler(s.HandleWS).ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
func (s *WatchServer) HandleHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
if s.MemoryAllocator != nil {
|
||||
runtime.AllocatorPool.Put(s.MemoryAllocator)
|
||||
}
|
||||
}()
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
@ -222,6 +218,7 @@ func (s *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
flusher.Flush()
|
||||
|
||||
kind := s.Scope.Kind
|
||||
watchEncoder := newWatchEncoder(req.Context(), kind, s.EmbeddedEncoder, s.Encoder, framer)
|
||||
ch := s.Watching.ResultChan()
|
||||
done := req.Context().Done()
|
||||
@ -265,10 +262,19 @@ func (s *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// HandleWS implements a websocket handler.
|
||||
// HandleWS serves a series of encoded events over a websocket connection.
|
||||
func (s *WatchServer) HandleWS(ws *websocket.Conn) {
|
||||
defer func() {
|
||||
if s.MemoryAllocator != nil {
|
||||
runtime.AllocatorPool.Put(s.MemoryAllocator)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ws.Close()
|
||||
done := make(chan struct{})
|
||||
// ensure the connection times out
|
||||
timeoutCh, cleanup := s.TimeoutFactory.TimeoutCh()
|
||||
defer cleanup()
|
||||
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
@ -279,67 +285,62 @@ func (s *WatchServer) HandleWS(ws *websocket.Conn) {
|
||||
close(done)
|
||||
}()
|
||||
|
||||
var unknown runtime.Unknown
|
||||
internalEvent := &metav1.InternalEvent{}
|
||||
buf := &bytes.Buffer{}
|
||||
streamBuf := &bytes.Buffer{}
|
||||
framer := newWebsocketFramer(ws, s.UseTextFraming)
|
||||
|
||||
kind := s.Scope.Kind
|
||||
watchEncoder := newWatchEncoder(context.TODO(), kind, s.EmbeddedEncoder, s.Encoder, framer)
|
||||
ch := s.Watching.ResultChan()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
case <-timeoutCh:
|
||||
return
|
||||
case event, ok := <-ch:
|
||||
if !ok {
|
||||
// End of results.
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.EmbeddedEncoder.Encode(event.Object, buf); err != nil {
|
||||
// unexpected error
|
||||
utilruntime.HandleError(fmt.Errorf("unable to encode watch object %T: %v", event.Object, err))
|
||||
return
|
||||
}
|
||||
|
||||
// ContentType is not required here because we are defaulting to the serializer
|
||||
// type
|
||||
unknown.Raw = buf.Bytes()
|
||||
event.Object = &unknown
|
||||
|
||||
// the internal event will be versioned by the encoder
|
||||
// create the external type directly and encode it. Clients will only recognize the serialization we provide.
|
||||
// The internal event is being reused, not reallocated so its just a few extra assignments to do it this way
|
||||
// and we get the benefit of using conversion functions which already have to stay in sync
|
||||
outEvent := &metav1.WatchEvent{}
|
||||
*internalEvent = metav1.InternalEvent(event)
|
||||
err := metav1.Convert_v1_InternalEvent_To_v1_WatchEvent(internalEvent, outEvent, nil)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to convert watch object: %v", err))
|
||||
if err := watchEncoder.Encode(event); err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
// client disconnect.
|
||||
return
|
||||
}
|
||||
if err := s.Encoder.Encode(outEvent, streamBuf); err != nil {
|
||||
// encoding error
|
||||
utilruntime.HandleError(fmt.Errorf("unable to encode event: %v", err))
|
||||
return
|
||||
}
|
||||
if s.UseTextFraming {
|
||||
if err := websocket.Message.Send(ws, streamBuf.String()); err != nil {
|
||||
// Client disconnect.
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := websocket.Message.Send(ws, streamBuf.Bytes()); err != nil {
|
||||
// Client disconnect.
|
||||
return
|
||||
}
|
||||
}
|
||||
buf.Reset()
|
||||
streamBuf.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type websocketFramer struct {
|
||||
ws *websocket.Conn
|
||||
useTextFraming bool
|
||||
}
|
||||
|
||||
func newWebsocketFramer(ws *websocket.Conn, useTextFraming bool) io.Writer {
|
||||
return &websocketFramer{
|
||||
ws: ws,
|
||||
useTextFraming: useTextFraming,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *websocketFramer) Write(p []byte) (int, error) {
|
||||
if w.useTextFraming {
|
||||
// bytes.Buffer::String() has a special handling of nil value, but given
|
||||
// we're writing serialized watch events, this will never happen here.
|
||||
if err := websocket.Message.Send(w.ws, string(p)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
if err := websocket.Message.Send(w.ws, p); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
var _ io.Writer = &websocketFramer{}
|
||||
|
||||
func shouldRecordWatchListLatency(event watch.Event) bool {
|
||||
if event.Type != watch.Bookmark || !utilfeature.DefaultFeatureGate.Enabled(features.WatchList) {
|
||||
return false
|
||||
|
36
vendor/k8s.io/apiserver/pkg/endpoints/installer.go
generated
vendored
36
vendor/k8s.io/apiserver/pkg/endpoints/installer.go
generated
vendored
@ -26,7 +26,9 @@ import (
|
||||
"unicode"
|
||||
|
||||
restful "github.com/emicklei/go-restful/v3"
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -46,12 +48,12 @@ import (
|
||||
"k8s.io/apiserver/pkg/storageversion"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
versioninfo "k8s.io/component-base/version"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
const (
|
||||
ROUTE_META_GVK = "x-kubernetes-group-version-kind"
|
||||
ROUTE_META_ACTION = "x-kubernetes-action"
|
||||
RouteMetaGVK = "x-kubernetes-group-version-kind"
|
||||
RouteMetaSelectableFields = "x-kubernetes-selectable-fields"
|
||||
RouteMetaAction = "x-kubernetes-action"
|
||||
)
|
||||
|
||||
type APIInstaller struct {
|
||||
@ -69,8 +71,8 @@ type action struct {
|
||||
AllNamespaces bool // true iff the action is namespaced but works on aggregate result for all namespaces
|
||||
}
|
||||
|
||||
func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscoveryv2beta1.APIResourceDiscovery, error) {
|
||||
var apiResourceList []apidiscoveryv2beta1.APIResourceDiscovery
|
||||
func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscoveryv2.APIResourceDiscovery, error) {
|
||||
var apiResourceList []apidiscoveryv2.APIResourceDiscovery
|
||||
parentResources := make(map[string]int)
|
||||
|
||||
// Loop through all top-level resources
|
||||
@ -80,14 +82,14 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
||||
continue
|
||||
}
|
||||
|
||||
var scope apidiscoveryv2beta1.ResourceScope
|
||||
var scope apidiscoveryv2.ResourceScope
|
||||
if r.Namespaced {
|
||||
scope = apidiscoveryv2beta1.ScopeNamespace
|
||||
scope = apidiscoveryv2.ScopeNamespace
|
||||
} else {
|
||||
scope = apidiscoveryv2beta1.ScopeCluster
|
||||
scope = apidiscoveryv2.ScopeCluster
|
||||
}
|
||||
|
||||
resource := apidiscoveryv2beta1.APIResourceDiscovery{
|
||||
resource := apidiscoveryv2.APIResourceDiscovery{
|
||||
Resource: r.Name,
|
||||
Scope: scope,
|
||||
ResponseKind: &metav1.GroupVersionKind{
|
||||
@ -114,17 +116,17 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
||||
continue
|
||||
}
|
||||
|
||||
var scope apidiscoveryv2beta1.ResourceScope
|
||||
var scope apidiscoveryv2.ResourceScope
|
||||
if r.Namespaced {
|
||||
scope = apidiscoveryv2beta1.ScopeNamespace
|
||||
scope = apidiscoveryv2.ScopeNamespace
|
||||
} else {
|
||||
scope = apidiscoveryv2beta1.ScopeCluster
|
||||
scope = apidiscoveryv2.ScopeCluster
|
||||
}
|
||||
|
||||
parentidx, exists := parentResources[split[0]]
|
||||
if !exists {
|
||||
// If a subresource exists without a parent, create a parent
|
||||
apiResourceList = append(apiResourceList, apidiscoveryv2beta1.APIResourceDiscovery{
|
||||
apiResourceList = append(apiResourceList, apidiscoveryv2.APIResourceDiscovery{
|
||||
Resource: split[0],
|
||||
Scope: scope,
|
||||
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
||||
@ -140,7 +142,7 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
||||
//
|
||||
}
|
||||
|
||||
subresource := apidiscoveryv2beta1.APISubresourceDiscovery{
|
||||
subresource := apidiscoveryv2.APISubresourceDiscovery{
|
||||
Subresource: split[1],
|
||||
Verbs: r.Verbs,
|
||||
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
||||
@ -1059,12 +1061,12 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
return nil, nil, fmt.Errorf("unrecognized action verb: %s", action.Verb)
|
||||
}
|
||||
for _, route := range routes {
|
||||
route.Metadata(ROUTE_META_GVK, metav1.GroupVersionKind{
|
||||
route.Metadata(RouteMetaGVK, metav1.GroupVersionKind{
|
||||
Group: reqScope.Kind.Group,
|
||||
Version: reqScope.Kind.Version,
|
||||
Kind: reqScope.Kind.Kind,
|
||||
})
|
||||
route.Metadata(ROUTE_META_ACTION, strings.ToLower(action.Verb))
|
||||
route.Metadata(RouteMetaAction, strings.ToLower(action.Verb))
|
||||
ws.Route(route)
|
||||
}
|
||||
// Note: update GetAuthorizerAttributes() when adding a custom handler.
|
||||
|
23
vendor/k8s.io/apiserver/pkg/endpoints/request/webhook_duration.go
generated
vendored
23
vendor/k8s.io/apiserver/pkg/endpoints/request/webhook_duration.go
generated
vendored
@ -152,6 +152,13 @@ type LatencyTrackers struct {
|
||||
// The Write method can be invoked multiple times, so we use a
|
||||
// latency tracker that sums up the duration from each call.
|
||||
ResponseWriteTracker DurationTracker
|
||||
|
||||
// DecodeTracker is used to track latency incurred inside the function
|
||||
// that takes an object returned from the underlying storage layer
|
||||
// (etcd) and performs decoding of the response object.
|
||||
// When called multiple times, the latency incurred inside to
|
||||
// decode func each time will be summed up.
|
||||
DecodeTracker DurationTracker
|
||||
}
|
||||
|
||||
type latencyTrackersKeyType int
|
||||
@ -177,6 +184,7 @@ func WithLatencyTrackersAndCustomClock(parent context.Context, c clock.Clock) co
|
||||
TransformTracker: newSumLatencyTracker(c),
|
||||
SerializationTracker: newSumLatencyTracker(c),
|
||||
ResponseWriteTracker: newSumLatencyTracker(c),
|
||||
DecodeTracker: newSumLatencyTracker(c),
|
||||
})
|
||||
}
|
||||
|
||||
@ -243,6 +251,17 @@ func TrackAPFQueueWaitLatency(ctx context.Context, d time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
// TrackDecodeLatency is used to track latency incurred inside the function
|
||||
// that takes an object returned from the underlying storage layer
|
||||
// (etcd) and performs decoding of the response object.
|
||||
// When called multiple times, the latency incurred inside to
|
||||
// decode func each time will be summed up.
|
||||
func TrackDecodeLatency(ctx context.Context, d time.Duration) {
|
||||
if tracker, ok := LatencyTrackersFrom(ctx); ok {
|
||||
tracker.DecodeTracker.TrackDuration(d)
|
||||
}
|
||||
}
|
||||
|
||||
// AuditAnnotationsFromLatencyTrackers will inspect each latency tracker
|
||||
// associated with the request context and return a set of audit
|
||||
// annotations that can be added to the API audit entry.
|
||||
@ -254,6 +273,7 @@ func AuditAnnotationsFromLatencyTrackers(ctx context.Context) map[string]string
|
||||
responseWriteLatencyKey = "apiserver.latency.k8s.io/response-write"
|
||||
mutatingWebhookLatencyKey = "apiserver.latency.k8s.io/mutating-webhook"
|
||||
validatingWebhookLatencyKey = "apiserver.latency.k8s.io/validating-webhook"
|
||||
decodeLatencyKey = "apiserver.latency.k8s.io/decode-response-object"
|
||||
)
|
||||
|
||||
tracker, ok := LatencyTrackersFrom(ctx)
|
||||
@ -280,6 +300,9 @@ func AuditAnnotationsFromLatencyTrackers(ctx context.Context) map[string]string
|
||||
if latency := tracker.ValidatingWebhookTracker.GetLatency(); latency != 0 {
|
||||
annotations[validatingWebhookLatencyKey] = latency.String()
|
||||
}
|
||||
if latency := tracker.DecodeTracker.GetLatency(); latency != 0 {
|
||||
annotations[decodeLatencyKey] = latency.String()
|
||||
}
|
||||
|
||||
return annotations
|
||||
}
|
||||
|
59
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
59
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
@ -38,6 +38,7 @@ const (
|
||||
// owner: @ivelichkovich, @tallclair
|
||||
// alpha: v1.27
|
||||
// beta: v1.28
|
||||
// stable: v1.30
|
||||
// kep: https://kep.k8s.io/3716
|
||||
//
|
||||
// Enables usage of MatchConditions fields to use CEL expressions for matching on admission webhooks
|
||||
@ -46,6 +47,7 @@ const (
|
||||
// owner: @jefftree @alexzielenski
|
||||
// alpha: v1.26
|
||||
// beta: v1.27
|
||||
// stable: v1.30
|
||||
//
|
||||
// Enables an single HTTP endpoint /discovery/<version> which supports native HTTP
|
||||
// caching with ETags containing all APIResources known to the apiserver.
|
||||
@ -90,10 +92,19 @@ const (
|
||||
// Add support for distributed tracing in the API Server
|
||||
APIServerTracing featuregate.Feature = "APIServerTracing"
|
||||
|
||||
// owner: @linxiulei
|
||||
// beta: v1.30
|
||||
//
|
||||
// Enables serving watch requests in separate goroutines.
|
||||
APIServingWithRoutine featuregate.Feature = "APIServingWithRoutine"
|
||||
|
||||
// owner: @cici37 @jpbetz
|
||||
// kep: http://kep.k8s.io/3488
|
||||
// alpha: v1.26
|
||||
// beta: v1.28
|
||||
// stable: v1.30
|
||||
//
|
||||
// Note: the feature gate can be removed in 1.32
|
||||
// Enables expression validation in Admission Control
|
||||
ValidatingAdmissionPolicy featuregate.Feature = "ValidatingAdmissionPolicy"
|
||||
|
||||
@ -137,6 +148,13 @@ const (
|
||||
// Enables the use of derived encryption keys with KMS v2.
|
||||
KMSv2KDF featuregate.Feature = "KMSv2KDF"
|
||||
|
||||
// owner: @alexzielenski, @cici37, @jiahuif
|
||||
// kep: https://kep.k8s.io/3962
|
||||
// alpha: v1.30
|
||||
//
|
||||
// Enables the MutatingAdmissionPolicy in Admission Chain
|
||||
MutatingAdmissionPolicy featuregate.Feature = "MutatingAdmissionPolicy"
|
||||
|
||||
// owner: @jiahuif
|
||||
// kep: https://kep.k8s.io/2887
|
||||
// alpha: v1.23
|
||||
@ -155,14 +173,6 @@ const (
|
||||
// to a chunking list request.
|
||||
RemainingItemCount featuregate.Feature = "RemainingItemCount"
|
||||
|
||||
// owner: @wojtek-t
|
||||
// alpha: v1.16
|
||||
// beta: v1.20
|
||||
// GA: v1.24
|
||||
//
|
||||
// Deprecates and removes SelfLink from ObjectMeta and ListMeta.
|
||||
RemoveSelfLink featuregate.Feature = "RemoveSelfLink"
|
||||
|
||||
// owner: @serathius
|
||||
// beta: v1.30
|
||||
//
|
||||
@ -204,6 +214,12 @@ const (
|
||||
// clients.
|
||||
UnauthenticatedHTTP2DOSMitigation featuregate.Feature = "UnauthenticatedHTTP2DOSMitigation"
|
||||
|
||||
// owner: @jpbetz
|
||||
// alpha: v1.30
|
||||
// Resource create requests using generateName are retried automatically by the apiserver
|
||||
// if the generated name conflicts with an existing resource name, up to a maximum number of 7 retries.
|
||||
RetryGenerateName featuregate.Feature = "RetryGenerateName"
|
||||
|
||||
// owner: @caesarxuchao @roycaihw
|
||||
// alpha: v1.20
|
||||
//
|
||||
@ -221,6 +237,7 @@ const (
|
||||
// owner: @aramase, @enj, @nabokihms
|
||||
// kep: https://kep.k8s.io/3331
|
||||
// alpha: v1.29
|
||||
// beta: v1.30
|
||||
//
|
||||
// Enables Structured Authentication Configuration
|
||||
StructuredAuthenticationConfiguration featuregate.Feature = "StructuredAuthenticationConfiguration"
|
||||
@ -228,6 +245,7 @@ const (
|
||||
// owner: @palnabarun
|
||||
// kep: https://kep.k8s.io/3221
|
||||
// alpha: v1.29
|
||||
// beta: v1.30
|
||||
//
|
||||
// Enables Structured Authorization Configuration
|
||||
StructuredAuthorizationConfiguration featuregate.Feature = "StructuredAuthorizationConfiguration"
|
||||
@ -240,6 +258,12 @@ const (
|
||||
// Enables support for watch bookmark events.
|
||||
WatchBookmark featuregate.Feature = "WatchBookmark"
|
||||
|
||||
// owner: @serathius
|
||||
// beta: 1.30
|
||||
// Enables watches without resourceVersion to be served from storage.
|
||||
// Used to prevent https://github.com/kubernetes/kubernetes/issues/123072 until etcd fixes the issue.
|
||||
WatchFromStorageWithoutResourceVersion featuregate.Feature = "WatchFromStorageWithoutResourceVersion"
|
||||
|
||||
// owner: @vinaykul
|
||||
// kep: http://kep.k8s.io/1287
|
||||
// alpha: v1.27
|
||||
@ -262,6 +286,7 @@ const (
|
||||
|
||||
// owner: @tkashem
|
||||
// beta: v1.29
|
||||
// GA: v1.30
|
||||
//
|
||||
// Allow Priority & Fairness in the API server to use a zero value for
|
||||
// the 'nominalConcurrencyShares' field of the 'limited' section of a
|
||||
@ -278,9 +303,9 @@ func init() {
|
||||
// available throughout Kubernetes binaries.
|
||||
var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
|
||||
AggregatedDiscoveryEndpoint: {Default: true, PreRelease: featuregate.Beta},
|
||||
AggregatedDiscoveryEndpoint: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
|
||||
|
||||
AdmissionWebhookMatchConditions: {Default: true, PreRelease: featuregate.Beta},
|
||||
AdmissionWebhookMatchConditions: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33
|
||||
|
||||
APIListChunking: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
|
||||
|
||||
@ -292,7 +317,9 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
APIServerTracing: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
ValidatingAdmissionPolicy: {Default: false, PreRelease: featuregate.Beta},
|
||||
APIServingWithRoutine: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
ValidatingAdmissionPolicy: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
|
||||
|
||||
CustomResourceValidationExpressions: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.31
|
||||
|
||||
@ -308,7 +335,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
RemainingItemCount: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
|
||||
|
||||
RemoveSelfLink: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
RetryGenerateName: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
SeparateCacheWatchRPC: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
@ -320,19 +347,21 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
|
||||
StorageVersionHash: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
StructuredAuthenticationConfiguration: {Default: false, PreRelease: featuregate.Alpha},
|
||||
StructuredAuthenticationConfiguration: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
StructuredAuthorizationConfiguration: {Default: false, PreRelease: featuregate.Alpha},
|
||||
StructuredAuthorizationConfiguration: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
UnauthenticatedHTTP2DOSMitigation: {Default: true, PreRelease: featuregate.Beta},
|
||||
|
||||
WatchBookmark: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
|
||||
WatchFromStorageWithoutResourceVersion: {Default: false, PreRelease: featuregate.Beta},
|
||||
|
||||
InPlacePodVerticalScaling: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
WatchList: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
ConsistentListFromCache: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
ZeroLimitedNominalConcurrencyShares: {Default: false, PreRelease: featuregate.Beta},
|
||||
ZeroLimitedNominalConcurrencyShares: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
|
||||
}
|
||||
|
48
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
48
vendor/k8s.io/apiserver/pkg/registry/generic/registry/store.go
generated
vendored
@ -23,6 +23,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/validation"
|
||||
@ -40,15 +42,16 @@ import (
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
storeerr "k8s.io/apiserver/pkg/storage/errors"
|
||||
"k8s.io/apiserver/pkg/storage/etcd3/metrics"
|
||||
"k8s.io/apiserver/pkg/util/dryrun"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
@ -392,11 +395,54 @@ func (e *Store) ListPredicate(ctx context.Context, p storage.SelectionPredicate,
|
||||
// finishNothing is a do-nothing FinishFunc.
|
||||
func finishNothing(context.Context, bool) {}
|
||||
|
||||
// maxNameGenerationCreateAttempts is the maximum number of
|
||||
// times create will be attempted when generateName is used
|
||||
// and create attempts fails due to name conflict errors.
|
||||
// Each attempt uses a newly randomly generated name.
|
||||
// 8 was selected as the max because it is sufficient to generate
|
||||
// 1 million names per generateName prefix, with only a 0.1%
|
||||
// probability of any generated name conflicting with existing names.
|
||||
// Without retry, a 0.1% probability occurs at ~500
|
||||
// generated names and a 50% probability occurs at ~4500
|
||||
// generated names.
|
||||
const maxNameGenerationCreateAttempts = 8
|
||||
|
||||
// Create inserts a new item according to the unique key from the object.
|
||||
// Note that registries may mutate the input object (e.g. in the strategy
|
||||
// hooks). Tests which call this might want to call DeepCopy if they expect to
|
||||
// be able to examine the input and output objects for differences.
|
||||
func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.RetryGenerateName) && needsNameGeneration(obj) {
|
||||
return e.createWithGenerateNameRetry(ctx, obj, createValidation, options)
|
||||
}
|
||||
|
||||
return e.create(ctx, obj, createValidation, options)
|
||||
}
|
||||
|
||||
// needsNameGeneration returns true if the obj has a generateName but no name.
|
||||
func needsNameGeneration(obj runtime.Object) bool {
|
||||
if objectMeta, err := meta.Accessor(obj); err == nil {
|
||||
if len(objectMeta.GetGenerateName()) > 0 && len(objectMeta.GetName()) == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// createWithGenerateNameRetry attempts to create obj up to maxNameGenerationCreateAttempts
|
||||
// when create fails due to a name conflict error. Each attempt randomly generates a new
|
||||
// name based on generateName.
|
||||
func (e *Store) createWithGenerateNameRetry(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (resultObj runtime.Object, err error) {
|
||||
for i := 0; i < maxNameGenerationCreateAttempts; i++ {
|
||||
resultObj, err = e.create(ctx, obj.DeepCopyObject(), createValidation, options)
|
||||
if err == nil || !apierrors.IsAlreadyExists(err) {
|
||||
return resultObj, err
|
||||
}
|
||||
}
|
||||
return resultObj, err
|
||||
}
|
||||
|
||||
func (e *Store) create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
var finishCreate FinishFunc = finishNothing
|
||||
|
||||
// Init metadata as early as possible.
|
||||
|
23
vendor/k8s.io/apiserver/pkg/server/config.go
generated
vendored
23
vendor/k8s.io/apiserver/pkg/server/config.go
generated
vendored
@ -668,6 +668,11 @@ func (c *Config) DrainedNotify() <-chan struct{} {
|
||||
return c.lifecycleSignals.InFlightRequestsDrained.Signaled()
|
||||
}
|
||||
|
||||
// ShutdownInitiated returns a lifecycle signal of apiserver shutdown having been initiated.
|
||||
func (c *Config) ShutdownInitiatedNotify() <-chan struct{} {
|
||||
return c.lifecycleSignals.ShutdownInitiated.Signaled()
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data and can be derived
|
||||
// from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver.
|
||||
func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
|
||||
@ -799,15 +804,14 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
|
||||
preShutdownHooks: map[string]preShutdownHookEntry{},
|
||||
disabledPostStartHooks: c.DisabledPostStartHooks,
|
||||
|
||||
healthzChecks: c.HealthzChecks,
|
||||
livezChecks: c.LivezChecks,
|
||||
readyzChecks: c.ReadyzChecks,
|
||||
healthzRegistry: healthCheckRegistry{path: "/healthz", checks: c.HealthzChecks},
|
||||
livezRegistry: healthCheckRegistry{path: "/livez", checks: c.LivezChecks, clock: clock.RealClock{}},
|
||||
readyzRegistry: healthCheckRegistry{path: "/readyz", checks: c.ReadyzChecks},
|
||||
livezGracePeriod: c.LivezGracePeriod,
|
||||
|
||||
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer),
|
||||
|
||||
maxRequestBodyBytes: c.MaxRequestBodyBytes,
|
||||
livezClock: clock.RealClock{},
|
||||
|
||||
lifecycleSignals: c.lifecycleSignals,
|
||||
ShutdownSendRetryAfter: c.ShutdownSendRetryAfter,
|
||||
@ -1012,6 +1016,10 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
||||
|
||||
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
|
||||
|
||||
// WithWarningRecorder must be wrapped by the timeout handler
|
||||
// to make the addition of warning headers threadsafe
|
||||
handler = genericapifilters.WithWarningRecorder(handler)
|
||||
|
||||
// WithTimeoutForNonLongRunningRequests will call the rest of the request handling in a go-routine with the
|
||||
// context with deadline. The go-routine can keep running, while the timeout logic will return a timeout to the client.
|
||||
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc)
|
||||
@ -1025,7 +1033,6 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
||||
if c.SecureServing != nil && !c.SecureServing.DisableHTTP2 && c.GoawayChance > 0 {
|
||||
handler = genericfilters.WithProbabilisticGoaway(handler, c.GoawayChance)
|
||||
}
|
||||
handler = genericapifilters.WithWarningRecorder(handler)
|
||||
handler = genericapifilters.WithCacheControl(handler)
|
||||
handler = genericfilters.WithHSTS(handler, c.HSTSDirectives)
|
||||
if c.ShutdownSendRetryAfter {
|
||||
@ -1036,6 +1043,12 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
||||
handler = genericapifilters.WithTracing(handler, c.TracerProvider)
|
||||
}
|
||||
handler = genericapifilters.WithLatencyTrackers(handler)
|
||||
// WithRoutine will execute future handlers in a separate goroutine and serving
|
||||
// handler in current goroutine to minimize the stack memory usage. It must be
|
||||
// after WithPanicRecover() to be protected from panics.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServingWithRoutine) {
|
||||
handler = genericfilters.WithRoutine(handler, c.LongRunningFunc)
|
||||
}
|
||||
handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver)
|
||||
handler = genericapifilters.WithRequestReceivedTimestamp(handler)
|
||||
handler = genericapifilters.WithMuxAndDiscoveryComplete(handler, c.lifecycleSignals.MuxAndDiscoveryComplete.Signaled())
|
||||
|
77
vendor/k8s.io/apiserver/pkg/server/filters/routine.go
generated
vendored
Normal file
77
vendor/k8s.io/apiserver/pkg/server/filters/routine.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
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 filters
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
type taskKeyType int
|
||||
|
||||
const taskKey taskKeyType = iota
|
||||
|
||||
type Task struct {
|
||||
Func func()
|
||||
}
|
||||
|
||||
func WithTask(parent context.Context, t *Task) context.Context {
|
||||
return request.WithValue(parent, taskKey, t)
|
||||
}
|
||||
|
||||
func TaskFrom(ctx context.Context) *Task {
|
||||
t, _ := ctx.Value(taskKey).(*Task)
|
||||
return t
|
||||
}
|
||||
|
||||
// WithRoutine returns an http.Handler that executes preparation of long running requests (i.e. watches)
|
||||
// in a separate Goroutine and then serves the long running request in the main Goroutine. Doing so allows
|
||||
// freeing stack memory used in preparation Goroutine for better memory efficiency.
|
||||
func WithRoutine(handler http.Handler, longRunning request.LongRunningRequestCheck) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
requestInfo, _ := request.RequestInfoFrom(ctx)
|
||||
if !longRunning(req, requestInfo) {
|
||||
handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
req = req.WithContext(WithTask(ctx, &Task{}))
|
||||
panicCh := make(chan any, 1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
panicCh <- r
|
||||
}
|
||||
close(panicCh)
|
||||
}()
|
||||
handler.ServeHTTP(w, req)
|
||||
}()
|
||||
|
||||
if p, ok := <-panicCh; ok {
|
||||
panic(p)
|
||||
}
|
||||
|
||||
ctx = req.Context()
|
||||
if t := TaskFrom(ctx); t != nil && t.Func != nil {
|
||||
t.Func()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
31
vendor/k8s.io/apiserver/pkg/server/genericapiserver.go
generated
vendored
31
vendor/k8s.io/apiserver/pkg/server/genericapiserver.go
generated
vendored
@ -29,7 +29,7 @@ import (
|
||||
systemd "github.com/coreos/go-systemd/v22/daemon"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -60,7 +60,6 @@ import (
|
||||
"k8s.io/kube-openapi/pkg/handler3"
|
||||
openapiutil "k8s.io/kube-openapi/pkg/util"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
// Info about an API group.
|
||||
@ -191,19 +190,11 @@ type GenericAPIServer struct {
|
||||
preShutdownHooksCalled bool
|
||||
|
||||
// healthz checks
|
||||
healthzLock sync.Mutex
|
||||
healthzChecks []healthz.HealthChecker
|
||||
healthzChecksInstalled bool
|
||||
// livez checks
|
||||
livezLock sync.Mutex
|
||||
livezChecks []healthz.HealthChecker
|
||||
livezChecksInstalled bool
|
||||
// readyz checks
|
||||
readyzLock sync.Mutex
|
||||
readyzChecks []healthz.HealthChecker
|
||||
readyzChecksInstalled bool
|
||||
livezGracePeriod time.Duration
|
||||
livezClock clock.Clock
|
||||
healthzRegistry healthCheckRegistry
|
||||
readyzRegistry healthCheckRegistry
|
||||
livezRegistry healthCheckRegistry
|
||||
|
||||
livezGracePeriod time.Duration
|
||||
|
||||
// auditing. The backend is started before the server starts listening.
|
||||
AuditBackend audit.Backend
|
||||
@ -330,7 +321,7 @@ func (s *GenericAPIServer) PreShutdownHooks() map[string]preShutdownHookEntry {
|
||||
return s.preShutdownHooks
|
||||
}
|
||||
func (s *GenericAPIServer) HealthzChecks() []healthz.HealthChecker {
|
||||
return s.healthzChecks
|
||||
return s.healthzRegistry.checks
|
||||
}
|
||||
func (s *GenericAPIServer) ListedPaths() []string {
|
||||
return s.listedPathProvider.ListedPaths()
|
||||
@ -765,8 +756,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
if apiPrefix == APIGroupPrefix {
|
||||
s.AggregatedDiscoveryGroupManager.AddGroupVersion(
|
||||
groupVersion.Group,
|
||||
apidiscoveryv2beta1.APIVersionDiscovery{
|
||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
||||
apidiscoveryv2.APIVersionDiscovery{
|
||||
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||
Version: groupVersion.Version,
|
||||
Resources: discoveryAPIResources,
|
||||
},
|
||||
@ -775,8 +766,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
// There is only one group version for legacy resources, priority can be defaulted to 0.
|
||||
s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion(
|
||||
groupVersion.Group,
|
||||
apidiscoveryv2beta1.APIVersionDiscovery{
|
||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
||||
apidiscoveryv2.APIVersionDiscovery{
|
||||
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||
Version: groupVersion.Version,
|
||||
Resources: discoveryAPIResources,
|
||||
},
|
||||
|
98
vendor/k8s.io/apiserver/pkg/server/healthz.go
generated
vendored
98
vendor/k8s.io/apiserver/pkg/server/healthz.go
generated
vendored
@ -19,12 +19,60 @@ package server
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
// healthMux is an interface describing the methods InstallHandler requires.
|
||||
type healthMux interface {
|
||||
Handle(pattern string, handler http.Handler)
|
||||
}
|
||||
|
||||
type healthCheckRegistry struct {
|
||||
path string
|
||||
lock sync.Mutex
|
||||
checks []healthz.HealthChecker
|
||||
checksInstalled bool
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
func (reg *healthCheckRegistry) addHealthChecks(checks ...healthz.HealthChecker) error {
|
||||
return reg.addDelayedHealthChecks(0, checks...)
|
||||
}
|
||||
|
||||
func (reg *healthCheckRegistry) addDelayedHealthChecks(delay time.Duration, checks ...healthz.HealthChecker) error {
|
||||
if delay > 0 && reg.clock == nil {
|
||||
return fmt.Errorf("nil clock in healthCheckRegistry for %s endpoint", reg.path)
|
||||
}
|
||||
reg.lock.Lock()
|
||||
defer reg.lock.Unlock()
|
||||
if reg.checksInstalled {
|
||||
return fmt.Errorf("unable to add because the %s endpoint has already been created", reg.path)
|
||||
}
|
||||
if delay > 0 {
|
||||
for _, check := range checks {
|
||||
reg.checks = append(reg.checks, delayedHealthCheck(check, reg.clock, delay))
|
||||
}
|
||||
} else {
|
||||
reg.checks = append(reg.checks, checks...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (reg *healthCheckRegistry) installHandler(mux healthMux) {
|
||||
reg.installHandlerWithHealthyFunc(mux, nil)
|
||||
}
|
||||
|
||||
func (reg *healthCheckRegistry) installHandlerWithHealthyFunc(mux healthMux, firstTimeHealthy func()) {
|
||||
reg.lock.Lock()
|
||||
defer reg.lock.Unlock()
|
||||
reg.checksInstalled = true
|
||||
healthz.InstallPathHandlerWithHealthyFunc(mux, reg.path, firstTimeHealthy, reg.checks...)
|
||||
}
|
||||
|
||||
// AddHealthChecks adds HealthCheck(s) to health endpoints (healthz, livez, readyz) but
|
||||
// configures the liveness grace period to be zero, which means we expect this health check
|
||||
// to immediately indicate that the apiserver is unhealthy.
|
||||
@ -47,40 +95,23 @@ func (s *GenericAPIServer) AddBootSequenceHealthChecks(checks ...healthz.HealthC
|
||||
// addHealthChecks adds health checks to healthz, livez, and readyz. The delay passed in will set
|
||||
// a corresponding grace period on livez.
|
||||
func (s *GenericAPIServer) addHealthChecks(livezGracePeriod time.Duration, checks ...healthz.HealthChecker) error {
|
||||
s.healthzLock.Lock()
|
||||
defer s.healthzLock.Unlock()
|
||||
if s.healthzChecksInstalled {
|
||||
return fmt.Errorf("unable to add because the healthz endpoint has already been created")
|
||||
}
|
||||
s.healthzChecks = append(s.healthzChecks, checks...)
|
||||
if err := s.AddLivezChecks(livezGracePeriod, checks...); err != nil {
|
||||
if err := s.healthzRegistry.addHealthChecks(checks...); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.AddReadyzChecks(checks...)
|
||||
if err := s.livezRegistry.addDelayedHealthChecks(livezGracePeriod, checks...); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.readyzRegistry.addHealthChecks(checks...)
|
||||
}
|
||||
|
||||
// AddReadyzChecks allows you to add a HealthCheck to readyz.
|
||||
func (s *GenericAPIServer) AddReadyzChecks(checks ...healthz.HealthChecker) error {
|
||||
s.readyzLock.Lock()
|
||||
defer s.readyzLock.Unlock()
|
||||
if s.readyzChecksInstalled {
|
||||
return fmt.Errorf("unable to add because the readyz endpoint has already been created")
|
||||
}
|
||||
s.readyzChecks = append(s.readyzChecks, checks...)
|
||||
return nil
|
||||
return s.readyzRegistry.addHealthChecks(checks...)
|
||||
}
|
||||
|
||||
// AddLivezChecks allows you to add a HealthCheck to livez.
|
||||
func (s *GenericAPIServer) AddLivezChecks(delay time.Duration, checks ...healthz.HealthChecker) error {
|
||||
s.livezLock.Lock()
|
||||
defer s.livezLock.Unlock()
|
||||
if s.livezChecksInstalled {
|
||||
return fmt.Errorf("unable to add because the livez endpoint has already been created")
|
||||
}
|
||||
for _, check := range checks {
|
||||
s.livezChecks = append(s.livezChecks, delayedHealthCheck(check, s.livezClock, delay))
|
||||
}
|
||||
return nil
|
||||
return s.livezRegistry.addDelayedHealthChecks(delay, checks...)
|
||||
}
|
||||
|
||||
// addReadyzShutdownCheck is a convenience function for adding a readyz shutdown check, so
|
||||
@ -92,29 +123,20 @@ func (s *GenericAPIServer) addReadyzShutdownCheck(stopCh <-chan struct{}) error
|
||||
|
||||
// installHealthz creates the healthz endpoint for this server
|
||||
func (s *GenericAPIServer) installHealthz() {
|
||||
s.healthzLock.Lock()
|
||||
defer s.healthzLock.Unlock()
|
||||
s.healthzChecksInstalled = true
|
||||
healthz.InstallHandler(s.Handler.NonGoRestfulMux, s.healthzChecks...)
|
||||
s.healthzRegistry.installHandler(s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
|
||||
// installReadyz creates the readyz endpoint for this server.
|
||||
func (s *GenericAPIServer) installReadyz() {
|
||||
s.readyzLock.Lock()
|
||||
defer s.readyzLock.Unlock()
|
||||
s.readyzChecksInstalled = true
|
||||
healthz.InstallReadyzHandlerWithHealthyFunc(s.Handler.NonGoRestfulMux, func() {
|
||||
// note: InstallReadyzHandlerWithHealthyFunc guarantees that this is called only once
|
||||
s.readyzRegistry.installHandlerWithHealthyFunc(s.Handler.NonGoRestfulMux, func() {
|
||||
// note: installHandlerWithHealthyFunc guarantees that this is called only once
|
||||
s.lifecycleSignals.HasBeenReady.Signal()
|
||||
}, s.readyzChecks...)
|
||||
})
|
||||
}
|
||||
|
||||
// installLivez creates the livez endpoint for this server.
|
||||
func (s *GenericAPIServer) installLivez() {
|
||||
s.livezLock.Lock()
|
||||
defer s.livezLock.Unlock()
|
||||
s.livezChecksInstalled = true
|
||||
healthz.InstallLivezHandler(s.Handler.NonGoRestfulMux, s.livezChecks...)
|
||||
s.livezRegistry.installHandler(s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
|
||||
// shutdownCheck fails if the embedded channel is closed. This is intended to allow for graceful shutdown sequences
|
||||
|
6
vendor/k8s.io/apiserver/pkg/server/healthz/healthz.go
generated
vendored
6
vendor/k8s.io/apiserver/pkg/server/healthz/healthz.go
generated
vendored
@ -142,12 +142,6 @@ func InstallReadyzHandler(mux mux, checks ...HealthChecker) {
|
||||
InstallPathHandler(mux, "/readyz", checks...)
|
||||
}
|
||||
|
||||
// InstallReadyzHandlerWithHealthyFunc is like InstallReadyzHandler, but in addition call firstTimeReady
|
||||
// the first time /readyz succeeds.
|
||||
func InstallReadyzHandlerWithHealthyFunc(mux mux, firstTimeReady func(), checks ...HealthChecker) {
|
||||
InstallPathHandlerWithHealthyFunc(mux, "/readyz", firstTimeReady, checks...)
|
||||
}
|
||||
|
||||
// InstallLivezHandler registers handlers for liveness checking on the path
|
||||
// "/livez" to mux. *All handlers* for mux must be specified in
|
||||
// exactly one call to InstallHandler. Calling InstallHandler more
|
||||
|
21
vendor/k8s.io/apiserver/pkg/server/options/admission.go
generated
vendored
21
vendor/k8s.io/apiserver/pkg/server/options/admission.go
generated
vendored
@ -19,26 +19,30 @@ package options
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy"
|
||||
validatingadmissionpolicy "k8s.io/apiserver/pkg/admission/plugin/policy/validating"
|
||||
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
|
||||
validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
|
||||
apiserverapi "k8s.io/apiserver/pkg/apis/apiserver"
|
||||
apiserverapiv1 "k8s.io/apiserver/pkg/apis/apiserver/v1"
|
||||
apiserverapiv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/restmapper"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
@ -143,11 +147,24 @@ func (a *AdmissionOptions) ApplyTo(
|
||||
return fmt.Errorf("failed to read plugin config: %v", err)
|
||||
}
|
||||
|
||||
discoveryClient := cacheddiscovery.NewMemCacheClient(kubeClient.Discovery())
|
||||
discoveryRESTMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient)
|
||||
genericInitializer := initializer.New(kubeClient, dynamicClient, informers, c.Authorization.Authorizer, features,
|
||||
c.DrainedNotify())
|
||||
c.DrainedNotify(), discoveryRESTMapper)
|
||||
initializersChain := admission.PluginInitializers{genericInitializer}
|
||||
initializersChain = append(initializersChain, pluginInitializers...)
|
||||
|
||||
admissionPostStartHook := func(context server.PostStartHookContext) error {
|
||||
discoveryRESTMapper.Reset()
|
||||
go utilwait.Until(discoveryRESTMapper.Reset, 30*time.Second, context.StopCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
err = c.AddPostStartHook("start-apiserver-admission-initializer", admissionPostStartHook)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add post start hook for policy admission: %w", err)
|
||||
}
|
||||
|
||||
admissionChain, err := a.Plugins.NewFromPlugins(pluginNames, pluginsConfigProvider, initializersChain, a.Decorators)
|
||||
if err != nil {
|
||||
return err
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user