move webhook admission to generic apiserver

pull/6/head
David Eads 2017-10-24 08:48:05 -04:00
parent 86f90ecbb8
commit 8c1fe1f61a
47 changed files with 162 additions and 134 deletions

View File

@ -59,6 +59,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",

View File

@ -48,7 +48,6 @@ go_library(
"//plugin/pkg/admission/securitycontext/scdeny:go_default_library",
"//plugin/pkg/admission/serviceaccount:go_default_library",
"//plugin/pkg/admission/storageclass/setdefault:go_default_library",
"//plugin/pkg/admission/webhook:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",

View File

@ -104,8 +104,8 @@ func TestAddFlags(t *testing.T) {
MinRequestTimeout: 1800,
},
Admission: &apiserveroptions.AdmissionOptions{
RecommendedPluginOrder: []string{"NamespaceLifecycle", "Initializers"},
DefaultOffPlugins: []string{"Initializers"},
RecommendedPluginOrder: []string{"NamespaceLifecycle", "Initializers", "GenericAdmissionWebhook"},
DefaultOffPlugins: []string{"Initializers", "GenericAdmissionWebhook"},
PluginNames: []string{"AlwaysDeny"},
ConfigFile: "/admission-control-config",
Plugins: s.Admission.Plugins,

View File

@ -50,7 +50,6 @@ import (
"k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny"
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
"k8s.io/kubernetes/plugin/pkg/admission/storageclass/setdefault"
"k8s.io/kubernetes/plugin/pkg/admission/webhook"
)
// RegisterAllAdmissionPlugins registers all admission plugins
@ -79,6 +78,5 @@ func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
scdeny.Register(plugins)
serviceaccount.Register(plugins)
setdefault.Register(plugins)
webhook.Register(plugins)
resize.Register(plugins)
}

View File

@ -44,6 +44,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
utilwait "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/webhook"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authorization/authorizer"
genericapiserver "k8s.io/apiserver/pkg/server"
@ -452,26 +453,36 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
}
webhookAuthResolver := func(delegate webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver {
return webhook.AuthenticationInfoResolverFunc(func(server string) (*rest.Config, error) {
if server == "kubernetes.default.svc" {
return genericConfig.LoopbackClientConfig, nil
}
ret, err := delegate.ClientConfigFor(server)
if err != nil {
return nil, err
}
if proxyTransport != nil && proxyTransport.Dial != nil {
ret.Dial = proxyTransport.Dial
}
return ret, err
})
}
pluginInitializer, err := BuildAdmissionPluginInitializer(
s,
client,
sharedInformers,
serviceResolver,
webhookAuthResolver,
)
if err != nil {
return nil, nil, nil, nil, nil, fmt.Errorf("failed to create admission plugin initializer: %v", err)
}
webhookClientConfig := rest.AnonymousClientConfig(genericConfig.LoopbackClientConfig)
if proxyTransport != nil && proxyTransport.Dial != nil {
webhookClientConfig.Dial = proxyTransport.Dial
}
err = s.Admission.ApplyTo(
genericConfig,
versionedInformers,
kubeClientConfig,
webhookClientConfig,
legacyscheme.Scheme,
pluginInitializer)
if err != nil {
@ -481,7 +492,7 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
}
// BuildAdmissionPluginInitializer constructs the admission plugin initializer
func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, serviceResolver aggregatorapiserver.ServiceResolver) (admission.PluginInitializer, error) {
func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, sharedInformers informers.SharedInformerFactory, serviceResolver aggregatorapiserver.ServiceResolver, webhookAuthWrapper webhook.AuthenticationInfoResolverWrapper) (admission.PluginInitializer, error) {
var cloudConfig []byte
if s.CloudProvider.CloudConfigFile != "" {
@ -499,9 +510,7 @@ func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client interna
// do not require us to open watches for all items tracked by quota.
quotaRegistry := quotainstall.NewRegistry(nil, nil)
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaRegistry)
pluginInitializer = pluginInitializer.SetServiceResolver(serviceResolver)
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, restMapper, quotaRegistry, webhookAuthWrapper, serviceResolver)
return pluginInitializer, nil
}

View File

@ -84,7 +84,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//vendor/k8s.io/client-go/informers:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
],
)

View File

@ -42,7 +42,6 @@ import (
serverstorage "k8s.io/apiserver/pkg/server/storage"
clientgoinformers "k8s.io/client-go/informers"
clientgoclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
openapicommon "k8s.io/kube-openapi/pkg/common"
federationv1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
"k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options"
@ -211,13 +210,12 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
// NOTE: we do not provide informers to the quota registry because admission level decisions
// do not require us to open watches for all items tracked by quota.
quotaRegistry := quotainstall.NewRegistry(nil, nil)
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, nil, quotaRegistry)
pluginInitializer := kubeapiserveradmission.NewPluginInitializer(client, sharedInformers, cloudConfig, nil, quotaRegistry, nil, nil)
err = s.Admission.ApplyTo(
genericConfig,
versionedInformers,
kubeClientConfig,
rest.AnonymousClientConfig(kubeClientConfig),
legacyscheme.Scheme,
pluginInitializer,
)

View File

@ -463,7 +463,6 @@ plugin/pkg/admission/security
plugin/pkg/admission/security/podsecuritypolicy
plugin/pkg/admission/serviceaccount
plugin/pkg/admission/storageclass/setdefault
plugin/pkg/admission/webhook
plugin/pkg/auth/authorizer/node
plugin/pkg/auth/authorizer/rbac
plugin/pkg/scheduler/algorithm
@ -584,6 +583,7 @@ staging/src/k8s.io/apiserver/pkg/admission
staging/src/k8s.io/apiserver/pkg/admission/configuration
staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization
staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook
staging/src/k8s.io/apiserver/pkg/apis/apiserver
staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1
staging/src/k8s.io/apiserver/pkg/apis/audit

View File

@ -11,7 +11,10 @@ go_test(
srcs = ["init_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubeapiserver/admission",
library = ":go_default_library",
deps = ["//vendor/k8s.io/apiserver/pkg/admission:go_default_library"],
deps = [
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:go_default_library",
],
)
go_library(
@ -24,6 +27,7 @@ go_library(
"//pkg/quota:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
],

View File

@ -21,6 +21,7 @@ import (
"testing"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/webhook"
)
type doNothingAdmission struct{}
@ -40,7 +41,7 @@ func (self *WantsCloudConfigAdmissionPlugin) SetCloudConfig(cloudConfig []byte)
func TestCloudConfigAdmissionPlugin(t *testing.T) {
cloudConfig := []byte("cloud-configuration")
initializer := NewPluginInitializer(nil, nil, cloudConfig, nil, nil)
initializer := NewPluginInitializer(nil, nil, cloudConfig, nil, nil, nil, nil)
wantsCloudConfigAdmission := &WantsCloudConfigAdmissionPlugin{}
initializer.Initialize(wantsCloudConfigAdmission)
@ -60,13 +61,13 @@ type serviceWanter struct {
got ServiceResolver
}
func (s *serviceWanter) SetServiceResolver(sr ServiceResolver) { s.got = sr }
func (s *serviceWanter) SetServiceResolver(sr webhook.ServiceResolver) { s.got = sr }
func TestWantsServiceResolver(t *testing.T) {
sw := &serviceWanter{}
fsr := &fakeServiceResolver{}
i := &PluginInitializer{}
i.SetServiceResolver(fsr).Initialize(sw)
i := NewPluginInitializer(nil, nil, nil, nil, nil, nil, fsr)
i.Initialize(sw)
if got, ok := sw.got.(*fakeServiceResolver); !ok || got != fsr {
t.Errorf("plumbing fail - %v %v#", ok, got)
}

View File

@ -21,6 +21,7 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/webhook"
"k8s.io/apiserver/pkg/authorization/authorizer"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
@ -61,7 +62,7 @@ type WantsQuotaRegistry interface {
// WantsServiceResolver defines a fuction that accepts a ServiceResolver for
// admission plugins that need to make calls to services.
type WantsServiceResolver interface {
SetServiceResolver(ServiceResolver)
SetServiceResolver(webhook.ServiceResolver)
}
// ServiceResolver knows how to convert a service reference into an actual
@ -70,15 +71,23 @@ type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error)
}
// WantsAuthenticationInfoResolverWrapper defines a function that wraps the standard AuthenticationInfoResolver
// to allow the apiserver to control what is returned as auth info
type WantsAuthenticationInfoResolverWrapper interface {
SetAuthenticationInfoResolverWrapper(webhook.AuthenticationInfoResolverWrapper)
admission.Validator
}
type PluginInitializer struct {
internalClient internalclientset.Interface
externalClient clientset.Interface
informers informers.SharedInformerFactory
authorizer authorizer.Authorizer
cloudConfig []byte
restMapper meta.RESTMapper
quotaRegistry quota.Registry
serviceResolver ServiceResolver
internalClient internalclientset.Interface
externalClient clientset.Interface
informers informers.SharedInformerFactory
authorizer authorizer.Authorizer
cloudConfig []byte
restMapper meta.RESTMapper
quotaRegistry quota.Registry
serviceResolver webhook.ServiceResolver
authenticationInfoResolverWrapper webhook.AuthenticationInfoResolverWrapper
}
var _ admission.PluginInitializer = &PluginInitializer{}
@ -92,22 +101,20 @@ func NewPluginInitializer(
cloudConfig []byte,
restMapper meta.RESTMapper,
quotaRegistry quota.Registry,
authenticationInfoResolverWrapper webhook.AuthenticationInfoResolverWrapper,
serviceResolver webhook.ServiceResolver,
) *PluginInitializer {
return &PluginInitializer{
internalClient: internalClient,
informers: sharedInformers,
cloudConfig: cloudConfig,
restMapper: restMapper,
quotaRegistry: quotaRegistry,
internalClient: internalClient,
informers: sharedInformers,
cloudConfig: cloudConfig,
restMapper: restMapper,
quotaRegistry: quotaRegistry,
authenticationInfoResolverWrapper: authenticationInfoResolverWrapper,
serviceResolver: serviceResolver,
}
}
// SetServiceResolver sets the service resolver which is needed by some plugins.
func (i *PluginInitializer) SetServiceResolver(s ServiceResolver) *PluginInitializer {
i.serviceResolver = s
return i
}
// Initialize checks the initialization interfaces implemented by each plugin
// and provide the appropriate initialization data
func (i *PluginInitializer) Initialize(plugin admission.Interface) {
@ -134,4 +141,10 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) {
if wants, ok := plugin.(WantsServiceResolver); ok {
wants.SetServiceResolver(i.serviceResolver)
}
if wants, ok := plugin.(WantsAuthenticationInfoResolverWrapper); ok {
if i.authenticationInfoResolverWrapper != nil {
wants.SetAuthenticationInfoResolverWrapper(i.authenticationInfoResolverWrapper)
}
}
}

View File

@ -37,7 +37,6 @@ filegroup(
"//plugin/pkg/admission/securitycontext/scdeny:all-srcs",
"//plugin/pkg/admission/serviceaccount:all-srcs",
"//plugin/pkg/admission/storageclass/setdefault:all-srcs",
"//plugin/pkg/admission/webhook:all-srcs",
"//plugin/pkg/auth:all-srcs",
"//plugin/pkg/scheduler:all-srcs",
],

View File

@ -86,11 +86,11 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
whiteList: whiteList,
}
genericPluginInitializer, err := initializer.New(nil, nil, fakeAuthorizer{}, nil, nil)
genericPluginInitializer, err := initializer.New(nil, nil, fakeAuthorizer{}, nil)
if err != nil {
return nil, err
}
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil)
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil, nil, nil)
initializersChain := admission.PluginInitializers{}
initializersChain = append(initializersChain, genericPluginInitializer)
initializersChain = append(initializersChain, pluginInitializer)

View File

@ -744,7 +744,7 @@ func newHandlerForTest(c clientset.Interface) (admission.Interface, informers.Sh
if err != nil {
return nil, f, err
}
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
pluginInitializer.Initialize(handler)
err = admission.Validate(handler)
return handler, f, err

View File

@ -38,7 +38,7 @@ import (
func newHandlerForTest(c clientset.Interface) (admission.Interface, informers.SharedInformerFactory, error) {
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
handler := NewProvision()
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
pluginInitializer.Initialize(handler)
err := admission.Validate(handler)
return handler, f, err

View File

@ -37,7 +37,7 @@ import (
func newHandlerForTest(c clientset.Interface) (admission.Interface, informers.SharedInformerFactory, error) {
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
handler := NewExists()
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
pluginInitializer.Initialize(handler)
err := admission.Validate(handler)
return handler, f, err

View File

@ -241,7 +241,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
func newHandlerForTest(c clientset.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
handler := NewPodNodeSelector(nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
pluginInitializer.Initialize(handler)
err := admission.Validate(handler)
return handler, f, err

View File

@ -342,7 +342,7 @@ func newHandlerForTest(c clientset.Interface) (*podTolerationsPlugin, informers.
return nil, nil, err
}
handler := NewPodTolerationsPlugin(pluginConfig)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil, nil, nil)
pluginInitializer.Initialize(handler)
err = admission.Validate(handler)
return handler, f, err

View File

@ -514,6 +514,10 @@
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
},
{
"ImportPath": "k8s.io/api/admission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@ -862,6 +866,10 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/webhook",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/apis/apiserver",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -762,6 +762,10 @@
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
},
{
"ImportPath": "k8s.io/api/admission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@ -1674,6 +1678,10 @@
"ImportPath": "k8s.io/client-go/tools/clientcmd",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/client-go/tools/clientcmd/api",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/client-go/tools/clientcmd/api/v1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -68,6 +68,7 @@ filegroup(
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -19,7 +19,6 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/client-go/informers:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
],
)

View File

@ -22,17 +22,13 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
type pluginInitializer struct {
externalClient kubernetes.Interface
externalInformers informers.SharedInformerFactory
authorizer authorizer.Authorizer
// webhookRESTClientConfig provies a client used to contact webhooks
// TODO clean out cruft
webhookRESTClientConfig *rest.Config
scheme *runtime.Scheme
scheme *runtime.Scheme
}
// New creates an instance of admission plugins initializer.
@ -41,15 +37,13 @@ func New(
extClientset kubernetes.Interface,
extInformers informers.SharedInformerFactory,
authz authorizer.Authorizer,
webhookRESTClientConfig *rest.Config,
scheme *runtime.Scheme,
) (pluginInitializer, error) {
return pluginInitializer{
externalClient: extClientset,
externalInformers: extInformers,
authorizer: authz,
webhookRESTClientConfig: webhookRESTClientConfig,
scheme: scheme,
externalClient: extClientset,
externalInformers: extInformers,
authorizer: authz,
scheme: scheme,
}, nil
}
@ -68,10 +62,6 @@ func (i pluginInitializer) Initialize(plugin admission.Interface) {
wants.SetAuthorizer(i.authorizer)
}
if wants, ok := plugin.(WantsWebhookRESTClientConfig); ok {
wants.SetWebhookRESTClientConfig(i.webhookRESTClientConfig)
}
if wants, ok := plugin.(WantsScheme); ok {
wants.SetScheme(i.scheme)
}

View File

@ -33,7 +33,7 @@ import (
// the WantsScheme interface is implemented by a plugin.
func TestWantsScheme(t *testing.T) {
scheme := runtime.NewScheme()
target, err := initializer.New(nil, nil, nil, nil, scheme)
target, err := initializer.New(nil, nil, nil, scheme)
if err != nil {
t.Fatal(err)
}
@ -47,7 +47,7 @@ func TestWantsScheme(t *testing.T) {
// TestWantsAuthorizer ensures that the authorizer is injected
// when the WantsAuthorizer interface is implemented by a plugin.
func TestWantsAuthorizer(t *testing.T) {
target, err := initializer.New(nil, nil, &TestAuthorizer{}, nil, nil)
target, err := initializer.New(nil, nil, &TestAuthorizer{}, nil)
if err != nil {
t.Fatal(err)
}
@ -62,7 +62,7 @@ func TestWantsAuthorizer(t *testing.T) {
// when the WantsExternalKubeClientSet interface is implemented by a plugin.
func TestWantsExternalKubeClientSet(t *testing.T) {
cs := &fake.Clientset{}
target, err := initializer.New(cs, nil, &TestAuthorizer{}, nil, nil)
target, err := initializer.New(cs, nil, &TestAuthorizer{}, nil)
if err != nil {
t.Fatal(err)
}
@ -78,7 +78,7 @@ func TestWantsExternalKubeClientSet(t *testing.T) {
func TestWantsExternalKubeInformerFactory(t *testing.T) {
cs := &fake.Clientset{}
sf := informers.NewSharedInformerFactory(cs, time.Duration(1)*time.Second)
target, err := initializer.New(cs, sf, &TestAuthorizer{}, nil, nil)
target, err := initializer.New(cs, sf, &TestAuthorizer{}, nil)
if err != nil {
t.Fatal(err)
}

View File

@ -22,7 +22,6 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
// WantsExternalKubeClientSet defines a function which sets external ClientSet for admission plugins that need it
@ -43,13 +42,6 @@ type WantsAuthorizer interface {
admission.Validator
}
// WantsWebhookRESTClientConfig defines a function that accepts client config for admission
// plugins that need to make calls and prove their identity.
type WantsWebhookRESTClientConfig interface {
SetWebhookRESTClientConfig(*rest.Config)
admission.Validator
}
// WantsScheme defines a function that accepts runtime.Scheme for admission plugins that need it.
type WantsScheme interface {
SetScheme(*runtime.Scheme)

View File

@ -48,7 +48,7 @@ func newHandlerForTestWithClock(c clientset.Interface, cacheClock clock.Clock) (
if err != nil {
return nil, f, err
}
pluginInitializer, err := kubeadmission.New(c, f, nil, nil, nil)
pluginInitializer, err := kubeadmission.New(c, f, nil, nil)
if err != nil {
return handler, f, err
}

View File

@ -11,11 +11,9 @@ go_library(
"rules.go",
"serviceresolver.go",
],
importpath = "k8s.io/kubernetes/plugin/pkg/admission/webhook",
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/webhook",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/admission/install:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/admission/v1alpha1:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
@ -46,16 +44,15 @@ go_test(
"rules_test.go",
"serviceresolver_test.go",
],
importpath = "k8s.io/kubernetes/plugin/pkg/admission/webhook",
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/webhook",
library = ":go_default_library",
deps = [
"//pkg/api:go_default_library",
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/admission/install:go_default_library",
"//vendor/k8s.io/api/admission/v1alpha1:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",

View File

@ -21,6 +21,7 @@ import (
"context"
"fmt"
"io"
"net/url"
"path"
"sync"
@ -40,10 +41,11 @@ import (
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
admissioninit "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
// install the clientgo admission API for use with api registry
_ "k8s.io/kubernetes/pkg/apis/admission/install"
const (
// Name of admission plug-in
PluginName = "GenericAdmissionWebhook"
)
type ErrCallingWebhook struct {
@ -60,7 +62,7 @@ func (e *ErrCallingWebhook) Error() string {
// Register registers a plugin
func Register(plugins *admission.Plugins) {
plugins.Register("GenericAdmissionWebhook", func(configFile io.Reader) (admission.Interface, error) {
plugins.Register(PluginName, func(configFile io.Reader) (admission.Interface, error) {
plugin, err := NewGenericAdmissionWebhook(configFile)
if err != nil {
return nil, err
@ -110,31 +112,31 @@ func NewGenericAdmissionWebhook(configFile io.Reader) (*GenericAdmissionWebhook,
type GenericAdmissionWebhook struct {
*admission.Handler
hookSource WebhookSource
serviceResolver admissioninit.ServiceResolver
serviceResolver ServiceResolver
negotiatedSerializer runtime.NegotiatedSerializer
authInfoResolver AuthenticationInfoResolver
}
// serviceResolver knows how to convert a service reference into an actual location.
type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error)
}
var (
_ = admissioninit.WantsServiceResolver(&GenericAdmissionWebhook{})
_ = genericadmissioninit.WantsWebhookRESTClientConfig(&GenericAdmissionWebhook{})
_ = genericadmissioninit.WantsExternalKubeClientSet(&GenericAdmissionWebhook{})
)
// TODO find a better way wire this, but keep this pull small for now.
func (a *GenericAdmissionWebhook) SetWebhookRESTClientConfig(in *rest.Config) {
if in != nil {
a.authInfoResolver = &dialOverridingAuthenticationInfoResolver{
dialFn: in.Dial,
delegate: a.authInfoResolver,
}
func (a *GenericAdmissionWebhook) SetAuthenticationInfoResolverWrapper(wrapper AuthenticationInfoResolverWrapper) {
if wrapper != nil {
a.authInfoResolver = wrapper(a.authInfoResolver)
}
}
// SetServiceResolver sets a service resolver for the webhook admission plugin.
// Passing a nil resolver does not have an effect, instead a default one will be used.
func (a *GenericAdmissionWebhook) SetServiceResolver(sr admissioninit.ServiceResolver) {
func (a *GenericAdmissionWebhook) SetServiceResolver(sr ServiceResolver) {
if sr != nil {
a.serviceResolver = sr
}

View File

@ -29,14 +29,12 @@ import (
"k8s.io/api/admission/v1alpha1"
registrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
api "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/client-go/rest"
_ "k8s.io/kubernetes/pkg/apis/admission/install"
)
type fakeHookSource struct {
@ -67,6 +65,10 @@ func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL,
// TestAdmit tests that GenericAdmissionWebhook#Admit works as expected
func TestAdmit(t *testing.T) {
scheme := runtime.NewScheme()
v1alpha1.AddToScheme(scheme)
api.AddToScheme(scheme)
// Create the test webhook server
sCert, err := tls.X509KeyPair(serverCert, serverKey)
if err != nil {
@ -101,7 +103,7 @@ func TestAdmit(t *testing.T) {
}
// Set up a test object for the call
kind := api.Kind("Pod").WithVersion("v1")
kind := api.SchemeGroupVersion.WithKind("Pod")
name := "my-pod"
namespace := "webhook-test"
object := api.Pod{
@ -266,7 +268,7 @@ func TestAdmit(t *testing.T) {
t.Run(name, func(t *testing.T) {
wh.hookSource = &tt.hookSource
wh.serviceResolver = fakeServiceResolver{base: *serverURL}
wh.SetScheme(legacyscheme.Scheme)
wh.SetScheme(scheme)
err = wh.Admit(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo))
if tt.expectAllow != (err == nil) {

View File

@ -18,7 +18,6 @@ package webhook
import (
"io/ioutil"
"net"
"strings"
"time"
@ -29,10 +28,18 @@ import (
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
type AuthenticationInfoResolverWrapper func(AuthenticationInfoResolver) AuthenticationInfoResolver
type AuthenticationInfoResolver interface {
ClientConfigFor(server string) (*rest.Config, error)
}
type AuthenticationInfoResolverFunc func(server string) (*rest.Config, error)
func (a AuthenticationInfoResolverFunc) ClientConfigFor(server string) (*rest.Config, error) {
return a(server)
}
type defaultAuthenticationInfoResolver struct {
kubeconfig clientcmdapi.Config
}
@ -140,18 +147,3 @@ func setGlobalDefaults(config *rest.Config) *rest.Config {
return config
}
type dialOverridingAuthenticationInfoResolver struct {
dialFn func(network, addr string) (net.Conn, error)
delegate AuthenticationInfoResolver
}
func (c *dialOverridingAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) {
cfg, err := c.delegate.ClientConfigFor(server)
if err != nil {
return nil, err
}
cfg.Dial = c.dialFn
return cfg, nil
}

View File

@ -21,14 +21,10 @@ import (
"errors"
"fmt"
"net/url"
admissioninit "k8s.io/kubernetes/pkg/kubeapiserver/admission"
)
type defaultServiceResolver struct{}
var _ admissioninit.ServiceResolver = defaultServiceResolver{}
// ResolveEndpoint constructs a service URL from a given namespace and name
// note that the name and namespace are required and by default all created addresses use HTTPS scheme.
// for example:

View File

@ -85,6 +85,7 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/initialization:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/install:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library",

View File

@ -32,6 +32,7 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/initialization:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/webhook:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library",

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/admission/initializer"
"k8s.io/apiserver/pkg/admission/plugin/initialization"
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
"k8s.io/apiserver/pkg/admission/plugin/webhook/webhook"
"k8s.io/apiserver/pkg/server"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
@ -55,8 +56,8 @@ func NewAdmissionOptions() *AdmissionOptions {
options := &AdmissionOptions{
Plugins: &admission.Plugins{},
PluginNames: []string{},
RecommendedPluginOrder: []string{lifecycle.PluginName, initialization.PluginName},
DefaultOffPlugins: []string{initialization.PluginName},
RecommendedPluginOrder: []string{lifecycle.PluginName, initialization.PluginName, webhook.PluginName},
DefaultOffPlugins: []string{initialization.PluginName, webhook.PluginName},
}
server.RegisterAllAdmissionPlugins(options.Plugins)
return options
@ -81,7 +82,6 @@ func (a *AdmissionOptions) ApplyTo(
c *server.Config,
informers informers.SharedInformerFactory,
kubeAPIServerClientConfig *rest.Config,
webhookClientConfig *rest.Config,
scheme *runtime.Scheme,
pluginInitializers ...admission.PluginInitializer,
) error {
@ -99,7 +99,7 @@ func (a *AdmissionOptions) ApplyTo(
if err != nil {
return err
}
genericInitializer, err := initializer.New(clientset, informers, c.Authorizer, webhookClientConfig, scheme)
genericInitializer, err := initializer.New(clientset, informers, c.Authorizer, scheme)
if err != nil {
return err
}

View File

@ -21,10 +21,12 @@ import (
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/initialization"
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
"k8s.io/apiserver/pkg/admission/plugin/webhook/webhook"
)
// RegisterAllAdmissionPlugins registers all admission plugins
func RegisterAllAdmissionPlugins(plugins *admission.Plugins) {
lifecycle.Register(plugins)
initialization.Register(plugins)
webhook.Register(plugins)
}

View File

@ -490,6 +490,10 @@
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
},
{
"ImportPath": "k8s.io/api/admission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@ -830,6 +834,10 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/webhook",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/apis/apiserver",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -474,6 +474,10 @@
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
},
{
"ImportPath": "k8s.io/api/admission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@ -826,6 +830,10 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/webhook",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/apis/apiserver",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -119,7 +119,7 @@ func (o WardleServerOptions) Config() (*apiserver.Config, error) {
return nil, err
}
if err := o.Admission.ApplyTo(&serverConfig.Config, serverConfig.SharedInformerFactory, serverConfig.ClientConfig, serverConfig.ClientConfig, apiserver.Scheme, admissionInitializer); err != nil {
if err := o.Admission.ApplyTo(&serverConfig.Config, serverConfig.SharedInformerFactory, serverConfig.ClientConfig, apiserver.Scheme, admissionInitializer); err != nil {
return nil, err
}