From 18d0325d5c7c66f0b14004a78260ecfd4cb6f7e6 Mon Sep 17 00:00:00 2001 From: David Eads Date: Wed, 18 Oct 2017 12:57:59 -0400 Subject: [PATCH] update admission webhook to accept client config Kubernetes-commit: 0859798e8e278ec382dcbeb77914f40bf2c78a2c --- rest/config.go | 40 ++++++++++++++++++ rest/config_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/rest/config.go b/rest/config.go index 57848c8a..038fee94 100644 --- a/rest/config.go +++ b/rest/config.go @@ -420,5 +420,45 @@ func AnonymousClientConfig(config *Config) *Config { QPS: config.QPS, Burst: config.Burst, Timeout: config.Timeout, + Dial: config.Dial, + } +} + +// CopyConfig returns a copy of the given config +func CopyConfig(config *Config) *Config { + return &Config{ + Host: config.Host, + APIPath: config.APIPath, + Prefix: config.Prefix, + ContentConfig: config.ContentConfig, + Username: config.Username, + Password: config.Password, + BearerToken: config.BearerToken, + CacheDir: config.CacheDir, + Impersonate: ImpersonationConfig{ + Groups: config.Impersonate.Groups, + Extra: config.Impersonate.Extra, + UserName: config.Impersonate.UserName, + }, + AuthProvider: config.AuthProvider, + AuthConfigPersister: config.AuthConfigPersister, + TLSClientConfig: TLSClientConfig{ + Insecure: config.TLSClientConfig.Insecure, + ServerName: config.TLSClientConfig.ServerName, + CertFile: config.TLSClientConfig.CertFile, + KeyFile: config.TLSClientConfig.KeyFile, + CAFile: config.TLSClientConfig.CAFile, + CertData: config.TLSClientConfig.CertData, + KeyData: config.TLSClientConfig.KeyData, + CAData: config.TLSClientConfig.CAData, + }, + UserAgent: config.UserAgent, + Transport: config.Transport, + WrapTransport: config.WrapTransport, + QPS: config.QPS, + Burst: config.Burst, + RateLimiter: config.RateLimiter, + Timeout: config.Timeout, + Dial: config.Dial, } } diff --git a/rest/config_test.go b/rest/config_test.go index ff851e6a..0e86442d 100644 --- a/rest/config_test.go +++ b/rest/config_test.go @@ -35,6 +35,8 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/util/flowcontrol" + "errors" + "github.com/stretchr/testify/assert" ) @@ -206,6 +208,19 @@ func (n *fakeNegotiatedSerializer) DecoderToVersion(serializer runtime.Decoder, return &fakeCodec{} } +var fakeDialFunc = func(network, addr string) (net.Conn, error) { + return nil, fakeDialerError +} +var fakeDialerError = errors.New("fakedialer") + +type fakeAuthProviderConfigPersister struct{} + +func (fakeAuthProviderConfigPersister) Persist(map[string]string) error { + return fakeAuthProviderConfigPersisterError +} + +var fakeAuthProviderConfigPersisterError = errors.New("fakeAuthProviderConfigPersisterError") + func TestAnonymousConfig(t *testing.T) { f := fuzz.New().NilChance(0.0).NumElements(1, 1) f.Funcs( @@ -268,9 +283,94 @@ func TestAnonymousConfig(t *testing.T) { actual.WrapTransport = nil expected.WrapTransport = nil } + if actual.Dial != nil { + _, actualError := actual.Dial("", "") + _, expectedError := actual.Dial("", "") + if !reflect.DeepEqual(expectedError, actualError) { + t.Fatalf("CopyConfig dropped the Dial field") + } + } else { + actual.Dial = nil + expected.Dial = nil + } if !reflect.DeepEqual(*actual, expected) { t.Fatalf("AnonymousClientConfig dropped unexpected fields, identify whether they are security related or not: %s", diff.ObjectGoPrintDiff(expected, actual)) } } } + +func TestCopyConfig(t *testing.T) { + f := fuzz.New().NilChance(0.0).NumElements(1, 1) + f.Funcs( + func(r *runtime.Codec, f fuzz.Continue) { + codec := &fakeCodec{} + f.Fuzz(codec) + *r = codec + }, + func(r *http.RoundTripper, f fuzz.Continue) { + roundTripper := &fakeRoundTripper{} + f.Fuzz(roundTripper) + *r = roundTripper + }, + func(fn *func(http.RoundTripper) http.RoundTripper, f fuzz.Continue) { + *fn = fakeWrapperFunc + }, + func(r *runtime.NegotiatedSerializer, f fuzz.Continue) { + serializer := &fakeNegotiatedSerializer{} + f.Fuzz(serializer) + *r = serializer + }, + func(r *flowcontrol.RateLimiter, f fuzz.Continue) { + limiter := &fakeLimiter{} + f.Fuzz(limiter) + *r = limiter + }, + func(r *AuthProviderConfigPersister, f fuzz.Continue) { + *r = fakeAuthProviderConfigPersister{} + }, + func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) { + *r = fakeDialFunc + }, + ) + for i := 0; i < 20; i++ { + original := &Config{} + f.Fuzz(original) + actual := CopyConfig(original) + expected := *original + + // this is the list of known risky fields, add to this list if a new field + // is added to Config, update CopyConfig to preserve the field otherwise. + + // The DeepEqual cannot handle the func comparison, so we just verify if the + // function return the expected object. + if actual.WrapTransport == nil || !reflect.DeepEqual(expected.WrapTransport(nil), &fakeRoundTripper{}) { + t.Fatalf("CopyConfig dropped the WrapTransport field") + } else { + actual.WrapTransport = nil + expected.WrapTransport = nil + } + if actual.Dial != nil { + _, actualError := actual.Dial("", "") + _, expectedError := actual.Dial("", "") + if !reflect.DeepEqual(expectedError, actualError) { + t.Fatalf("CopyConfig dropped the Dial field") + } + } + actual.Dial = nil + expected.Dial = nil + if actual.AuthConfigPersister != nil { + actualError := actual.AuthConfigPersister.Persist(nil) + expectedError := actual.AuthConfigPersister.Persist(nil) + if !reflect.DeepEqual(expectedError, actualError) { + t.Fatalf("CopyConfig dropped the Dial field") + } + } + actual.AuthConfigPersister = nil + expected.AuthConfigPersister = nil + + if !reflect.DeepEqual(*actual, expected) { + t.Fatalf("CopyConfig dropped unexpected fields, identify whether they are security related or not: %s", diff.ObjectReflectDiff(expected, *actual)) + } + } +}