mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #85870 from Jefftree/authn-netproxy
Use Network Proxy with Authentication & Authorizer Webhooks
This commit is contained in:
		@@ -498,13 +498,13 @@ func buildGenericConfig(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
 | 
						versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, clientgoExternalClient, versionedInformers)
 | 
						genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, genericConfig.EgressSelector, clientgoExternalClient, versionedInformers)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		lastErr = fmt.Errorf("invalid authentication config: %v", err)
 | 
							lastErr = fmt.Errorf("invalid authentication config: %v", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, err = BuildAuthorizer(s, versionedInformers)
 | 
						genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, err = BuildAuthorizer(s, genericConfig.EgressSelector, versionedInformers)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		lastErr = fmt.Errorf("invalid authorization config: %v", err)
 | 
							lastErr = fmt.Errorf("invalid authorization config: %v", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -560,7 +560,7 @@ func buildGenericConfig(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BuildAuthenticator constructs the authenticator
 | 
					// BuildAuthenticator constructs the authenticator
 | 
				
			||||||
func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) {
 | 
					func BuildAuthenticator(s *options.ServerRunOptions, EgressSelector *egressselector.EgressSelector, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) {
 | 
				
			||||||
	authenticatorConfig, err := s.Authentication.ToAuthenticationConfig()
 | 
						authenticatorConfig, err := s.Authentication.ToAuthenticationConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, nil, err
 | 
							return nil, nil, err
 | 
				
			||||||
@@ -577,12 +577,29 @@ func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset
 | 
				
			|||||||
		versionedInformer.Core().V1().Secrets().Lister().Secrets(v1.NamespaceSystem),
 | 
							versionedInformer.Core().V1().Secrets().Lister().Secrets(v1.NamespaceSystem),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if EgressSelector != nil {
 | 
				
			||||||
 | 
							egressDialer, err := EgressSelector.Lookup(egressselector.Master.AsNetworkContext())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							authenticatorConfig.CustomDial = egressDialer
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return authenticatorConfig.New()
 | 
						return authenticatorConfig.New()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BuildAuthorizer constructs the authorizer
 | 
					// BuildAuthorizer constructs the authorizer
 | 
				
			||||||
func BuildAuthorizer(s *options.ServerRunOptions, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
					func BuildAuthorizer(s *options.ServerRunOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
				
			||||||
	authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
 | 
						authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if EgressSelector != nil {
 | 
				
			||||||
 | 
							egressDialer, err := EgressSelector.Lookup(egressselector.Master.AsNetworkContext())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							authorizationConfig.CustomDial = egressDialer
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return authorizationConfig.New()
 | 
						return authorizationConfig.New()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ go_library(
 | 
				
			|||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
        "//pkg/features:go_default_library",
 | 
					        "//pkg/features:go_default_library",
 | 
				
			||||||
        "//pkg/serviceaccount:go_default_library",
 | 
					        "//pkg/serviceaccount:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticatorfactory:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticatorfactory:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/group:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/group:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/go-openapi/spec"
 | 
						"github.com/go-openapi/spec"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
						"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
 | 
						"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/group"
 | 
						"k8s.io/apiserver/pkg/authentication/group"
 | 
				
			||||||
@@ -83,6 +84,9 @@ type Config struct {
 | 
				
			|||||||
	// Generally this is the CA bundle file used to authenticate client certificates
 | 
						// Generally this is the CA bundle file used to authenticate client certificates
 | 
				
			||||||
	// If this value is nil, then mutual TLS is disabled.
 | 
						// If this value is nil, then mutual TLS is disabled.
 | 
				
			||||||
	ClientCAContentProvider dynamiccertificates.CAContentProvider
 | 
						ClientCAContentProvider dynamiccertificates.CAContentProvider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Optional field, custom dial function used to connect to webhook
 | 
				
			||||||
 | 
						CustomDial utilnet.DialFunc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New returns an authenticator.Request or an error that supports the standard
 | 
					// New returns an authenticator.Request or an error that supports the standard
 | 
				
			||||||
@@ -179,10 +183,11 @@ func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, er
 | 
				
			|||||||
		tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, oidcAuth))
 | 
							tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, oidcAuth))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(config.WebhookTokenAuthnConfigFile) > 0 {
 | 
						if len(config.WebhookTokenAuthnConfigFile) > 0 {
 | 
				
			||||||
		webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnVersion, config.WebhookTokenAuthnCacheTTL, config.APIAudiences)
 | 
							webhookTokenAuth, err := newWebhookTokenAuthenticator(config)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, nil, err
 | 
								return nil, nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
 | 
							tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -305,11 +310,11 @@ func newServiceAccountAuthenticator(iss string, keyfiles []string, apiAudiences
 | 
				
			|||||||
	return tokenAuthenticator, nil
 | 
						return tokenAuthenticator, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newWebhookTokenAuthenticator(webhookConfigFile string, version string, ttl time.Duration, implicitAuds authenticator.Audiences) (authenticator.Token, error) {
 | 
					func newWebhookTokenAuthenticator(config Config) (authenticator.Token, error) {
 | 
				
			||||||
	webhookTokenAuthenticator, err := webhook.New(webhookConfigFile, version, implicitAuds)
 | 
						webhookTokenAuthenticator, err := webhook.New(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnVersion, config.APIAudiences, config.CustomDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return tokencache.New(webhookTokenAuthenticator, false, ttl, ttl), nil
 | 
						return tokencache.New(webhookTokenAuthenticator, false, config.WebhookTokenAuthnCacheTTL, config.WebhookTokenAuthnCacheTTL), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ go_library(
 | 
				
			|||||||
        "//plugin/pkg/auth/authorizer/node:go_default_library",
 | 
					        "//plugin/pkg/auth/authorizer/node:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/auth/authorizer/rbac:go_default_library",
 | 
					        "//plugin/pkg/auth/authorizer/rbac:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
 | 
					        "//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/union:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/union:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizerfactory"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizerfactory"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/union"
 | 
						"k8s.io/apiserver/pkg/authorization/union"
 | 
				
			||||||
@@ -54,6 +55,9 @@ type Config struct {
 | 
				
			|||||||
	WebhookCacheUnauthorizedTTL time.Duration
 | 
						WebhookCacheUnauthorizedTTL time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VersionedInformerFactory versionedinformers.SharedInformerFactory
 | 
						VersionedInformerFactory versionedinformers.SharedInformerFactory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Optional field, custom dial function used to connect to webhook
 | 
				
			||||||
 | 
						CustomDial utilnet.DialFunc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New returns the right sort of union of multiple authorizer.Authorizer objects
 | 
					// New returns the right sort of union of multiple authorizer.Authorizer objects
 | 
				
			||||||
@@ -102,7 +106,8 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
				
			|||||||
			webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
 | 
								webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
 | 
				
			||||||
				config.WebhookVersion,
 | 
									config.WebhookVersion,
 | 
				
			||||||
				config.WebhookCacheAuthorizedTTL,
 | 
									config.WebhookCacheAuthorizedTTL,
 | 
				
			||||||
				config.WebhookCacheUnauthorizedTTL)
 | 
									config.WebhookCacheUnauthorizedTTL,
 | 
				
			||||||
 | 
									config.CustomDial)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return nil, nil, err
 | 
									return nil, nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -261,7 +261,7 @@ func NewImagePolicyWebhook(configFile io.Reader) (*Plugin, error) {
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gw, err := webhook.NewGenericWebhook(legacyscheme.Scheme, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff)
 | 
						gw, err := webhook.NewGenericWebhook(legacyscheme.Scheme, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	corev1 "k8s.io/api/core/v1"
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
						auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
				
			||||||
	auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
 | 
						auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
 | 
				
			||||||
	auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
 | 
						auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
 | 
				
			||||||
@@ -37,6 +38,7 @@ import (
 | 
				
			|||||||
	"k8s.io/apiserver/pkg/audit/policy"
 | 
						"k8s.io/apiserver/pkg/audit/policy"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/features"
 | 
						"k8s.io/apiserver/pkg/features"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/server"
 | 
						"k8s.io/apiserver/pkg/server"
 | 
				
			||||||
 | 
						"k8s.io/apiserver/pkg/server/egressselector"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	pluginbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
 | 
						pluginbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
 | 
				
			||||||
	plugindynamic "k8s.io/apiserver/plugin/pkg/audit/dynamic"
 | 
						plugindynamic "k8s.io/apiserver/plugin/pkg/audit/dynamic"
 | 
				
			||||||
@@ -323,7 +325,15 @@ func (o *AuditOptions) ApplyTo(
 | 
				
			|||||||
		if checker == nil {
 | 
							if checker == nil {
 | 
				
			||||||
			klog.V(2).Info("No audit policy file provided, no events will be recorded for webhook backend")
 | 
								klog.V(2).Info("No audit policy file provided, no events will be recorded for webhook backend")
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			webhookBackend, err = o.WebhookOptions.newUntruncatedBackend()
 | 
								if c.EgressSelector != nil {
 | 
				
			||||||
 | 
									egressDialer, err := c.EgressSelector.Lookup(egressselector.Master.AsNetworkContext())
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									webhookBackend, err = o.WebhookOptions.newUntruncatedBackend(egressDialer)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									webhookBackend, err = o.WebhookOptions.newUntruncatedBackend(nil)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -590,9 +600,9 @@ func (o *AuditWebhookOptions) enabled() bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// newUntruncatedBackend returns a webhook backend without the truncate options applied
 | 
					// newUntruncatedBackend returns a webhook backend without the truncate options applied
 | 
				
			||||||
// this is done so that the same trucate backend can wrap both the webhook and dynamic backends
 | 
					// this is done so that the same trucate backend can wrap both the webhook and dynamic backends
 | 
				
			||||||
func (o *AuditWebhookOptions) newUntruncatedBackend() (audit.Backend, error) {
 | 
					func (o *AuditWebhookOptions) newUntruncatedBackend(customDial utilnet.DialFunc) (audit.Backend, error) {
 | 
				
			||||||
	groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString)
 | 
						groupVersion, _ := schema.ParseGroupVersion(o.GroupVersionString)
 | 
				
			||||||
	webhook, err := pluginwebhook.NewBackend(o.ConfigFile, groupVersion, o.InitialBackoff)
 | 
						webhook, err := pluginwebhook.NewBackend(o.ConfigFile, groupVersion, o.InitialBackoff, customDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("initializing audit webhook: %v", err)
 | 
							return nil, fmt.Errorf("initializing audit webhook: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,7 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
						"k8s.io/apimachinery/pkg/runtime/serializer"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/net"
 | 
						"k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	"k8s.io/client-go/rest"
 | 
						"k8s.io/client-go/rest"
 | 
				
			||||||
	"k8s.io/client-go/tools/clientcmd"
 | 
						"k8s.io/client-go/tools/clientcmd"
 | 
				
			||||||
@@ -61,11 +62,11 @@ func DefaultShouldRetry(err error) bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
 | 
					// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
 | 
				
			||||||
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) {
 | 
					func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
 | 
				
			||||||
	return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout)
 | 
						return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout, customDial)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) {
 | 
					func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration, customDial utilnet.DialFunc) (*GenericWebhook, error) {
 | 
				
			||||||
	for _, groupVersion := range groupVersions {
 | 
						for _, groupVersion := range groupVersions {
 | 
				
			||||||
		if !scheme.IsVersionRegistered(groupVersion) {
 | 
							if !scheme.IsVersionRegistered(groupVersion) {
 | 
				
			||||||
			return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
 | 
								return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
 | 
				
			||||||
@@ -95,6 +96,8 @@ func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact
 | 
				
			|||||||
	codec := codecFactory.LegacyCodec(groupVersions...)
 | 
						codec := codecFactory.LegacyCodec(groupVersions...)
 | 
				
			||||||
	clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
 | 
						clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clientConfig.Dial = customDial
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	restClient, err := rest.UnversionedRESTClientFor(clientConfig)
 | 
						restClient, err := rest.UnversionedRESTClientFor(clientConfig)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -259,7 +259,7 @@ func TestKubeConfigFile(t *testing.T) {
 | 
				
			|||||||
			if err == nil {
 | 
								if err == nil {
 | 
				
			||||||
				defer os.Remove(kubeConfigFile)
 | 
									defer os.Remove(kubeConfigFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				_, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff)
 | 
									_, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, nil)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
@@ -282,7 +282,7 @@ func TestKubeConfigFile(t *testing.T) {
 | 
				
			|||||||
// TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly
 | 
					// TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly
 | 
				
			||||||
func TestMissingKubeConfigFile(t *testing.T) {
 | 
					func TestMissingKubeConfigFile(t *testing.T) {
 | 
				
			||||||
	kubeConfigPath := "/some/missing/path"
 | 
						kubeConfigPath := "/some/missing/path"
 | 
				
			||||||
	_, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff)
 | 
						_, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		t.Errorf("creating the webhook should had failed")
 | 
							t.Errorf("creating the webhook should had failed")
 | 
				
			||||||
@@ -394,7 +394,7 @@ func TestTLSConfig(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			defer os.Remove(configFile)
 | 
								defer os.Remove(configFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
 | 
								wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err == nil {
 | 
								if err == nil {
 | 
				
			||||||
				err = wh.RestClient.Get().Do(context.TODO()).Error()
 | 
									err = wh.RestClient.Get().Do(context.TODO()).Error()
 | 
				
			||||||
@@ -459,7 +459,7 @@ func TestRequestTimeout(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var requestTimeout = 10 * time.Millisecond
 | 
						var requestTimeout = 10 * time.Millisecond
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout)
 | 
						wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("failed to create the webhook: %v", err)
 | 
							t.Fatalf("failed to create the webhook: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -545,7 +545,7 @@ func TestWithExponentialBackoff(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	defer os.Remove(configFile)
 | 
						defer os.Remove(configFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
 | 
						wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("failed to create the webhook: %v", err)
 | 
							t.Fatalf("failed to create the webhook: %v", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ go_library(
 | 
				
			|||||||
    importpath = "k8s.io/apiserver/plugin/pkg/audit/webhook",
 | 
					    importpath = "k8s.io/apiserver/plugin/pkg/audit/webhook",
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/apis/audit:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/apis/audit:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/apis/audit/install:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/apis/audit/install:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/audit:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/audit:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
						auditinternal "k8s.io/apiserver/pkg/apis/audit"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/apis/audit/install"
 | 
						"k8s.io/apiserver/pkg/apis/audit/install"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/audit"
 | 
						"k8s.io/apiserver/pkg/audit"
 | 
				
			||||||
@@ -60,9 +61,9 @@ func retryOnError(err error) bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) {
 | 
					func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (*webhook.GenericWebhook, error) {
 | 
				
			||||||
	w, err := webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile,
 | 
						w, err := webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile,
 | 
				
			||||||
		[]schema.GroupVersion{groupVersion}, initialBackoff)
 | 
							[]schema.GroupVersion{groupVersion}, initialBackoff, customDial)
 | 
				
			||||||
	w.ShouldRetry = retryOnError
 | 
						w.ShouldRetry = retryOnError
 | 
				
			||||||
	return w, err
 | 
						return w, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -86,8 +87,8 @@ func NewDynamicBackend(rc *rest.RESTClient, initialBackoff time.Duration) audit.
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewBackend returns an audit backend that sends events over HTTP to an external service.
 | 
					// NewBackend returns an audit backend that sends events over HTTP to an external service.
 | 
				
			||||||
func NewBackend(kubeConfigFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (audit.Backend, error) {
 | 
					func NewBackend(kubeConfigFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration, customDial utilnet.DialFunc) (audit.Backend, error) {
 | 
				
			||||||
	w, err := loadWebhook(kubeConfigFile, groupVersion, initialBackoff)
 | 
						w, err := loadWebhook(kubeConfigFile, groupVersion, initialBackoff, customDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,7 +106,7 @@ func newWebhook(t *testing.T, endpoint string, groupVersion schema.GroupVersion)
 | 
				
			|||||||
	// NOTE(ericchiang): Do we need to use a proper serializer?
 | 
						// NOTE(ericchiang): Do we need to use a proper serializer?
 | 
				
			||||||
	require.NoError(t, stdjson.NewEncoder(f).Encode(config), "writing kubeconfig")
 | 
						require.NoError(t, stdjson.NewEncoder(f).Encode(config), "writing kubeconfig")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b, err := NewBackend(f.Name(), groupVersion, DefaultInitialBackoff)
 | 
						b, err := NewBackend(f.Name(), groupVersion, DefaultInitialBackoff, nil)
 | 
				
			||||||
	require.NoError(t, err, "initializing backend")
 | 
						require.NoError(t, err, "initializing backend")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return b.(*backend)
 | 
						return b.(*backend)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@ go_library(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ import (
 | 
				
			|||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
						"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/user"
 | 
						"k8s.io/apiserver/pkg/authentication/user"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/util/webhook"
 | 
						"k8s.io/apiserver/pkg/util/webhook"
 | 
				
			||||||
@@ -63,8 +64,8 @@ func NewFromInterface(tokenReview authenticationv1client.TokenReviewInterface, i
 | 
				
			|||||||
// file. It is recommend to wrap this authenticator with the token cache
 | 
					// file. It is recommend to wrap this authenticator with the token cache
 | 
				
			||||||
// authenticator implemented in
 | 
					// authenticator implemented in
 | 
				
			||||||
// k8s.io/apiserver/pkg/authentication/token/cache.
 | 
					// k8s.io/apiserver/pkg/authentication/token/cache.
 | 
				
			||||||
func New(kubeConfigFile string, version string, implicitAuds authenticator.Audiences) (*WebhookTokenAuthenticator, error) {
 | 
					func New(kubeConfigFile string, version string, implicitAuds authenticator.Audiences, customDial utilnet.DialFunc) (*WebhookTokenAuthenticator, error) {
 | 
				
			||||||
	tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile, version)
 | 
						tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile, version, customDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -153,7 +154,7 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
 | 
				
			|||||||
// tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
 | 
					// tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
 | 
				
			||||||
// and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview
 | 
					// and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview
 | 
				
			||||||
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
 | 
					// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
 | 
				
			||||||
func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (tokenReviewer, error) {
 | 
					func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, customDial utilnet.DialFunc) (tokenReviewer, error) {
 | 
				
			||||||
	localScheme := runtime.NewScheme()
 | 
						localScheme := runtime.NewScheme()
 | 
				
			||||||
	if err := scheme.AddToScheme(localScheme); err != nil {
 | 
						if err := scheme.AddToScheme(localScheme); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -165,7 +166,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (
 | 
				
			|||||||
		if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
							if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
 | 
							gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, customDial)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -176,7 +177,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (
 | 
				
			|||||||
		if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
							if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
 | 
							gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, customDial)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -193,7 +193,7 @@ func newV1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte,
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c, err := tokenReviewInterfaceFromKubeconfig(p, "v1")
 | 
						c, err := tokenReviewInterfaceFromKubeconfig(p, "v1", nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -195,7 +195,7 @@ func newV1beta1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c, err := tokenReviewInterfaceFromKubeconfig(p, "v1beta1")
 | 
						c, err := tokenReviewInterfaceFromKubeconfig(p, "v1beta1", nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@ go_library(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/cache"
 | 
						"k8s.io/apimachinery/pkg/util/cache"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/user"
 | 
						"k8s.io/apiserver/pkg/authentication/user"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/util/webhook"
 | 
						"k8s.io/apiserver/pkg/util/webhook"
 | 
				
			||||||
@@ -84,8 +85,8 @@ func NewFromInterface(subjectAccessReview authorizationv1client.SubjectAccessRev
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// For additional HTTP configuration, refer to the kubeconfig documentation
 | 
					// For additional HTTP configuration, refer to the kubeconfig documentation
 | 
				
			||||||
// https://kubernetes.io/docs/user-guide/kubeconfig-file/.
 | 
					// https://kubernetes.io/docs/user-guide/kubeconfig-file/.
 | 
				
			||||||
func New(kubeConfigFile string, version string, authorizedTTL, unauthorizedTTL time.Duration) (*WebhookAuthorizer, error) {
 | 
					func New(kubeConfigFile string, version string, authorizedTTL, unauthorizedTTL time.Duration, customDial utilnet.DialFunc) (*WebhookAuthorizer, error) {
 | 
				
			||||||
	subjectAccessReview, err := subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version)
 | 
						subjectAccessReview, err := subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version, customDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -245,7 +246,7 @@ func convertToSARExtra(extra map[string][]string) map[string]authorizationv1.Ext
 | 
				
			|||||||
// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
 | 
					// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
 | 
				
			||||||
// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
 | 
					// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
 | 
				
			||||||
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
 | 
					// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
 | 
				
			||||||
func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (subjectAccessReviewer, error) {
 | 
					func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, customDial utilnet.DialFunc) (subjectAccessReviewer, error) {
 | 
				
			||||||
	localScheme := runtime.NewScheme()
 | 
						localScheme := runtime.NewScheme()
 | 
				
			||||||
	if err := scheme.AddToScheme(localScheme); err != nil {
 | 
						if err := scheme.AddToScheme(localScheme); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -257,7 +258,7 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
 | 
				
			|||||||
		if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
							if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
 | 
							gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, customDial)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -268,7 +269,7 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
 | 
				
			|||||||
		if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
							if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
 | 
							gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, customDial)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,7 +186,7 @@ current-context: default
 | 
				
			|||||||
				return fmt.Errorf("failed to execute test template: %v", err)
 | 
									return fmt.Errorf("failed to execute test template: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Create a new authorizer
 | 
								// Create a new authorizer
 | 
				
			||||||
			sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1")
 | 
								sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", nil)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return fmt.Errorf("error building sar client: %v", err)
 | 
									return fmt.Errorf("error building sar client: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -325,7 +325,7 @@ func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cache
 | 
				
			|||||||
	if err := json.NewEncoder(tempfile).Encode(config); err != nil {
 | 
						if err := json.NewEncoder(tempfile).Encode(config); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1")
 | 
						sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("error building sar client: %v", err)
 | 
							return nil, fmt.Errorf("error building sar client: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,7 +186,7 @@ current-context: default
 | 
				
			|||||||
				return fmt.Errorf("failed to execute test template: %v", err)
 | 
									return fmt.Errorf("failed to execute test template: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Create a new authorizer
 | 
								// Create a new authorizer
 | 
				
			||||||
			sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1")
 | 
								sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", nil)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return fmt.Errorf("error building sar client: %v", err)
 | 
									return fmt.Errorf("error building sar client: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -325,7 +325,7 @@ func newV1beta1Authorizer(callbackURL string, clientCert, clientKey, ca []byte,
 | 
				
			|||||||
	if err := json.NewEncoder(tempfile).Encode(config); err != nil {
 | 
						if err := json.NewEncoder(tempfile).Encode(config); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1")
 | 
						sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("error building sar client: %v", err)
 | 
							return nil, fmt.Errorf("error building sar client: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,7 @@ go_test(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	authenticationv1beta1 "k8s.io/api/authentication/v1beta1"
 | 
						authenticationv1beta1 "k8s.io/api/authentication/v1beta1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
						"k8s.io/apiserver/pkg/authentication/authenticator"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/group"
 | 
						"k8s.io/apiserver/pkg/authentication/group"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/request/bearertoken"
 | 
						"k8s.io/apiserver/pkg/authentication/request/bearertoken"
 | 
				
			||||||
@@ -69,7 +70,7 @@ func getTestTokenAuth() authenticator.Request {
 | 
				
			|||||||
	return group.NewGroupAdder(bearertoken.New(tokenAuthenticator), []string{user.AllAuthenticated})
 | 
						return group.NewGroupAdder(bearertoken.New(tokenAuthenticator), []string{user.AllAuthenticated})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getTestWebhookTokenAuth(serverURL string) (authenticator.Request, error) {
 | 
					func getTestWebhookTokenAuth(serverURL string, customDial utilnet.DialFunc) (authenticator.Request, error) {
 | 
				
			||||||
	kubecfgFile, err := ioutil.TempFile("", "webhook-kubecfg")
 | 
						kubecfgFile, err := ioutil.TempFile("", "webhook-kubecfg")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -85,13 +86,19 @@ func getTestWebhookTokenAuth(serverURL string) (authenticator.Request, error) {
 | 
				
			|||||||
	if err := json.NewEncoder(kubecfgFile).Encode(config); err != nil {
 | 
						if err := json.NewEncoder(kubecfgFile).Encode(config); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	webhookTokenAuth, err := webhook.New(kubecfgFile.Name(), "v1beta1", nil)
 | 
						webhookTokenAuth, err := webhook.New(kubecfgFile.Name(), "v1beta1", nil, customDial)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return bearertoken.New(cache.New(webhookTokenAuth, false, 2*time.Minute, 2*time.Minute)), nil
 | 
						return bearertoken.New(cache.New(webhookTokenAuth, false, 2*time.Minute, 2*time.Minute)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getTestWebhookTokenAuthCustomDialer(serverURL string) (authenticator.Request, error) {
 | 
				
			||||||
 | 
						customDial := http.DefaultTransport.(*http.Transport).DialContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getTestWebhookTokenAuth(serverURL, customDial)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func path(resource, namespace, name string) string {
 | 
					func path(resource, namespace, name string) string {
 | 
				
			||||||
	return pathWithPrefix("", resource, namespace, name)
 | 
						return pathWithPrefix("", resource, namespace, name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1192,9 +1199,27 @@ func TestReadOnlyAuthorization(t *testing.T) {
 | 
				
			|||||||
// authenticator to call out to a remote web server for authentication
 | 
					// authenticator to call out to a remote web server for authentication
 | 
				
			||||||
// decisions.
 | 
					// decisions.
 | 
				
			||||||
func TestWebhookTokenAuthenticator(t *testing.T) {
 | 
					func TestWebhookTokenAuthenticator(t *testing.T) {
 | 
				
			||||||
 | 
						testWebhookTokenAuthenticator(false, t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TestWebhookTokenAuthenticatorCustomDial is the same as TestWebhookTokenAuthenticator, but uses a
 | 
				
			||||||
 | 
					// custom dialer
 | 
				
			||||||
 | 
					func TestWebhookTokenAuthenticatorCustomDial(t *testing.T) {
 | 
				
			||||||
 | 
						testWebhookTokenAuthenticator(true, t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func testWebhookTokenAuthenticator(customDialer bool, t *testing.T) {
 | 
				
			||||||
	authServer := newTestWebhookTokenAuthServer()
 | 
						authServer := newTestWebhookTokenAuthServer()
 | 
				
			||||||
	defer authServer.Close()
 | 
						defer authServer.Close()
 | 
				
			||||||
	authenticator, err := getTestWebhookTokenAuth(authServer.URL)
 | 
						var authenticator authenticator.Request
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if customDialer == false {
 | 
				
			||||||
 | 
							authenticator, err = getTestWebhookTokenAuth(authServer.URL, nil)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							authenticator, err = getTestWebhookTokenAuthCustomDialer(authServer.URL)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("error starting webhook token authenticator server: %v", err)
 | 
							t.Fatalf("error starting webhook token authenticator server: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user