Use SSH tunnel for webhook communication iff the webhook is deployed as a service

This commit is contained in:
Yang Guo
2018-01-22 16:18:34 -08:00
parent ddea2dd56f
commit 454276c23c
6 changed files with 21 additions and 14 deletions

View File

@@ -460,15 +460,17 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
} }
webhookAuthResolver := func(delegate webhookconfig.AuthenticationInfoResolver) webhookconfig.AuthenticationInfoResolver { webhookAuthResolver := func(delegate webhookconfig.AuthenticationInfoResolver) webhookconfig.AuthenticationInfoResolver {
return webhookconfig.AuthenticationInfoResolverFunc(func(server string) (*rest.Config, error) { return webhookconfig.AuthenticationInfoResolverFunc(func(server string, directRouting bool) (*rest.Config, error) {
if server == "kubernetes.default.svc" { if server == "kubernetes.default.svc" {
return genericConfig.LoopbackClientConfig, nil return genericConfig.LoopbackClientConfig, nil
} }
ret, err := delegate.ClientConfigFor(server) ret, err := delegate.ClientConfigFor(server, directRouting)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if proxyTransport != nil && proxyTransport.Dial != nil { if !directRouting && proxyTransport != nil && proxyTransport.Dial != nil {
// Use the SSH tunnels iff the webhook server is not directly
// routable from apiserver's network environment.
ret.Dial = proxyTransport.Dial ret.Dial = proxyTransport.Dial
} }
return ret, err return ret, err

View File

@@ -31,17 +31,22 @@ import (
// rest.Config generated by the resolver. // rest.Config generated by the resolver.
type AuthenticationInfoResolverWrapper func(AuthenticationInfoResolver) AuthenticationInfoResolver type AuthenticationInfoResolverWrapper func(AuthenticationInfoResolver) AuthenticationInfoResolver
// AuthenticationInfoResolver builds rest.Config base on the server name. // AuthenticationInfoResolver builds rest.Config base on the server name and
// the directRouting flag indicating whether the webhook server is routable
// directly from apiserver's network environment.
//
// TODO(yguo0905): Remove the directRouting flag once the SSH tunnels that is
// used for the communication from master to nodes get removed.
type AuthenticationInfoResolver interface { type AuthenticationInfoResolver interface {
ClientConfigFor(server string) (*rest.Config, error) ClientConfigFor(server string, directRouting bool) (*rest.Config, error)
} }
// AuthenticationInfoResolverFunc implements AuthenticationInfoResolver. // AuthenticationInfoResolverFunc implements AuthenticationInfoResolver.
type AuthenticationInfoResolverFunc func(server string) (*rest.Config, error) type AuthenticationInfoResolverFunc func(server string, directRouting bool) (*rest.Config, error)
//ClientConfigFor implements AuthenticationInfoResolver. //ClientConfigFor implements AuthenticationInfoResolver.
func (a AuthenticationInfoResolverFunc) ClientConfigFor(server string) (*rest.Config, error) { func (a AuthenticationInfoResolverFunc) ClientConfigFor(server string, directRouting bool) (*rest.Config, error) {
return a(server) return a(server, directRouting)
} }
type defaultAuthenticationInfoResolver struct { type defaultAuthenticationInfoResolver struct {
@@ -67,7 +72,7 @@ func NewDefaultAuthenticationInfoResolver(kubeconfigFile string) (Authentication
return &defaultAuthenticationInfoResolver{kubeconfig: clientConfig}, nil return &defaultAuthenticationInfoResolver{kubeconfig: clientConfig}, nil
} }
func (c *defaultAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { func (c *defaultAuthenticationInfoResolver) ClientConfigFor(server string, directRouting bool) (*rest.Config, error) {
// exact match // exact match
if authConfig, ok := c.kubeconfig.AuthInfos[server]; ok { if authConfig, ok := c.kubeconfig.AuthInfos[server]; ok {
return restConfigFromKubeconfig(authConfig) return restConfigFromKubeconfig(authConfig)

View File

@@ -114,7 +114,7 @@ func TestAuthenticationDetection(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
resolver := defaultAuthenticationInfoResolver{kubeconfig: tc.kubeconfig} resolver := defaultAuthenticationInfoResolver{kubeconfig: tc.kubeconfig}
actual, err := resolver.ClientConfigFor(tc.serverName) actual, err := resolver.ClientConfigFor(tc.serverName, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@@ -123,7 +123,7 @@ func (cm *ClientManager) HookClient(h *v1beta1.Webhook) (*rest.RESTClient, error
if svc := h.ClientConfig.Service; svc != nil { if svc := h.ClientConfig.Service; svc != nil {
serverName := svc.Name + "." + svc.Namespace + ".svc" serverName := svc.Name + "." + svc.Namespace + ".svc"
restConfig, err := cm.authInfoResolver.ClientConfigFor(serverName) restConfig, err := cm.authInfoResolver.ClientConfigFor(serverName, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -162,7 +162,7 @@ func (cm *ClientManager) HookClient(h *v1beta1.Webhook) (*rest.RESTClient, error
return nil, &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Unparsable URL: %v", err)} return nil, &webhookerrors.ErrCallingWebhook{WebhookName: h.Name, Reason: fmt.Errorf("Unparsable URL: %v", err)}
} }
restConfig, err := cm.authInfoResolver.ClientConfigFor(u.Host) restConfig, err := cm.authInfoResolver.ClientConfigFor(u.Host, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -631,7 +631,7 @@ type fakeAuthenticationInfoResolver struct {
cachedCount *int32 cachedCount *int32
} }
func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string, directRouting bool) (*rest.Config, error) {
atomic.AddInt32(c.cachedCount, 1) atomic.AddInt32(c.cachedCount, 1)
return c.restConfig, nil return c.restConfig, nil
} }

View File

@@ -656,7 +656,7 @@ type fakeAuthenticationInfoResolver struct {
cachedCount *int32 cachedCount *int32
} }
func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) { func (c *fakeAuthenticationInfoResolver) ClientConfigFor(server string, directRouting bool) (*rest.Config, error) {
atomic.AddInt32(c.cachedCount, 1) atomic.AddInt32(c.cachedCount, 1)
return c.restConfig, nil return c.restConfig, nil
} }