Skip to content

Commit d318e52

Browse files
committed
authentication webhook via network proxy
1 parent a555825 commit d318e52

File tree

13 files changed

+53
-25
lines changed

13 files changed

+53
-25
lines changed

cmd/kube-apiserver/app/server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ func buildGenericConfig(
498498
}
499499
versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
500500

501-
genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, clientgoExternalClient, versionedInformers)
501+
genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, genericConfig, clientgoExternalClient, versionedInformers)
502502
if err != nil {
503503
lastErr = fmt.Errorf("invalid authentication config: %v", err)
504504
return
@@ -560,7 +560,7 @@ func buildGenericConfig(
560560
}
561561

562562
// BuildAuthenticator constructs the authenticator
563-
func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) {
563+
func BuildAuthenticator(s *options.ServerRunOptions, c *genericapiserver.Config, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) {
564564
authenticatorConfig, err := s.Authentication.ToAuthenticationConfig()
565565
if err != nil {
566566
return nil, nil, err
@@ -577,6 +577,10 @@ func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset
577577
versionedInformer.Core().V1().Secrets().Lister().Secrets(v1.NamespaceSystem),
578578
)
579579

580+
if c.EgressSelector != nil {
581+
authenticatorConfig.EgressLookup = c.EgressSelector.Lookup
582+
}
583+
580584
return authenticatorConfig.New()
581585
}
582586

pkg/kubeapiserver/authenticator/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ go_library(
2525
"//staging/src/k8s.io/apiserver/pkg/authentication/token/tokenfile:go_default_library",
2626
"//staging/src/k8s.io/apiserver/pkg/authentication/token/union:go_default_library",
2727
"//staging/src/k8s.io/apiserver/pkg/server/dynamiccertificates:go_default_library",
28+
"//staging/src/k8s.io/apiserver/pkg/server/egressselector:go_default_library",
2829
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
2930
"//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile:go_default_library",
3031
"//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth:go_default_library",

pkg/kubeapiserver/authenticator/config.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
3535
tokenunion "k8s.io/apiserver/pkg/authentication/token/union"
3636
"k8s.io/apiserver/pkg/server/dynamiccertificates"
37+
"k8s.io/apiserver/pkg/server/egressselector"
3738
utilfeature "k8s.io/apiserver/pkg/util/feature"
3839
"k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile"
3940
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
@@ -83,6 +84,9 @@ type Config struct {
8384
// Generally this is the CA bundle file used to authenticate client certificates
8485
// If this value is nil, then mutual TLS is disabled.
8586
ClientCAContentProvider dynamiccertificates.CAContentProvider
87+
88+
// Lookup will give us a dialer if the egress selector is configured for it
89+
EgressLookup egressselector.Lookup
8690
}
8791

8892
// 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
179183
tokenAuthenticators = append(tokenAuthenticators, authenticator.WrapAudienceAgnosticToken(config.APIAudiences, oidcAuth))
180184
}
181185
if len(config.WebhookTokenAuthnConfigFile) > 0 {
182-
webhookTokenAuth, err := newWebhookTokenAuthenticator(config.WebhookTokenAuthnConfigFile, config.WebhookTokenAuthnVersion, config.WebhookTokenAuthnCacheTTL, config.APIAudiences)
186+
webhookTokenAuth, err := newWebhookTokenAuthenticator(config)
183187
if err != nil {
184188
return nil, nil, err
185189
}
190+
186191
tokenAuthenticators = append(tokenAuthenticators, webhookTokenAuth)
187192
}
188193

@@ -305,8 +310,13 @@ func newServiceAccountAuthenticator(iss string, keyfiles []string, apiAudiences
305310
return tokenAuthenticator, nil
306311
}
307312

308-
func newWebhookTokenAuthenticator(webhookConfigFile string, version string, ttl time.Duration, implicitAuds authenticator.Audiences) (authenticator.Token, error) {
309-
webhookTokenAuthenticator, err := webhook.New(webhookConfigFile, version, implicitAuds)
313+
func newWebhookTokenAuthenticator(config Config) (authenticator.Token, error) {
314+
webhookConfigFile := config.WebhookTokenAuthnConfigFile
315+
version := config.WebhookTokenAuthnVersion
316+
ttl := config.WebhookTokenAuthnCacheTTL
317+
implicitAuds := config.APIAudiences
318+
319+
webhookTokenAuthenticator, err := webhook.New(webhookConfigFile, version, implicitAuds, config.EgressLookup)
310320
if err != nil {
311321
return nil, err
312322
}

plugin/pkg/admission/imagepolicy/admission.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func NewImagePolicyWebhook(configFile io.Reader) (*Plugin, error) {
261261
return nil, err
262262
}
263263

264-
gw, err := webhook.NewGenericWebhook(legacyscheme.Scheme, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff)
264+
gw, err := webhook.NewGenericWebhook(legacyscheme.Scheme, legacyscheme.Codecs, whConfig.KubeConfigFile, groupVersions, whConfig.RetryBackoff, nil)
265265
if err != nil {
266266
return nil, err
267267
}

staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
"k8s.io/apimachinery/pkg/runtime/schema"
2828
"k8s.io/apimachinery/pkg/runtime/serializer"
2929
"k8s.io/apimachinery/pkg/util/net"
30+
utilnet "k8s.io/apimachinery/pkg/util/net"
3031
"k8s.io/apimachinery/pkg/util/wait"
32+
"k8s.io/apiserver/pkg/server/egressselector"
3133
"k8s.io/client-go/rest"
3234
"k8s.io/client-go/tools/clientcmd"
3335
)
@@ -61,11 +63,11 @@ func DefaultShouldRetry(err error) bool {
6163
}
6264

6365
// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
64-
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration) (*GenericWebhook, error) {
65-
return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout)
66+
func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff time.Duration, egressLookup egressselector.Lookup) (*GenericWebhook, error) {
67+
return newGenericWebhook(scheme, codecFactory, kubeConfigFile, groupVersions, initialBackoff, defaultRequestTimeout, egressLookup)
6668
}
6769

68-
func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration) (*GenericWebhook, error) {
70+
func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFactory, kubeConfigFile string, groupVersions []schema.GroupVersion, initialBackoff, requestTimeout time.Duration, egressLookup egressselector.Lookup) (*GenericWebhook, error) {
6971
for _, groupVersion := range groupVersions {
7072
if !scheme.IsVersionRegistered(groupVersion) {
7173
return nil, fmt.Errorf("webhook plugin requires enabling extension resource: %s", groupVersion)
@@ -94,6 +96,15 @@ func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact
9496

9597
codec := codecFactory.LegacyCodec(groupVersions...)
9698
clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
99+
if egressLookup != nil {
100+
networkContext := egressselector.Master.AsNetworkContext()
101+
var egressDialer utilnet.DialFunc
102+
egressDialer, err = egressLookup(networkContext)
103+
if err != nil {
104+
return nil, err
105+
}
106+
clientConfig.Dial = egressDialer
107+
}
97108

98109
restClient, err := rest.UnversionedRESTClientFor(clientConfig)
99110
if err != nil {

staging/src/k8s.io/apiserver/pkg/util/webhook/webhook_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ func TestKubeConfigFile(t *testing.T) {
259259
if err == nil {
260260
defer os.Remove(kubeConfigFile)
261261

262-
_, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff)
262+
_, err = NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, nil)
263263
}
264264

265265
return err
@@ -282,7 +282,7 @@ func TestKubeConfigFile(t *testing.T) {
282282
// TestMissingKubeConfigFile ensures that a kube config path to a missing file is handled properly
283283
func TestMissingKubeConfigFile(t *testing.T) {
284284
kubeConfigPath := "/some/missing/path"
285-
_, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff)
285+
_, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, kubeConfigPath, groupVersions, retryBackoff, nil)
286286

287287
if err == nil {
288288
t.Errorf("creating the webhook should had failed")
@@ -394,7 +394,7 @@ func TestTLSConfig(t *testing.T) {
394394

395395
defer os.Remove(configFile)
396396

397-
wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
397+
wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, nil)
398398

399399
if err == nil {
400400
err = wh.RestClient.Get().Do(context.TODO()).Error()
@@ -459,7 +459,7 @@ func TestRequestTimeout(t *testing.T) {
459459

460460
var requestTimeout = 10 * time.Millisecond
461461

462-
wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout)
462+
wh, err := newGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, requestTimeout, nil)
463463
if err != nil {
464464
t.Fatalf("failed to create the webhook: %v", err)
465465
}
@@ -545,7 +545,7 @@ func TestWithExponentialBackoff(t *testing.T) {
545545

546546
defer os.Remove(configFile)
547547

548-
wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff)
548+
wh, err := NewGenericWebhook(runtime.NewScheme(), scheme.Codecs, configFile, groupVersions, retryBackoff, nil)
549549

550550
if err != nil {
551551
t.Fatalf("failed to create the webhook: %v", err)

staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func retryOnError(err error) bool {
6262

6363
func loadWebhook(configFile string, groupVersion schema.GroupVersion, initialBackoff time.Duration) (*webhook.GenericWebhook, error) {
6464
w, err := webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile,
65-
[]schema.GroupVersion{groupVersion}, initialBackoff)
65+
[]schema.GroupVersion{groupVersion}, initialBackoff, nil)
6666
w.ShouldRetry = retryOnError
6767
return w, err
6868
}

staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ go_library(
4141
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
4242
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
4343
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
44+
"//staging/src/k8s.io/apiserver/pkg/server/egressselector:go_default_library",
4445
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
4546
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
4647
"//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library",

staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"k8s.io/apimachinery/pkg/runtime/schema"
3131
"k8s.io/apiserver/pkg/authentication/authenticator"
3232
"k8s.io/apiserver/pkg/authentication/user"
33+
"k8s.io/apiserver/pkg/server/egressselector"
3334
"k8s.io/apiserver/pkg/util/webhook"
3435
"k8s.io/client-go/kubernetes/scheme"
3536
authenticationv1client "k8s.io/client-go/kubernetes/typed/authentication/v1"
@@ -63,8 +64,8 @@ func NewFromInterface(tokenReview authenticationv1client.TokenReviewInterface, i
6364
// file. It is recommend to wrap this authenticator with the token cache
6465
// authenticator implemented in
6566
// k8s.io/apiserver/pkg/authentication/token/cache.
66-
func New(kubeConfigFile string, version string, implicitAuds authenticator.Audiences) (*WebhookTokenAuthenticator, error) {
67-
tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile, version)
67+
func New(kubeConfigFile string, version string, implicitAuds authenticator.Audiences, egressLookup egressselector.Lookup) (*WebhookTokenAuthenticator, error) {
68+
tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile, version, egressLookup)
6869
if err != nil {
6970
return nil, err
7071
}
@@ -153,7 +154,7 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
153154
// tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
154155
// and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview
155156
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
156-
func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (tokenReviewer, error) {
157+
func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, egressLookup egressselector.Lookup) (tokenReviewer, error) {
157158
localScheme := runtime.NewScheme()
158159
if err := scheme.AddToScheme(localScheme); err != nil {
159160
return nil, err
@@ -165,7 +166,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (
165166
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
166167
return nil, err
167168
}
168-
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
169+
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, egressLookup)
169170
if err != nil {
170171
return nil, err
171172
}
@@ -176,7 +177,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string) (
176177
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
177178
return nil, err
178179
}
179-
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0)
180+
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, 0, egressLookup)
180181
if err != nil {
181182
return nil, err
182183
}

staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook/webhook_v1_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func newV1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte,
193193
return nil, err
194194
}
195195

196-
c, err := tokenReviewInterfaceFromKubeconfig(p, "v1")
196+
c, err := tokenReviewInterfaceFromKubeconfig(p, "v1", nil)
197197
if err != nil {
198198
return nil, err
199199
}

0 commit comments

Comments
 (0)