mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 03:57:41 +00:00
update to inject only the list of excluded resources.
This commit is contained in:
parent
e257522889
commit
6b03166bed
@ -70,7 +70,7 @@ func (c *Config) New(proxyTransport *http.Transport, egressSelector *egressselec
|
||||
cloudConfig,
|
||||
discoveryRESTMapper,
|
||||
quotainstall.NewQuotaConfigurationForAdmission(),
|
||||
exclusion.NewFilter(),
|
||||
exclusion.Excluded(),
|
||||
)
|
||||
|
||||
admissionPostStartHook := func(context genericapiserver.PostStartHookContext) error {
|
||||
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
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 exclusion
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/resourcefilter"
|
||||
)
|
||||
|
||||
// NewFilter creates a resource filter with the built-in exclusion list.
|
||||
func NewFilter() resourcefilter.Interface {
|
||||
return &filter{excluded: sets.New[schema.GroupResource](excluded...)}
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
excluded sets.Set[schema.GroupResource]
|
||||
}
|
||||
|
||||
func (f *filter) ShouldHandle(a admission.Attributes) bool {
|
||||
gvr := a.GetResource()
|
||||
// ignore the version for the decision-making
|
||||
// because putting different versions into different category
|
||||
// is almost always a mistake.
|
||||
gr := gvr.GroupResource()
|
||||
return !f.excluded.Has(gr)
|
||||
}
|
@ -18,9 +18,9 @@ package admission
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/admission/resourcefilter"
|
||||
quota "k8s.io/apiserver/pkg/quota/v1"
|
||||
)
|
||||
|
||||
@ -33,10 +33,10 @@ type WantsCloudConfig interface {
|
||||
|
||||
// PluginInitializer is used for initialization of the Kubernetes specific admission plugins.
|
||||
type PluginInitializer struct {
|
||||
cloudConfig []byte
|
||||
restMapper meta.RESTMapper
|
||||
quotaConfiguration quota.Configuration
|
||||
resourceFilter resourcefilter.Interface
|
||||
cloudConfig []byte
|
||||
restMapper meta.RESTMapper
|
||||
quotaConfiguration quota.Configuration
|
||||
excludedAdmissionResources []schema.GroupResource
|
||||
}
|
||||
|
||||
var _ admission.PluginInitializer = &PluginInitializer{}
|
||||
@ -48,13 +48,13 @@ func NewPluginInitializer(
|
||||
cloudConfig []byte,
|
||||
restMapper meta.RESTMapper,
|
||||
quotaConfiguration quota.Configuration,
|
||||
resourceFilter resourcefilter.Interface,
|
||||
excludedAdmissionResources []schema.GroupResource,
|
||||
) *PluginInitializer {
|
||||
return &PluginInitializer{
|
||||
cloudConfig: cloudConfig,
|
||||
restMapper: restMapper,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
resourceFilter: resourceFilter,
|
||||
cloudConfig: cloudConfig,
|
||||
restMapper: restMapper,
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
excludedAdmissionResources: excludedAdmissionResources,
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
|
||||
wants.SetQuotaConfiguration(i.quotaConfiguration)
|
||||
}
|
||||
|
||||
if wants, ok := plugin.(initializer.WantsResourceFilter); ok {
|
||||
wants.SetResourceFilter(i.resourceFilter)
|
||||
if wants, ok := plugin.(initializer.WantsExcludedAdmissionResources); ok {
|
||||
wants.SetExcludedAdmissionResources(i.excludedAdmissionResources)
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package initializer
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/resourcefilter"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/cel/openapi/resolver"
|
||||
quota "k8s.io/apiserver/pkg/quota/v1"
|
||||
@ -91,9 +91,9 @@ type WantsSchemaResolver interface {
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
||||
// WantsResourceFilter defines a function which sets the ResourceFilter for
|
||||
// an admission plugin that needs it.
|
||||
type WantsResourceFilter interface {
|
||||
SetResourceFilter(filter resourcefilter.Interface)
|
||||
// WantsExcludedAdmissionResources defines a function which sets the ExcludedAdmissionResources
|
||||
// for an admission plugin that needs it.
|
||||
type WantsExcludedAdmissionResources interface {
|
||||
SetExcludedAdmissionResources(excludedAdmissionResources []schema.GroupResource)
|
||||
admission.InitializationValidator
|
||||
}
|
||||
|
@ -21,12 +21,14 @@ import (
|
||||
"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/admission/resourcefilter"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/informers"
|
||||
@ -37,6 +39,15 @@ import (
|
||||
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 {
|
||||
@ -49,14 +60,14 @@ type Plugin[H any] struct {
|
||||
dispatcher Dispatcher[H]
|
||||
matcher *matching.Matcher
|
||||
|
||||
informerFactory informers.SharedInformerFactory
|
||||
client kubernetes.Interface
|
||||
restMapper meta.RESTMapper
|
||||
dynamicClient dynamic.Interface
|
||||
resourceFilter resourcefilter.Interface // optional
|
||||
stopCh <-chan struct{}
|
||||
authorizer authorizer.Authorizer
|
||||
enabled bool
|
||||
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 (
|
||||
@ -66,7 +77,7 @@ var (
|
||||
_ initializer.WantsDynamicClient = &Plugin[any]{}
|
||||
_ initializer.WantsDrainedNotification = &Plugin[any]{}
|
||||
_ initializer.WantsAuthorizer = &Plugin[any]{}
|
||||
_ initializer.WantsResourceFilter = &Plugin[any]{}
|
||||
_ initializer.WantsExcludedAdmissionResources = &Plugin[any]{}
|
||||
_ admission.InitializationValidator = &Plugin[any]{}
|
||||
)
|
||||
|
||||
@ -79,6 +90,9 @@ func NewPlugin[H any](
|
||||
Handler: handler,
|
||||
sourceFactory: sourceFactory,
|
||||
dispatcherFactory: dispatcherFactory,
|
||||
|
||||
// always exclude admission/mutating policies and bindings
|
||||
excludedResources: sets.New(admissionResources...),
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,8 +128,8 @@ func (c *Plugin[H]) SetEnabled(enabled bool) {
|
||||
c.enabled = enabled
|
||||
}
|
||||
|
||||
func (c *Plugin[H]) SetResourceFilter(filter resourcefilter.Interface) {
|
||||
c.resourceFilter = filter
|
||||
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
|
||||
@ -184,7 +198,7 @@ func (c *Plugin[H]) Dispatch(
|
||||
) (err error) {
|
||||
if !c.enabled {
|
||||
return nil
|
||||
} else if isPolicyResource(a) || (c.resourceFilter != nil && !c.resourceFilter.ShouldHandle(a)) {
|
||||
} else if c.shouldIgnoreResource(a) {
|
||||
return nil
|
||||
} else if !c.WaitForReady() {
|
||||
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
|
||||
@ -193,14 +207,9 @@ func (c *Plugin[H]) Dispatch(
|
||||
return c.dispatcher.Dispatch(ctx, a, o, c.source.Hooks())
|
||||
}
|
||||
|
||||
func isPolicyResource(attr admission.Attributes) bool {
|
||||
gvk := attr.GetResource()
|
||||
if gvk.Group == "admissionregistration.k8s.io" {
|
||||
if gvk.Resource == "validatingadmissionpolicies" || gvk.Resource == "validatingadmissionpolicybindings" {
|
||||
return true
|
||||
} else if gvk.Resource == "mutatingadmissionpolicies" || gvk.Resource == "mutatingadmissionpolicybindings" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
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)
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ type Plugin struct {
|
||||
var _ admission.Interface = &Plugin{}
|
||||
var _ admission.ValidationInterface = &Plugin{}
|
||||
var _ initializer.WantsFeatures = &Plugin{}
|
||||
var _ initializer.WantsResourceFilter = &Plugin{}
|
||||
var _ initializer.WantsExcludedAdmissionResources = &Plugin{}
|
||||
|
||||
func NewPlugin(_ io.Reader) *Plugin {
|
||||
handler := admission.NewHandler(admission.Connect, admission.Create, admission.Delete, admission.Update)
|
||||
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
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 resourcefilter
|
||||
|
||||
import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
// Interface is a resource filter that takes an Attributes and
|
||||
// check if it should be handled or ignored by the admission plugin.
|
||||
type Interface interface {
|
||||
// ShouldHandle returns true if the admission plugin should handle the request,
|
||||
// considering the given Attributes, or false otherwise.
|
||||
ShouldHandle(admission.Attributes) bool
|
||||
}
|
Loading…
Reference in New Issue
Block a user