From d7cdcba883554fd455fc1ee894eb093d4e11492a Mon Sep 17 00:00:00 2001 From: David Eads Date: Thu, 12 Oct 2017 14:30:54 -0400 Subject: [PATCH 1/6] UPSTREAM: 52673: default service resolver for webhook admission --- .../kubeapiserver/admission/initializer.go | 3 - .../plugin/pkg/admission/webhook/BUILD | 2 + .../plugin/pkg/admission/webhook/admission.go | 7 ++- .../pkg/admission/webhook/serviceresolver.go | 42 ++++++++++++++ .../admission/webhook/serviceresolver_test.go | 57 +++++++++++++++++++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver.go create mode 100644 vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver_test.go diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go index 95b83dcd3ecc..f93a9d930661 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go @@ -174,9 +174,6 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) { } if wants, ok := plugin.(WantsServiceResolver); ok { - if i.serviceResolver == nil { - panic("An admission plugin wants the service resolver, but it was not provided.") - } wants.SetServiceResolver(i.serviceResolver) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD index 5faad954b69c..97a76b2c0a94 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD @@ -14,6 +14,7 @@ go_test( "admission_test.go", "certs_test.go", "rules_test.go", + "serviceresolver_test.go", ], library = ":go_default_library", tags = ["automanaged"], @@ -35,6 +36,7 @@ go_library( "admission.go", "doc.go", "rules.go", + "serviceresolver.go", ], tags = ["automanaged"], deps = [ diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go index 6236fb4fa987..81e611fb0338 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go @@ -94,6 +94,7 @@ func NewGenericAdmissionWebhook() (*GenericAdmissionWebhook, error) { negotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{ Serializer: api.Codecs.LegacyCodec(admissionv1alpha1.SchemeGroupVersion), }), + serviceResolver: defaultServiceResolver{}, }, nil } @@ -113,8 +114,12 @@ var ( _ = admissioninit.WantsExternalKubeClientSet(&GenericAdmissionWebhook{}) ) +// 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) { - a.serviceResolver = sr + if sr != nil { + a.serviceResolver = sr + } } func (a *GenericAdmissionWebhook) SetClientCert(cert, key []byte) { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver.go new file mode 100644 index 000000000000..018402934fef --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver.go @@ -0,0 +1,42 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package webhook checks a webhook for configured operation admission +package webhook + +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: +// name=ross namespace=andromeda resolves to https://ross.andromeda.svc +func (sr defaultServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { + if len(name) == 0 || len(namespace) == 0 { + return &url.URL{}, errors.New("cannot resolve an empty service name or namespace") + } + + return url.Parse(fmt.Sprintf("https://%s.%s.svc", name, namespace)) +} diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver_test.go new file mode 100644 index 000000000000..3fb2f7a53c58 --- /dev/null +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/serviceresolver_test.go @@ -0,0 +1,57 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package webhook checks a webhook for configured operation admission +package webhook + +import ( + "fmt" + "testing" +) + +func TestDefaultServiceResolver(t *testing.T) { + scenarios := []struct { + serviceName string + serviceNamespace string + expectedOutput string + expectError bool + }{ + // scenario 1: a service name along with a namespace resolves + {serviceName: "ross", serviceNamespace: "andromeda", expectedOutput: "https://ross.andromeda.svc"}, + // scenario 2: a service name without a namespace does not resolve + {serviceName: "ross", expectError: true}, + // scenario 3: cannot resolve an empty service name + {serviceNamespace: "andromeda", expectError: true}, + } + + // act + for index, scenario := range scenarios { + t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) { + target := defaultServiceResolver{} + serviceURL, err := target.ResolveEndpoint(scenario.serviceNamespace, scenario.serviceName) + + if err != nil && !scenario.expectError { + t.Errorf("unexpected error has occurred = %v", err) + } + if err == nil && scenario.expectError { + t.Error("expected an error but got nothing") + } + if serviceURL.String() != scenario.expectedOutput { + t.Errorf("expected = %s, got = %s", scenario.expectedOutput, serviceURL.String()) + } + }) + } +} From 0db40a63031a883216ebee5f5238bd38678ce935 Mon Sep 17 00:00:00 2001 From: David Eads Date: Thu, 12 Oct 2017 14:25:05 -0400 Subject: [PATCH 2/6] turn admission webhooks on in cluster up --- pkg/cmd/server/api/latest/helpers.go | 1 - .../origin/admission/plugin_initializer.go | 9 +++++ pkg/cmd/server/origin/aggregator.go | 37 ++++++++++--------- pkg/oc/bootstrap/docker/openshift/helper.go | 16 ++++---- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/pkg/cmd/server/api/latest/helpers.go b/pkg/cmd/server/api/latest/helpers.go index e1131f4c8acd..4d2f01d57e1b 100644 --- a/pkg/cmd/server/api/latest/helpers.go +++ b/pkg/cmd/server/api/latest/helpers.go @@ -167,7 +167,6 @@ func ConvertOpenshiftAdmissionConfigToKubeAdmissionConfig(in map[string]configap for _, pluginName := range sets.StringKeySet(in).List() { openshiftConfig := in[pluginName] - fmt.Printf("#### adding for %T\n", openshiftConfig.Configuration) kubeConfig := apiserver.AdmissionPluginConfiguration{ Name: pluginName, Path: openshiftConfig.Location, diff --git a/pkg/cmd/server/origin/admission/plugin_initializer.go b/pkg/cmd/server/origin/admission/plugin_initializer.go index 087b4e11b7e1..c5f635e3aacc 100644 --- a/pkg/cmd/server/origin/admission/plugin_initializer.go +++ b/pkg/cmd/server/origin/admission/plugin_initializer.go @@ -36,6 +36,7 @@ import ( kubeclientgoinformers "k8s.io/client-go/informers" kubeclientgoclient "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver" kclientsetexternal "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" kclientsetinternal "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" kexternalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions" @@ -144,6 +145,14 @@ func NewPluginInitializer( cloudConfig, restMapper, quotaRegistry) + // upstream broke this, so we can't use their mechanism. We need to get an actual client cert and practically speaking privileged loopback will always have one + kubePluginInitializer.SetClientCert(privilegedLoopbackConfig.TLSClientConfig.CertData, privilegedLoopbackConfig.TLSClientConfig.KeyData) + // this is a really problematic thing, because it breaks DNS resolution and IP routing, but its for an alpha feature that + // I need to work cluster-up + kubePluginInitializer.SetServiceResolver(aggregatorapiserver.NewClusterIPServiceResolver( + informers.GetClientGoKubeInformers().Core().V1().Services().Lister(), + )) + openshiftPluginInitializer := &oadmission.PluginInitializer{ OpenshiftInternalAuthorizationClient: authorizationClient, OpenshiftInternalBuildClient: buildClient, diff --git a/pkg/cmd/server/origin/aggregator.go b/pkg/cmd/server/origin/aggregator.go index 16cfb66810a0..bd8ab42826ca 100644 --- a/pkg/cmd/server/origin/aggregator.go +++ b/pkg/cmd/server/origin/aggregator.go @@ -176,24 +176,25 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ // can reasonably expect seems questionable. {Group: "extensions", Version: "v1beta1"}: {group: 17900, version: 1}, // to my knowledge, nothing below here collides - {Group: "apps", Version: "v1beta1"}: {group: 17800, version: 1}, - {Group: "authentication.k8s.io", Version: "v1"}: {group: 17700, version: 15}, - {Group: "authentication.k8s.io", Version: "v1beta1"}: {group: 17700, version: 9}, - {Group: "authorization.k8s.io", Version: "v1"}: {group: 17600, version: 15}, - {Group: "authorization.k8s.io", Version: "v1beta1"}: {group: 17600, version: 9}, - {Group: "autoscaling", Version: "v1"}: {group: 17500, version: 15}, - {Group: "autoscaling", Version: "v2alpha1"}: {group: 17500, version: 9}, - {Group: "batch", Version: "v1"}: {group: 17400, version: 15}, - {Group: "batch", Version: "v2alpha1"}: {group: 17400, version: 9}, - {Group: "certificates.k8s.io", Version: "v1beta1"}: {group: 17300, version: 9}, - {Group: "networking.k8s.io", Version: "v1"}: {group: 17200, version: 15}, - {Group: "policy", Version: "v1beta1"}: {group: 17100, version: 9}, - {Group: "rbac.authorization.k8s.io", Version: "v1beta1"}: {group: 17000, version: 12}, - {Group: "rbac.authorization.k8s.io", Version: "v1alpha1"}: {group: 17000, version: 9}, - {Group: "settings.k8s.io", Version: "v1alpha1"}: {group: 16900, version: 9}, - {Group: "storage.k8s.io", Version: "v1"}: {group: 16800, version: 15}, - {Group: "storage.k8s.io", Version: "v1beta1"}: {group: 16800, version: 9}, - {Group: "apiextensions.k8s.io", Version: "v1beta1"}: {group: 16700, version: 9}, + {Group: "apps", Version: "v1beta1"}: {group: 17800, version: 1}, + {Group: "authentication.k8s.io", Version: "v1"}: {group: 17700, version: 15}, + {Group: "authentication.k8s.io", Version: "v1beta1"}: {group: 17700, version: 9}, + {Group: "authorization.k8s.io", Version: "v1"}: {group: 17600, version: 15}, + {Group: "authorization.k8s.io", Version: "v1beta1"}: {group: 17600, version: 9}, + {Group: "autoscaling", Version: "v1"}: {group: 17500, version: 15}, + {Group: "autoscaling", Version: "v2alpha1"}: {group: 17500, version: 9}, + {Group: "batch", Version: "v1"}: {group: 17400, version: 15}, + {Group: "batch", Version: "v2alpha1"}: {group: 17400, version: 9}, + {Group: "certificates.k8s.io", Version: "v1beta1"}: {group: 17300, version: 9}, + {Group: "networking.k8s.io", Version: "v1"}: {group: 17200, version: 15}, + {Group: "policy", Version: "v1beta1"}: {group: 17100, version: 9}, + {Group: "rbac.authorization.k8s.io", Version: "v1beta1"}: {group: 17000, version: 12}, + {Group: "rbac.authorization.k8s.io", Version: "v1alpha1"}: {group: 17000, version: 9}, + {Group: "settings.k8s.io", Version: "v1alpha1"}: {group: 16900, version: 9}, + {Group: "storage.k8s.io", Version: "v1"}: {group: 16800, version: 15}, + {Group: "storage.k8s.io", Version: "v1beta1"}: {group: 16800, version: 9}, + {Group: "apiextensions.k8s.io", Version: "v1beta1"}: {group: 16700, version: 9}, + {Group: "admissionregistration.k8s.io", Version: "v1alpha1"}: {group: 16700, version: 9}, // arbitrarily starting openshift around 10000. // bump authorization above RBAC diff --git a/pkg/oc/bootstrap/docker/openshift/helper.go b/pkg/oc/bootstrap/docker/openshift/helper.go index a1a3a4487de2..dcadc8d928c5 100644 --- a/pkg/oc/bootstrap/docker/openshift/helper.go +++ b/pkg/oc/bootstrap/docker/openshift/helper.go @@ -696,16 +696,21 @@ func useAggregator(version semver.Version) bool { return version.GTE(version37) } -func useTemplateServiceBroker(version semver.Version) bool { - return version.GTE(version37) -} - func (h *Helper) updateConfig(configDir string, opt *StartOptions) error { cfg, configPath, err := h.GetConfigFromLocalDir(configDir) if err != nil { return err } + // turn on admission webhooks by default. They are no-ops until someone explicitly tries to configure one + if cfg.AdmissionConfig.PluginConfig == nil { + cfg.AdmissionConfig.PluginConfig = map[string]configapi.AdmissionPluginConfig{} + } + cfg.AdmissionConfig.PluginConfig["GenericAdmissionWebhook"] = configapi.AdmissionPluginConfig{ + Configuration: &configapi.DefaultAdmissionConfig{}, + } + cfg.KubernetesMasterConfig.APIServerArguments["runtime-config"] = append(cfg.KubernetesMasterConfig.APIServerArguments["runtime-config"], "apis/admissionregistration.k8s.io/v1alpha1=true") + if len(opt.RoutingSuffix) > 0 { cfg.RoutingConfig.Subdomain = opt.RoutingSuffix } else { @@ -721,9 +726,6 @@ func (h *Helper) updateConfig(configDir string, opt *StartOptions) error { } if len(opt.HTTPProxy) > 0 || len(opt.HTTPSProxy) > 0 || len(opt.NoProxy) > 0 { - if cfg.AdmissionConfig.PluginConfig == nil { - cfg.AdmissionConfig.PluginConfig = map[string]configapi.AdmissionPluginConfig{} - } var buildDefaults *defaultsapi.BuildDefaultsConfig buildDefaultsConfig, ok := cfg.AdmissionConfig.PluginConfig[defaultsapi.BuildDefaultsPlugin] From ea12582c68c334ebd6023ee3df61cf9b58db0112 Mon Sep 17 00:00:00 2001 From: David Eads Date: Thu, 12 Oct 2017 16:01:15 -0400 Subject: [PATCH 3/6] UPSTREAM: 53823: allow fail close webhook admission --- .../validation/validation.go | 10 ++-- .../validation/validation_test.go | 6 +-- .../plugin/pkg/admission/webhook/admission.go | 5 +- .../pkg/admission/webhook/admission_test.go | 47 +++++++++++++++++++ 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go index 4c478f457e04..d6e45cb292bc 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go @@ -199,13 +199,17 @@ func validateExternalAdmissionHook(hook *admissionregistration.ExternalAdmission for i, rule := range hook.Rules { allErrors = append(allErrors, validateRuleWithOperations(&rule, fldPath.Child("rules").Index(i))...) } - // TODO: relax the validation rule when admissionregistration is beta. - if hook.FailurePolicy != nil && *hook.FailurePolicy != admissionregistration.Ignore { - allErrors = append(allErrors, field.NotSupported(fldPath.Child("failurePolicy"), *hook.FailurePolicy, []string{string(admissionregistration.Ignore)})) + if hook.FailurePolicy != nil && !supportedFailurePolicies.Has(string(*hook.FailurePolicy)) { + allErrors = append(allErrors, field.NotSupported(fldPath.Child("failurePolicy"), *hook.FailurePolicy, supportedFailurePolicies.List())) } return allErrors } +var supportedFailurePolicies = sets.NewString( + string(admissionregistration.Ignore), + string(admissionregistration.Fail), +) + var supportedOperations = sets.NewString( string(admissionregistration.OperationAll), string(admissionregistration.Create), diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation_test.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation_test.go index a864ac3a8663..733e0a5630c3 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation_test.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation_test.go @@ -483,18 +483,18 @@ func TestValidateExternalAdmissionHookConfiguration(t *testing.T) { expectedError: `externalAdmissionHooks[0].rules[0].resources: Invalid value: []string{"*/*", "a"}: if '*/*' is present, must not specify other resources`, }, { - name: "FailurePolicy can only be \"Ignore\"", + name: "FailurePolicy can only be \"Ignore\" or \"Fail\"", config: getExternalAdmissionHookConfiguration( []admissionregistration.ExternalAdmissionHook{ { Name: "webhook.k8s.io", FailurePolicy: func() *admissionregistration.FailurePolicyType { - r := admissionregistration.Fail + r := admissionregistration.FailurePolicyType("other") return &r }(), }, }), - expectedError: `failurePolicy: Unsupported value: "Fail": supported values: Ignore`, + expectedError: `failurePolicy: Unsupported value: "other": supported values: Fail, Ignore`, }, } for _, test := range tests { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go index 81e611fb0338..692e73f39cb7 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go @@ -173,9 +173,12 @@ func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error { for i := range hooks { go func(hook *v1alpha1.ExternalAdmissionHook) { defer wg.Done() + + ignoreClientCallFailures := hook.FailurePolicy == nil || *hook.FailurePolicy == v1alpha1.Ignore + if err := a.callHook(ctx, hook, attr); err == nil { return - } else if callErr, ok := err.(*ErrCallingWebhook); ok { + } else if callErr, ok := err.(*ErrCallingWebhook); ignoreClientCallFailures && ok { glog.Warningf("Failed calling webhook %v: %v", hook.Name, callErr) utilruntime.HandleError(callErr) // Since we are failing open to begin with, we do not send an error down the channel diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go index 5e2380421bb1..c6d845201c19 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go @@ -143,6 +143,9 @@ func TestAdmit(t *testing.T) { }, }} + policyFail := registrationv1alpha1.Fail + policyIgnore := registrationv1alpha1.Ignore + table := map[string]test{ "no match": { hookSource: fakeHookSource{ @@ -187,6 +190,28 @@ func TestAdmit(t *testing.T) { errorContains: "you shall not pass", }, "match & fail (but allow because fail open)": { + hookSource: fakeHookSource{ + hooks: []registrationv1alpha1.ExternalAdmissionHook{{ + Name: "internalErr A", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyIgnore, + }, { + Name: "internalErr B", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyIgnore, + }, { + Name: "internalErr C", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyIgnore, + }}, + }, + path: "internalErr", + expectAllow: true, + }, + "match & fail (but allow because fail open on nil)": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "internalErr A", @@ -204,6 +229,28 @@ func TestAdmit(t *testing.T) { }, expectAllow: true, }, + "match & fail (but fail because fail closed)": { + hookSource: fakeHookSource{ + hooks: []registrationv1alpha1.ExternalAdmissionHook{{ + Name: "internalErr A", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyFail, + }, { + Name: "internalErr B", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyFail, + }, { + Name: "internalErr C", + ClientConfig: ccfg, + Rules: matchEverythingRules, + FailurePolicy: &policyFail, + }}, + }, + path: "internalErr", + expectAllow: false, + }, } for name, tt := range table { From 099f6002e7bbf99b734bc501cfacabe575204bb8 Mon Sep 17 00:00:00 2001 From: David Eads Date: Fri, 13 Oct 2017 10:57:45 -0400 Subject: [PATCH 4/6] UPSTREAM: 50476: fix the webhook unit test; the server cert needs to have a valid CN; fix a fuzzer --- .../cmd/kube-apiserver/app/server.go | 17 +- .../kubeapiserver/admission/initializer.go | 22 +- .../plugin/pkg/admission/webhook/admission.go | 20 +- .../pkg/admission/webhook/admission_test.go | 42 ++- .../pkg/admission/webhook/certs_test.go | 337 +++++++++--------- .../plugin/pkg/admission/webhook/gencerts.sh | 4 +- .../src/k8s.io/client-go/rest/config.go | 3 + .../src/k8s.io/client-go/rest/config_test.go | 3 + .../src/k8s.io/client-go/rest/transport.go | 1 + .../src/k8s.io/client-go/transport/cache.go | 12 +- .../src/k8s.io/client-go/transport/config.go | 8 +- 11 files changed, 265 insertions(+), 204 deletions(-) diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go index bf3d3716ee8d..12371226fc45 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/server.go @@ -241,7 +241,7 @@ func CreateNodeDialer(s *options.ServerRunOptions) (tunneler.Tunneler, *http.Tra } // CreateKubeAPIServerConfig creates all the resources for running the API server, but runs none of them -func CreateKubeAPIServerConfig(s *options.ServerRunOptions, nodeTunneler tunneler.Tunneler, proxyTransport http.RoundTripper) (*master.Config, informers.SharedInformerFactory, clientgoinformers.SharedInformerFactory, *kubeserver.InsecureServingInfo, aggregatorapiserver.ServiceResolver, error) { +func CreateKubeAPIServerConfig(s *options.ServerRunOptions, nodeTunneler tunneler.Tunneler, proxyTransport *http.Transport) (*master.Config, informers.SharedInformerFactory, clientgoinformers.SharedInformerFactory, *kubeserver.InsecureServingInfo, aggregatorapiserver.ServiceResolver, error) { // register all admission plugins RegisterAllAdmissionPlugins(s.Admission.Plugins) @@ -255,7 +255,14 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions, nodeTunneler tunnele return nil, nil, nil, nil, nil, utilerrors.NewAggregate(errs) } - genericConfig, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, err := BuildGenericConfig(s) + if s.CloudProvider != nil { + // Initialize the cloudprovider once, to give it a chance to register KMS plugins, if any. + _, err := cloudprovider.InitCloudProvider(s.CloudProvider.CloudProvider, s.CloudProvider.CloudConfigFile) + if err != nil { + return nil, nil, nil, nil, nil, err + } + } + genericConfig, sharedInformers, versionedInformers, insecureServingOptions, serviceResolver, err := BuildGenericConfig(s, proxyTransport) if err != nil { return nil, nil, nil, nil, nil, err } @@ -336,7 +343,7 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions, nodeTunneler tunnele } // BuildGenericConfig takes the master server options and produces the genericapiserver.Config associated with it -func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, informers.SharedInformerFactory, clientgoinformers.SharedInformerFactory, *kubeserver.InsecureServingInfo, aggregatorapiserver.ServiceResolver, error) { +func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transport) (*genericapiserver.Config, informers.SharedInformerFactory, clientgoinformers.SharedInformerFactory, *kubeserver.InsecureServingInfo, aggregatorapiserver.ServiceResolver, error) { genericConfig := genericapiserver.NewConfig(api.Codecs) if err := s.GenericServerRunOptions.ApplyTo(genericConfig); err != nil { return nil, nil, nil, nil, nil, err @@ -442,6 +449,7 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, sharedInformers, genericConfig.Authorizer, serviceResolver, + proxyTransport, ) if err != nil { return nil, nil, nil, nil, nil, fmt.Errorf("failed to create admission plugin initializer: %v", err) @@ -457,7 +465,7 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, } // BuildAdmissionPluginInitializer constructs the admission plugin initializer -func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, externalClient clientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer, serviceResolver aggregatorapiserver.ServiceResolver) (admission.PluginInitializer, error) { +func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client internalclientset.Interface, externalClient clientset.Interface, sharedInformers informers.SharedInformerFactory, apiAuthorizer authorizer.Authorizer, serviceResolver aggregatorapiserver.ServiceResolver, proxyTransport *http.Transport) (admission.PluginInitializer, error) { var cloudConfig []byte if s.CloudProvider.CloudConfigFile != "" { @@ -491,6 +499,7 @@ func BuildAdmissionPluginInitializer(s *options.ServerRunOptions, client interna } pluginInitializer = pluginInitializer.SetServiceResolver(serviceResolver) + pluginInitializer = pluginInitializer.SetProxyTransport(proxyTransport) return pluginInitializer, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go index f93a9d930661..4fbedb6f1a86 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go +++ b/vendor/k8s.io/kubernetes/pkg/kubeapiserver/admission/initializer.go @@ -17,6 +17,7 @@ limitations under the License. package admission import ( + "net/http" "net/url" "k8s.io/apimachinery/pkg/api/meta" @@ -88,6 +89,12 @@ type ServiceResolver interface { ResolveEndpoint(namespace, name string) (*url.URL, error) } +// WantsProxyTransport defines a fuction that accepts a proxy transport for admission +// plugins that need to make calls to pods. +type WantsProxyTransport interface { + SetProxyTransport(proxyTransport *http.Transport) +} + type PluginInitializer struct { internalClient internalclientset.Interface externalClient clientset.Interface @@ -99,8 +106,9 @@ type PluginInitializer struct { serviceResolver ServiceResolver // for proving we are apiserver in call-outs - clientCert []byte - clientKey []byte + clientCert []byte + clientKey []byte + proxyTransport *http.Transport } var _ admission.PluginInitializer = &PluginInitializer{} @@ -142,6 +150,12 @@ func (i *PluginInitializer) SetClientCert(cert, key []byte) *PluginInitializer { return i } +// SetProxyTransport sets the proxyTransport which is needed by some plugins. +func (i *PluginInitializer) SetProxyTransport(proxyTransport *http.Transport) *PluginInitializer { + i.proxyTransport = proxyTransport + return i +} + // Initialize checks the initialization interfaces implemented by each plugin // and provide the appropriate initialization data func (i *PluginInitializer) Initialize(plugin admission.Interface) { @@ -183,4 +197,8 @@ func (i *PluginInitializer) Initialize(plugin admission.Interface) { } wants.SetClientCert(i.clientCert, i.clientKey) } + + if wants, ok := plugin.(WantsProxyTransport); ok { + wants.SetProxyTransport(i.proxyTransport) + } } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go index 692e73f39cb7..b3995e59dde2 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go @@ -21,6 +21,8 @@ import ( "context" "fmt" "io" + "net" + "net/http" "sync" "time" @@ -106,6 +108,7 @@ type GenericAdmissionWebhook struct { negotiatedSerializer runtime.NegotiatedSerializer clientCert []byte clientKey []byte + proxyTransport *http.Transport } var ( @@ -114,6 +117,10 @@ var ( _ = admissioninit.WantsExternalKubeClientSet(&GenericAdmissionWebhook{}) ) +func (a *GenericAdmissionWebhook) SetProxyTransport(pt *http.Transport) { + a.proxyTransport = pt +} + // 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) { @@ -249,20 +256,27 @@ func (a *GenericAdmissionWebhook) hookClient(h *v1alpha1.ExternalAdmissionHook) return nil, err } + var dial func(network, addr string) (net.Conn, error) + if a.proxyTransport != nil && a.proxyTransport.Dial != nil { + dial = a.proxyTransport.Dial + } + // TODO: cache these instead of constructing one each time cfg := &rest.Config{ Host: u.Host, APIPath: u.Path, TLSClientConfig: rest.TLSClientConfig{ - CAData: h.ClientConfig.CABundle, - CertData: a.clientCert, - KeyData: a.clientKey, + ServerName: h.ClientConfig.Service.Name + "." + h.ClientConfig.Service.Namespace + ".svc", + CAData: h.ClientConfig.CABundle, + CertData: a.clientCert, + KeyData: a.clientKey, }, UserAgent: "kube-apiserver-admission", Timeout: 30 * time.Second, ContentConfig: rest.ContentConfig{ NegotiatedSerializer: a.negotiatedSerializer, }, + Dial: dial, } return rest.UnversionedRESTClientFor(cfg) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go index c6d845201c19..8dee1f3a055d 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go @@ -53,6 +53,7 @@ func (f *fakeHookSource) Run(stopCh <-chan struct{}) {} type fakeServiceResolver struct { base url.URL + path string } func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) { @@ -60,7 +61,7 @@ func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, return nil, fmt.Errorf("couldn't resolve service location") } u := f.base - u.Path = name + u.Path = f.path return &u, nil } @@ -89,7 +90,6 @@ func TestAdmit(t *testing.T) { if err != nil { t.Fatal(err) } - wh.serviceResolver = fakeServiceResolver{*serverURL} wh.clientCert = clientCert wh.clientKey = clientKey @@ -123,16 +123,16 @@ func TestAdmit(t *testing.T) { type test struct { hookSource fakeHookSource + path string expectAllow bool errorContains string } - ccfg := func(result string) registrationv1alpha1.AdmissionHookClientConfig { - return registrationv1alpha1.AdmissionHookClientConfig{ - Service: registrationv1alpha1.ServiceReference{ - Name: result, - }, - CABundle: caCert, - } + ccfg := registrationv1alpha1.AdmissionHookClientConfig{ + Service: registrationv1alpha1.ServiceReference{ + Name: "webhook-test", + Namespace: "default", + }, + CABundle: caCert, } matchEverythingRules := []registrationv1alpha1.RuleWithOperations{{ Operations: []registrationv1alpha1.OperationType{registrationv1alpha1.OperationAll}, @@ -151,42 +151,46 @@ func TestAdmit(t *testing.T) { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "nomatch", - ClientConfig: ccfg("disallow"), + ClientConfig: ccfg, Rules: []registrationv1alpha1.RuleWithOperations{{ Operations: []registrationv1alpha1.OperationType{registrationv1alpha1.Create}, }}, }}, }, + path: "disallow", expectAllow: true, }, "match & allow": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "allow", - ClientConfig: ccfg("allow"), + ClientConfig: ccfg, Rules: matchEverythingRules, }}, }, + path: "allow", expectAllow: true, }, "match & disallow": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "disallow", - ClientConfig: ccfg("disallow"), + ClientConfig: ccfg, Rules: matchEverythingRules, }}, }, + path: "disallow", errorContains: "without explanation", }, "match & disallow ii": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "disallowReason", - ClientConfig: ccfg("disallowReason"), + ClientConfig: ccfg, Rules: matchEverythingRules, }}, }, + path: "disallowReason", errorContains: "you shall not pass", }, "match & fail (but allow because fail open)": { @@ -215,18 +219,19 @@ func TestAdmit(t *testing.T) { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ Name: "internalErr A", - ClientConfig: ccfg("internalErr"), + ClientConfig: ccfg, Rules: matchEverythingRules, }, { - Name: "invalidReq B", - ClientConfig: ccfg("invalidReq"), + Name: "internalErr B", + ClientConfig: ccfg, Rules: matchEverythingRules, }, { - Name: "invalidResp C", - ClientConfig: ccfg("invalidResp"), + Name: "internalErr C", + ClientConfig: ccfg, Rules: matchEverythingRules, }}, }, + path: "internalErr", expectAllow: true, }, "match & fail (but fail because fail closed)": { @@ -255,6 +260,7 @@ func TestAdmit(t *testing.T) { for name, tt := range table { wh.hookSource = &tt.hookSource + wh.serviceResolver = fakeServiceResolver{base: *serverURL, path: tt.path} err = wh.Admit(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo)) if tt.expectAllow != (err == nil) { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go index db1e07be0266..815d8214caed 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go @@ -20,199 +20,196 @@ limitations under the License. package webhook var caKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY-----`) var caCert = []byte(`-----BEGIN CERTIFICATE----- -MIIDhDCCAmygAwIBAgIJAIf67NAEFfGmMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNV -BAMUKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX -DTE3MDUwNDIyMzMyOFoYDzIyOTEwMjE3MjIzMzI4WjA0MTIwMAYDVQQDFClnZW5l +MIIDPTCCAiWgAwIBAgIJAKa7yqtdLQh0MA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV +BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX +DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA0MTIwMAYDVQQDDClnZW5l cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jYTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAOanR6SUd7AINWnxFi5Z8XWw1dS7QLwnfVlh -P+IO9fgQcL8Cywv6Yj0Yvpv+wGByfc6FcL8AFGASTNqaUFdhsLKuFwOXS76/H17e -PmAP7C0wKNDwJv0EJmc4h1Pb+zidOMqY007gPOg/xJJKRD+5UZDfzRaVdz4VNBeU -065K80qXjwSEdWj0s4f+lJuk7RZPaIqmrdOZXlnDM6J4s64HkFPRFum0mGOcPoKt -V9nmW9bPXkffB9MXGX6Id6h5idSKvQnNja/jFKIZtpuOaM0/tS/oOOmTCccjwesS -6+7joZKCbCt9KuuwGSj6OfLQ05hCkl3waLSLxSOTfT97AFsXE4kCAwEAAaOBljCB -kzAdBgNVHQ4EFgQU55hOE1Dsydy16+6wgOxwsPKZ8JEwZAYDVR0jBF0wW4AU55hO -E1Dsydy16+6wgOxwsPKZ8JGhOKQ2MDQxMjAwBgNVBAMUKWdlbmVyaWNfd2ViaG9v -a19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhggkAh/rs0AQV8aYwDAYDVR0TBAUw -AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAtEa7AMnFdc/GmVrtY0aOmA3h1WJ/rhhd -SnVOp7LmA+1jnA6FMMvVCOFflYLfBwLhIPjPj4arQadWHyd5Quok6GIqgzL4RkK7 -67hPMc8inNH8w+9K0kgsCls06Jy08NIt7QTtIckh8skvxQsfJ6An/ROiCNI5QiYj -oQOK3Tp8jGf/2wcsJLeO9y09ZPcOUbLkDe2YlnT+OqNMx9VXrPSvRwq2qtYphgYW -YWHPMEBnB/9XrVkEtnKeWPjtjarVd+rNnfVpCW0ImnZRFtKQQeI4rtf4Gr83Gdju -Z0gPepfIFptDMl5wKWyw4o2XVSZ69Ur8tQQynoNyX/FTIx6tQ//hzg== +hvcNAQEBBQADggEPADCCAQoCggEBAKx3UWPd991NOMSqLap8CsCedooUhsK+YX+F +5KGeOvmWImj0tbBHipBT0WRGSCttnHf9oJcsvgLBFEYvMnhbre3sbuNWOjOQn4H+ +uJHmNhIEbvQ5QWckAUw+u03wOuMUW87R5oCaQWR6XdNEfaNSNOTmLKOwCxYqhLRw +z71I9z1Ne4e3N8RH6tZO5EKvE69BGxEPhlnRP19CB1uCeKSIytNdCh2Uic+FtMLl +YLIww71eERjyEXF0/5x9+oJjPq3MTYLR4DRwkkO4uoqFDI74N7radPFbcNInCvVe +TFdjABozYecwolL5fva07Fub+7UfWOablqgTxFmgacCcIyZRGgECAwEAAaNQME4w +HQYDVR0OBBYEFPa03YxFI220gcsALquzjQkfHztBMB8GA1UdIwQYMBaAFPa03YxF +I220gcsALquzjQkfHztBMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AJkgjVhVNAoVdNA55qPPYxouOpOUNyy6GV8ZKCSepz4O5uSRl1FHxTIoodnYzBvO +RkYBJCMupB4Ee+wuMlZGPd3Tfnl6SaP1V4vGYD1iS4otMM6J2tTJBxoLqQwNaDkc +S2E2zfbQ0OxaRNbMBn9AZvZE4lN2TMVuWuTGl1amMLF7Fsxs2ndt+OCpf8d2sWpW +Enh475ch0PJfqZU0papeSV0XRdn60lTGwIbRldUowTBLYcbKo4tTMsCE3oOK7yul +0QhQ9eJktvMbZNMYwGWz+p4pjs/eqBnlBP0KuXguKFHFXILxPlyRMhsvHKURUnC8 +ugGtqN9AEw6SF2Hf1rzmNno= -----END CERTIFICATE-----`) var badCAKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA2Mbqfl5nW+rYCSw/+G00ymtBElvTwzEI88sg3m5PXU0XMv5y -Tyjt+S3mhbzLY460ty6fXlEiveNNP0bzbo0k+tvUj7HbOG4q4Cs0JWiLvibchRXQ -LimqtndsVsT2xj56m7oTETWMYhjd8KFz1s6w7yK9dChe2pBCeeGjIbQs0def8Bf0 -5h7BbsmuXQb44nnpUdWgFI/Frqcz6jO6jySYV5U3ajqCjcWOBQmXRtMi1we48Hdj -2t4jW/evbRIo/tX88kluXFSVBmTitKA3nn23AzA+/qa6kTDwzQ8OntjC09JT7ykS -764WLRiBOo+wC3a6M3eZNMkW615+DNP7wAjYEwIDAQABAoIBAC9lZnXUvDKLqUpw -I1h0wBsV0jdqXmWJ/hQXsIsRgUa8CTt8CJAoOcfGcmWBPtL4q6h1iCC+CqOL5CLW -p3jfYVt73wC/+VdgNv2mVJNtRUiBBKwQdeDx+UJF4CkkjXQQywvrZinYFGaKW1Q2 -aLZpoKPYa6XPAdY1vmMZo2pGE5qZbGbIXKcl3kl5N2X0qyJKvTR6RA1Q8JiTmATh -H1U3S9K/MIGU+9OwP8zCDVKFdDI+xgJvDo05W8bt6XLfmE4bLRYHRfe0iE0uBNSC -zx5OGBNqkiHq/vMk5mLCYM0w/uzUkhB5uXqe5gSqa7DioLrHztqAe+sbtBvfL+Yd -hP3asWECgYEA9NQXa2B6AVXVf2GII67H8diPFrILKLEw4CUZjFmVbvrKIRB2ypqA -IsohpYl97s0nstetZt/75uEvkv3RPu5ad5LJaVAPHE3ESXKdAz6u4fSmi33qqPi6 -PvhHLYDDXvMgC7j2yCYyANVKNg2T+EJvpWMISlXM4h7CVm21CSDVZjECgYEA4qsl -zDA3sHoClfC4nAOVrRghYlHU2bT6HPLxjLtBkcUTfj6nO6nOLGC7EFVkqYw5mUWq -uSNntk1D1+MYVnZBeKqw6y21FFsclmzzXTtAJg0vuAg1jxnMHqiDbNqpUUO8ZWLG -iz2tdAWiBAKwZv0Psv44Dy++4v/BMd8FBb/iHYMCgYEAttKmRmW91b9t9Xg0fEjp -QBzyBQWhNZrTn520rUy8PSqDxBsSSgsDgncklwPMCYYjjfZmo3rBFdC0gPSOy4qb -/cycIMtK7VzZJeuzehfV6h+SOnolwFY0Zg9qv3z257FwDbDqf92d22dqymBrTaj2 -zC7eovvdSkGj53x3AsEE+hECgYAd7JJU3pi7h6AHw3vbvO1pqKHfpQYAp8/NOpWB -CsehQu9L32GcktJRMYQAqAVeDNEd1wCu6Gmsu46VVbnE0F/cWkx4/9PEGDMx+Lg4 -OrZBT8RY+1x2w+UatwyCtmtb+yFIET4866uWgZfeB6zaK9aCvuUPvDHrLfCHcPXs -yGRFmQKBgQDYvcjkUqKvnZwwpV6p6BHi6PuHWyjL+GLTk/IzsxOJykHzX4SV46Sd -9IxyE+OWZhkISBMSMe8wQC/S+QYs8hDbEE3WH1DXp33joyNgt2aWI0Splu7S1f6P -Pe08fYlLgz1xrbJuJAOgvkbskAUcmfmRwFeGaZSkkCtkzVxgN7LS3Q== +MIIEpQIBAAKCAQEA5T0xQ7mapkcE+h3owavy8NDxc2eKRe9q/5/yFp27F8QpnY13 +SQS0GXvDiFW1eXdXTg39loy5fG3SZLd/f0eniF2FWKsRvIJbRGyyVBzySbNvbEit +ekVeKQJTTH3Xlnb2JdRrr4vxWQC7crVPksS+AsB+MzdB39XIYxvK6hqwF7On8gro +tzJ+k9e9+/rk0u8FsOBvnE8Z9MX5qX+00UnHSVZuzQt//rTG4Dqsm1yswwTlUfe9 +XpjSh7D6fpjp5YNH9p3vLZMjoY/7ZqO0svHlcWjyv/zoN35p0gMwOGrByATYi2lo +wYBckI8oC+CzyRO8ThKUDW19fa9jKYcqsIDhwQIDAQABAoIBADFvadFWFFCpXhxm +GMyzPRfLp1YgzQPZ5rQrlPRlnXQ5nFParw+zEPex5e/fs9v27X/qqnYt8M4xjL6l +h7w2Ap34tQnzEkcZwX7XBfn3qBRWur+aSLbmgLDNTJNhS/2pt9lenr5jqm9sJgBN +s1ROUz+arVx0HSOdIbKlyrODf9gMQL6hg/ZYNym2KaaYjnNfyrGtb3GQgYDn5FNQ +TSeseXOm82Ev34pSbtQ/oFtU5W4DW72VFA68ciaLM2XslVl/zcncyDk+0LpvSq+W +PYSQbwU/xZukMXXxbBoQUaorNK1fDOdYXBzSzs+Yzo+71D3azFaqPv6CMlHCYeA8 +EUkDRAECgYEA8rmOnzjoHStjkOr7Yb5zqX4UyC0VvB6S9EJxy2a133K0eXJ82KPR +L7fkkvZk04PwDUpClTqcTw3gblhIaBYsFqTnCn6+8hS1Lqa6OqUYo5/UD1O4mXVh +ebLvss5CNqA2+ii80XkRZSW4w/27CG+u/iBAiS5JeYi0zm89G5PYbCECgYEA8cbR +VoUB6rFNC0VOd/D+LPMWaCU7FguAJQ+8Opoh/JgmxFqWwWYeteuX0tbGrKb8LXSA +XLEL1vrZjQ2W9tKP4hP9rgiZbvNujPABS1ey5mMFDPMy6q2OYgLY85jpeYU9PpRt +dOZiw7a0TFENRU19/WMeSfdDvEzafX6tqA/gwaECgYEA0337V6EuHrx/tPYKs9BO +15CUaxddqNy7DzoWDTUho+E+f9PSFLIow3toHuWyVNrRf8ME4SKAsCFXPM6PyKIJ +KHHnHq3xkt2YQV3lRtQz895/2BsK7ivpEzFmylYOO6q+PJria2MiVQ/ZPm0HWwJ1 +Z9iSYvWB7/O+F2G1zSG1ogECgYEAtoV0VY+VsdplokORCGULTV26JactoufNtqzZ +WZgwXiNy6LrGonv4ZTfU5tszIvXw3FPd75vMp1+6Soze0biF3JNg6DgftK3bYFRz +dbBgIyLPlkYmwxmAqqchp0xhvVaDtLGSrDScjMlp9U8e6JmmqlpgbFBZd1bBfwna +CUzrTOECgYEAx98UtYAFWVwoCZwtqSfzTKHerFN/qMFY34cXhdns2ZWn6kEb6alk +dXqNDkXV/7EBGWAcvKn/zbrwlhVDwPHUETgjCUpxqST0ly6E/JnwiNbrSOWG4Yg0 +RoKj46nUcolMbgRub+yeQqcQ48Y2/1OvnRUQ9aQ5MqVSyTyylgMKlB8= -----END RSA PRIVATE KEY-----`) var badCACert = []byte(`-----BEGIN CERTIFICATE----- -MIIDhDCCAmygAwIBAgIJAIabsJi6ILN7MA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNV -BAMUKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX -DTE3MDUwNDIyMzMyOFoYDzIyOTEwMjE3MjIzMzI4WjA0MTIwMAYDVQQDFClnZW5l +MIIDPTCCAiWgAwIBAgIJAOQ6iHm4OCSMMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV +BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX +DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA0MTIwMAYDVQQDDClnZW5l cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jYTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANjG6n5eZ1vq2AksP/htNMprQRJb08MxCPPL -IN5uT11NFzL+ck8o7fkt5oW8y2OOtLcun15RIr3jTT9G826NJPrb1I+x2zhuKuAr -NCVoi74m3IUV0C4pqrZ3bFbE9sY+epu6ExE1jGIY3fChc9bOsO8ivXQoXtqQQnnh -oyG0LNHXn/AX9OYewW7Jrl0G+OJ56VHVoBSPxa6nM+ozuo8kmFeVN2o6go3FjgUJ -l0bTItcHuPB3Y9reI1v3r20SKP7V/PJJblxUlQZk4rSgN559twMwPv6mupEw8M0P -Dp7YwtPSU+8pEu+uFi0YgTqPsAt2ujN3mTTJFutefgzT+8AI2BMCAwEAAaOBljCB -kzAdBgNVHQ4EFgQU9SUu1vDxGeyGEgy7pzZjLm+WSH0wZAYDVR0jBF0wW4AU9SUu -1vDxGeyGEgy7pzZjLm+WSH2hOKQ2MDQxMjAwBgNVBAMUKWdlbmVyaWNfd2ViaG9v -a19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhggkAhpuwmLogs3swDAYDVR0TBAUw -AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAViib1ZcwLUi5YE279NRypsGLa8pfT/A8 -10u41L4xw+32mD2HojMmAlAF4jnC62exaXFsAYEsze4TF+0zqwDkHyGqViw/hKAv -SrGgPUX3C7wLyiMa3pjZfcQQy+80SKiJLeClxxjkdhO0mGNo1LdJThYU5IADHVtF -u2oOKLTjWBVzkMRkTXp5RReeEoUPvFgJhPKIVLggdXdJT8oQjgIVlx6IuzjU0AeM -tJ5AIWYrsqv9FlpfUXWjdiy8uF3iLWTOpd6pICnjzfj02wQouTEkxQ2iFinl7Das -iK+7d34q6Ww1/1nu4EBBDYB1VlWdhDLJVT4F+mF8wZFBu863Ba+U5Q== +hvcNAQEBBQADggEPADCCAQoCggEBAOU9MUO5mqZHBPod6MGr8vDQ8XNnikXvav+f +8haduxfEKZ2Nd0kEtBl7w4hVtXl3V04N/ZaMuXxt0mS3f39Hp4hdhVirEbyCW0Rs +slQc8kmzb2xIrXpFXikCU0x915Z29iXUa6+L8VkAu3K1T5LEvgLAfjM3Qd/VyGMb +yuoasBezp/IK6LcyfpPXvfv65NLvBbDgb5xPGfTF+al/tNFJx0lWbs0Lf/60xuA6 +rJtcrMME5VH3vV6Y0oew+n6Y6eWDR/ad7y2TI6GP+2ajtLLx5XFo8r/86Dd+adID +MDhqwcgE2ItpaMGAXJCPKAvgs8kTvE4SlA1tfX2vYymHKrCA4cECAwEAAaNQME4w +HQYDVR0OBBYEFEe2nQ5ONNJFv/+6pWnzvfqRNTR9MB8GA1UdIwQYMBaAFEe2nQ5O +NNJFv/+6pWnzvfqRNTR9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AEORwyo3MJZVuYbqft728t9MWw0wFORzxPnFVLXMIrX223flNEmqvkA8UBSulxmq +yDYOOkOWByd2eemCZtc/MlmiSeYNFSi/PS+METkAef2cZfSQNdIUwwl5BZ4vW973 +J+fDNm0LQh3ZPDngylQ3XprQkF7l+UefRVfbDDTALVDzmJCV/FCm05ijg+HssgwX ++rYI9ZdJbp2z9xftN0RRIwrBQ3S9vA1mq6OoZFco+9Oq5Li5DHv0BpQgOS64dY1z +dtOy4RvQNF8NsITkOlp7f39716448dvq8TJlCdE27ptL44hU82cZib3cwQx8cynu +45owbCivEhgee3RUY7gVuc8= -----END CERTIFICATE-----`) var serverKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY-----`) var serverCert = []byte(`-----BEGIN CERTIFICATE----- -MIIDOzCCAiOgAwIBAgIJAN0PSMLOjTVAMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNV -BAMUKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX -DTE3MDUwNDIyMzMyOFoYDzIyOTEwMjE3MjIzMzI4WjA4MTYwNAYDVQQDDC1nZW5l -cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19zZXJ2ZXIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCq6KgKFtMb6LJODf5LAbDD/vI3ziO2 -Pnm/xeV3xOCTJq9JmbtDpZRF6+9e0kcy6D80DPqqgIXL/M6KjNSswHfoYU4Dwy3B -o510Ix0cyu5furb4KIVqaEWDny499Wv2qK3bQmLIGFo8f3taZDPCx9FC3gTWYJsQ -dlgrqvVGUXeLTScMLFzvjXC5inhRzmhgzR1ihUK/XUNh1/ra/WCssU7TZrmqMBQt -Lvgoo1onhgM6aqdO1a0jvlmQQlILZNP3Sjx4UhG4iZjXu96eohunfQD5e28yEhOD -nnrjxl1yL4IYcNyokDUL7LSvFdmRy4UUWsrS2I3sr9w8rUsO1LTyCnrVAgMBAAGj -SjBIMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC -BggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQCA -/IFclqY/dsadGY0e9U3xq0XliIjZIHaI6OLXmO8xBdLDVf2+d6Bt3dl9gQMtGQI3 -zj9vqJrM+znXR30yAERFefZItk8hTzAotk15HYExVJkIn5JQBaXRbeO2DUZFgAnu -6OU6KnuVC6i+7xDlbMl8wtRPmeZ6FS1wW4wnxLWZtKYAuLVDs0ISy6qbznGhCkWc -b0uPbxnMmZHQLVL+yF1LYWpX9+Xa9QnWXOSY7KHtcuYXZB/XV4Pt6aDncg76bFdl -MG3bocbJ9MsoS/LdlAiYzLNmKlFa243QPOo/zN170NhEZaF1lM80YBaLIE4rRtga -nrkNOnPHx1evvuleH0Yv +MIIDJjCCAg6gAwIBAgIJAPJEHs7Aav1jMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV +BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX +DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjAjMSEwHwYDVQQDExh3ZWJo +b29rLXRlc3QuZGVmYXVsdC5zdmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDGNNu5amkBAHXjRoDFVWjSN1wbDmJ3ggBryOLdP9fX6YMiRTx0DyR+nCBp +66uHc1qLRHotP1lnlokPxra52FWK9jRDXWyfD/gbjRq8vbI+vVUlIqSW/n9vWSdK +HncK+P7uZrrKOfnIHHDxXu/77fvJV7osc/cHRAG9HTuf2TnTuAoeTD9H3bgjolR0 +G2Wqgg/BEmVZFXInlFrB8Nn4pfZ32tjRYDFbrReB7yBY8y/xcpWLLD6nn7ly3poe +K7r++1E/k3vSUvwddCOv7HSpoV3qbf9JqONfwAq90hDMOhxPOaN2VEtGPyS8th/x +89rNLJupa/Ql5eRXEJk+/blI3boHAgMBAAGjSjBIMAkGA1UdEwQCMAAwCwYDVR0P +BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHREECDAG +hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQAp99rbIZlUhvNmxhiQCMcltLqtIpGs +ZorxbInV4QCdV+Kybot+L7kUDxu/OqERNLqr1qRsjqJRHUhiZZVv8gjZgwz4bO1/ +ycjUyAoS92OMKEWlvXe1nMnHH3Jw+lXnwiaOumoExhB1gpMjGqsU3mBQrHXGenNS +JyJtRsBFnkgk1hGycJPgNc/juaHuGBexLDdPqOy3Zmv1AtzFhvPzOTEFpaIGa5dz +vewjDBFBCpFFTqpISD93JX6AbkucPVKnfF97DkBLyj3mr+X9Cy0pLGjwN8Gcp1Ez +5MvTqbOmqLypcRJu285K0Yxmv7a38GND7xeoijfnPFjVjYGlacCnI7ps -----END CERTIFICATE-----`) var clientKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA1Cf8Tch5IieN9zAI0b5FFJoMzPsN3RAYD5GAk3Xo9XNbKnvJ -38o2TKdxFu1/Q8hqG3668vWuL6TYDYVcYWtC6rwNpU/moAdJZyyEtmZIam1Va1VW -HDCpylsk4b8jbUxxm6OzF1XxZpBUJg9o/1OvL1XA0rmcDiddXN5VdL2adJZsS54t -gI57hcH0jkQocHTEv5gIl2tcTDStd4GeWxBmCotYdCQWcNk+96QMRxIai88aPPYw -QxpOQeaABrYrjPO1fJA0jimM9bhkjGXK6cnrRQrg3jkeF3vuPw9BFbE4VeENLY+y -v2OWBPYOD8ov0Tn2inge4QjE2DZyK95l46wQbwIDAQABAoIBAGZiAY1cALEt24H9 -yVPG+bluelz1jwQuvx3MPvtqvIivKcC/ynVYNYoaiCXjaTZB4orwRrH3RB8z8xvb -TvCofbugEwnDHG3/9jl3L3iCtdG+f6lznkGublH8WDklL6iQaocMoeHSFNRFNIbF -iwskzHcQcCSBdEEUWCb4GM9krMQz7pBR9BloyV40ZAGilMXI9F9FZ0YBWWee09gi -jid6sEzYQveZ5RQgEEDrE/i+jzXkU8sBKsSm1GuKH62+YrtelBqP83DwVIKthMOJ -79tw6i98v5JHV+1ikqC1Na/c7OxBBF3xrgwCN47ok0cHaIXh7SX+EIN6jcwKTmRH -VZQBz2ECgYEA6tTpJEKNAzEY3KOO578zY2hWhPUNqzUTm8yLxZedhDt2rwyWjd4J -HhS7CiNqFpMT/kxFyOupA8SFJPZDhJBXttnyzO9Sb61fLWgSP739K9OQfK1FGTA6 -khjc3vHtBeGrWm9+1jSxQtrwly7Rs+EmdvseDCN7yie/mgrBLS7p1l8CgYEA50fN -6BnbeAgCTK8GDBWSJPaYUlo/lebUDCn5QIp1LK93vPQWjJR8xRBwL1TbiVKGd054 -dRZVuJYMJx+2mbrt5ca9UArisZp5OZgR4xz29n9u69P5XiuG8Fq/JBJXp1GXONVx -JNOsUHOW/b3w2tNUWZcMQAH601BHOtO+EtaEX/ECgYBHygz4A8xeFG1YTjwKxt3r -3uLMRKoIE/LJp093eXEzEoam3v9LoXxCEO5ZHBh7jD0JecG/uaNyvmpBsXNUnFfk -U16xndwiveqh0/X4PJmgA05hfwrnt2HAdg9XrLfcG3Ap9nnc/EDQgmQYo7yB9Cux -JfW6mkJmu54Mdos1x+i+mwKBgHmewcGe71E0bPkkRLrQERUM89bCjJNoWfO3ktIE -vU9tSjr75GuyndYHKedJ6VRSKFHO2vs/bn5tsSBVxfEbYoSlOOJBhyo8AClwNV/H -2HqRUqQCySxjGUeFgOQYHS3ocuw5GZFzGjcIQctXObPo0391NcTnBZ5fpcVimZ5Q -XjYRAoGAN2O3HQjPyThoOUOn5MJEIx0L5bMvGNDzJO+oFngAntX/zv0zu/zsD9tc -kk4EbMLluiw2/XJvYjCStieaYxbSWioKwlThy39C+iUut+IbpP2eI46SOkhvPczt -4u1/sslqjs4ZSntR4Z9UOk3vY3oxRKbiXX2/vl9cqzB/cGYu01c= +MIIEowIBAAKCAQEA1jCNOxaX7C6bH8YffvoneePNQVAnMejecJqQz+KJHdrwTlOD +dqzpBVf21tzUo2AU7xoKzpHnEZ5PvBlgzveBhBy3E48ILWRs4ZCnCXYRG62LD6fI +ub0uEt2IwHiT0A6q1fGrAYlrzLkYRz3LQyOQhL0Ca7nB2IeCzY/Vfz0TR2+4bMtY +54Go5G+lZRP1N88E2cplS8YEZLPlQqqVS6J15bkpnAMmQWL5x67cUbnXdST4qvns +3cSqjjC0LKhOd1aInxdCgwL7dT4lwF64Jz1/25OSUVFN5J5Y8xmPqQWHNtauVTjw +/StV1DYfe3LnVhVriQ+aNu/cssfe1Se7x6w7HQIDAQABAoIBACRaOy4jKIfCZTug +UaooZNjQK/8AzpYu8snjwd42kZUKmqyAihhzQl1Qz6kp88ECxqrKHblvk+sullPT +btXRth6pDP150iZ6G+yws1jsu/yZmLeAf5XeoNo81T/tdxDh3GbRTHfHTg+B/rfg +qgXsHFQbDDUiYt8QKMgguFiPEh2WbedyAe1N9LhtEazMhrnLXCUxTXIFddmcKvnk +fTcnV6mG4FftXFwh+Qn4HukphENHD+xazxIp/WFGDbbStQ8sbjkUSydU0w5x/eQ/ +V6z7ibgDmlHoSyKCxc0B0wuNE/BBQzQGvy2T9UhA4V2+vwuQpcXxM77tXMNnmxaX +fEXHQBUCgYEA+sYZKOTL7JCJNnGexVVxn6OWZUuSf94LAyVBCveHnItlFgowzwU1 +NYUFD894SR7orvbnSHvEOvim10C7YoyDcsH5+zt4K7dMnVJ6I6I4mNv0r/1WylHe +JyNkYP7jn6znMqVgvo4YHCMrk2OoPIE8jeH1aN+I/YOTi47BIb+MbfcCgYEA2qdG +AbgwVoWeQT7Z+3iJxTgaZGjO66Id2164HMK0NGeYjNeWikt58Y5Vitblk6h8JqQy +yOipyyIbQFnQbmTo6vlvNTKw2NOrPHkYktridIfFrinYqEmKfhbhQWnZAOTjOnpJ +9RFC5LbErmrf5G6HIWV8bfX/kBvi0QbF6VYuKosCgYB2Ztf0PeqmnCuc4BKFu2z1 +YcidtQvLgawTZSCLrAmEeTBWMqOO6zePOGoGZ/+0DnrwOTVEPOOOsF4d3btbsVpS +8ZE09IQtp9LtqMZwUqSET7385hF3XyYTtpsrTM1uU7WpbPn7np11k4l8gp4pSx+r +Ide8F2bXw6sDRniblZQZSwKBgQCjN4RZmj1zCLEWcS1UuyjUcEm7NEVpvY1eCLmU +tn7AM6i7Ud8NAsRXXXFbf4jGDVoHmkBSmuLMQHxpL+IX1fnMFUA/TMSYRoEnVhnS +3dN3OzaECLazAJqB/uBM7Q9QzIsWRtzYM/dkNU5iCGNy6FK0ykX061HHKBnLAKxR +vsQdewKBgGCZiy/QYdGR3jdfD7Qytfuptgf6zFLB0BqHJTG/YmnonCDTI8ZxmDOF +DspoiVbrjYdHED0IfcnXYNK8+Bv/2vVxAGqqCdA/aJbFXx86zKJvu8ZHcFrWl6Fy +vdk6OsJjqpA0RM/lD2kVvHeaBO44qGmMFfZHv52ONu+wE4mVX6Y8 -----END RSA PRIVATE KEY-----`) var clientCert = []byte(`-----BEGIN CERTIFICATE----- -MIIDOzCCAiOgAwIBAgIJAN0PSMLOjTVBMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNV -BAMUKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX -DTE3MDUwNDIyMzMyOFoYDzIyOTEwMjE3MjIzMzI4WjA4MTYwNAYDVQQDDC1nZW5l +MIIDOzCCAiOgAwIBAgIJAPJEHs7Aav1kMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV +BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX +DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA4MTYwNAYDVQQDFC1nZW5l cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jbGllbnQwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUJ/xNyHkiJ433MAjRvkUUmgzM+w3d -EBgPkYCTdej1c1sqe8nfyjZMp3EW7X9DyGobfrry9a4vpNgNhVxha0LqvA2lT+ag -B0lnLIS2ZkhqbVVrVVYcMKnKWyThvyNtTHGbo7MXVfFmkFQmD2j/U68vVcDSuZwO -J11c3lV0vZp0lmxLni2AjnuFwfSORChwdMS/mAiXa1xMNK13gZ5bEGYKi1h0JBZw -2T73pAxHEhqLzxo89jBDGk5B5oAGtiuM87V8kDSOKYz1uGSMZcrpyetFCuDeOR4X -e+4/D0EVsThV4Q0tj7K/Y5YE9g4Pyi/ROfaKeB7hCMTYNnIr3mXjrBBvAgMBAAGj +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWMI07FpfsLpsfxh9++id5481BUCcx +6N5wmpDP4okd2vBOU4N2rOkFV/bW3NSjYBTvGgrOkecRnk+8GWDO94GEHLcTjwgt +ZGzhkKcJdhEbrYsPp8i5vS4S3YjAeJPQDqrV8asBiWvMuRhHPctDI5CEvQJrucHY +h4LNj9V/PRNHb7hsy1jngajkb6VlE/U3zwTZymVLxgRks+VCqpVLonXluSmcAyZB +YvnHrtxRudd1JPiq+ezdxKqOMLQsqE53VoifF0KDAvt1PiXAXrgnPX/bk5JRUU3k +nljzGY+pBYc21q5VOPD9K1XUNh97cudWFWuJD5o279yyx97VJ7vHrDsdAgMBAAGj SjBIMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC -BggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQC/ -TBXk511JBKLosKVqrjluo8bzbgnREUrPcKclatiAOiIFKbMBy4nE4BlGZZW34t1u -sStB1dDHBHIuEkZxs93xwjqXN03yNNfve+FkRcb+guaZJEIBRlNocNxhd+lVDo8J -axRTdoOxyEOHGCjg+gyb0i9f/rqEqLnDwnYLZbH9Qbh/yv6OgISUTYOCzH35H0/6 -unY5JaBhRvmJHI0Z3KtmvMShbUyzoYD+oNLaS31fvoYIekcHsnOjZGBukaIx1bE1 -4SFjCUSPGDdzJdaYxQb0UXNI7oXKr6e6YeOrglIrVbboa0X3jtqGF1U7rop8ts3v -24SeXsvxqJht40itVvGK +BggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQBh +cqu6S6MkUUtNhlWR33ZfV6Ewoz06IGtUIUDDuRmVuizCDOdCcGOTDvdoXtbZMwUf +ZRVVaSyIjqdz5k+C06mHM7uEEgo+Xo7YolK1AiW9VflG8K47l/+XlLoHFv0eB9k/ +KdlFkzh3pszM4uEiynkLlSpQxyyBOhyaVdQlXdamqmSfIO0HlLza1OAP2rMILeMb +GJ0y+DCxxAspwVvmCUzc5nL6t35+oEDihRk9bjGDLhfh+b0AYSO4RUjzhNlayUBG +/Kbxh6GiimYmWwpIUTcTAbO7gB7Ya5eXmEB80McS0Z6MY/AEBHnu2Cy8BVEDY30f +uOhGOj+iPQxidcxc+wuy -----END CERTIFICATE-----`) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh index 7de850a590ac..3ee1a094fcd3 100755 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh @@ -61,7 +61,7 @@ openssl req -x509 -new -nodes -key badCAKey.pem -days 100000 -out badCACert.pem # Create a server certiticate openssl genrsa -out serverKey.pem 2048 -openssl req -new -key serverKey.pem -out server.csr -subj "/CN=${CN_BASE}_server" -config server.conf +openssl req -new -key serverKey.pem -out server.csr -subj "/CN=webhook-test.default.svc" -config server.conf openssl x509 -req -in server.csr -CA caCert.pem -CAkey caKey.pem -CAcreateserial -out serverCert.pem -days 100000 -extensions v3_req -extfile server.conf # Create a client certiticate @@ -104,4 +104,4 @@ done rm *.pem rm *.csr rm *.srl -rm *.conf \ No newline at end of file +rm *.conf diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go index b4511486592b..6b6d82ad62f6 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config.go @@ -110,6 +110,9 @@ type Config struct { // The maximum length of time to wait before giving up on a server request. A value of zero means no timeout. Timeout time.Duration + // Dial specifies the dial function for creating unencrypted TCP connections. + Dial func(network, addr string) (net.Conn, error) + // Version forces a specific version to be used (if registered) // Do we need this? // Version string diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go index 784a1ed831a2..468cddea9099 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/config_test.go @@ -18,6 +18,7 @@ package rest import ( "io" + "net" "net/http" "path/filepath" "reflect" @@ -236,6 +237,8 @@ func TestAnonymousConfig(t *testing.T) { func(r *clientcmdapi.AuthProviderConfig, f fuzz.Continue) { r.Config = map[string]string{} }, + // Dial does not require fuzzer + func(r *func(network, addr string) (net.Conn, error), f fuzz.Continue) {}, ) for i := 0; i < 20; i++ { original := &Config{} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go index ba43752bc93e..878c6abf1640 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/rest/transport.go @@ -95,5 +95,6 @@ func (c *Config) TransportConfig() (*transport.Config, error) { Groups: c.Impersonate.Groups, Extra: c.Impersonate.Extra, }, + Dial: c.Dial, }, nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go index 8d76def345de..561c92c18190 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/cache.go @@ -63,16 +63,20 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { return http.DefaultTransport, nil } + dial := config.Dial + if dial == nil { + dial = (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial + } // Cache a single transport for these options c.transports[key] = utilnet.SetTransportDefaults(&http.Transport{ Proxy: http.ProxyFromEnvironment, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: tlsConfig, MaxIdleConnsPerHost: idleConnsPerHost, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, + Dial: dial, }) return c.transports[key], nil } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go index 820594ba3547..af347dafea8f 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/transport/config.go @@ -16,7 +16,10 @@ limitations under the License. package transport -import "net/http" +import ( + "net" + "net/http" +) // Config holds various options for establishing a transport. type Config struct { @@ -48,6 +51,9 @@ type Config struct { // config may layer other RoundTrippers on top of the returned // RoundTripper. WrapTransport func(rt http.RoundTripper) http.RoundTripper + + // Dial specifies the dial function for creating unencrypted TCP connections. + Dial func(network, addr string) (net.Conn, error) } // ImpersonationConfig has all the available impersonation options From e8061fe3131793fa8d1dbade7b9a6c62f72e0ed4 Mon Sep 17 00:00:00 2001 From: David Eads Date: Fri, 13 Oct 2017 10:59:16 -0400 Subject: [PATCH 5/6] UPSTREAM: 53896: decode admission responses into a fresh object --- .../kubernetes/plugin/pkg/admission/webhook/admission.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go index b3995e59dde2..7ed48812b9d1 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go @@ -233,20 +233,21 @@ func (a *GenericAdmissionWebhook) callHook(ctx context.Context, h *v1alpha1.Exte if err != nil { return &ErrCallingWebhook{WebhookName: h.Name, Reason: err} } - if err := client.Post().Context(ctx).Body(&request).Do().Into(&request); err != nil { + response := &admissionv1alpha1.AdmissionReview{} + if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { return &ErrCallingWebhook{WebhookName: h.Name, Reason: err} } - if request.Status.Allowed { + if response.Status.Allowed { return nil } - if request.Status.Result == nil { + if response.Status.Result == nil { return fmt.Errorf("admission webhook %q denied the request without explanation", h.Name) } return &apierrors.StatusError{ - ErrStatus: *request.Status.Result, + ErrStatus: *response.Status.Result, } } From b8e3c19ed9047701d83a9c0a0c3559cf3cf4992e Mon Sep 17 00:00:00 2001 From: David Eads Date: Fri, 13 Oct 2017 09:53:55 -0400 Subject: [PATCH 6/6] UPSTREAM: : drop in 1.9 rebase. Shims enough admission webhook to work without modifying api --- .../apis/admissionregistration/validation/validation.go | 3 --- .../kubernetes/plugin/pkg/admission/webhook/admission.go | 9 ++++++++- .../plugin/pkg/admission/webhook/admission_test.go | 4 ++-- vendor/k8s.io/kubernetes/test/e2e/framework/framework.go | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go index d6e45cb292bc..a6e862366b06 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/admissionregistration/validation/validation.go @@ -189,9 +189,6 @@ func validateExternalAdmissionHook(hook *admissionregistration.ExternalAdmission if len(hook.Name) == 0 { allErrors = append(allErrors, field.Required(fldPath.Child("name"), "")) } - if errs := validationutil.IsDNS1123Subdomain(hook.Name); len(errs) > 0 { - allErrors = append(allErrors, field.Invalid(fldPath.Child("name"), hook.Name, strings.Join(errs, ","))) - } if len(strings.Split(hook.Name, ".")) < 3 { allErrors = append(allErrors, field.Invalid(fldPath.Child("name"), hook.Name, "should be a domain with at least two dots")) } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go index 7ed48812b9d1..8281825649b3 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go @@ -23,6 +23,7 @@ import ( "io" "net" "net/http" + "strings" "sync" "time" @@ -233,8 +234,14 @@ func (a *GenericAdmissionWebhook) callHook(ctx context.Context, h *v1alpha1.Exte if err != nil { return &ErrCallingWebhook{WebhookName: h.Name, Reason: err} } + + tokens := strings.SplitN(h.Name, "/", 2) + urlPath := "" + if len(tokens) == 2 { + urlPath = tokens[1] + } response := &admissionv1alpha1.AdmissionReview{} - if err := client.Post().Context(ctx).Body(&request).Do().Into(response); err != nil { + if err := client.Post().Context(ctx).AbsPath(urlPath).Body(&request).Do().Into(response); err != nil { return &ErrCallingWebhook{WebhookName: h.Name, Reason: err} } diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go index 8dee1f3a055d..c423b6784257 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go @@ -174,7 +174,7 @@ func TestAdmit(t *testing.T) { "match & disallow": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ - Name: "disallow", + Name: "disallow/disallow", ClientConfig: ccfg, Rules: matchEverythingRules, }}, @@ -185,7 +185,7 @@ func TestAdmit(t *testing.T) { "match & disallow ii": { hookSource: fakeHookSource{ hooks: []registrationv1alpha1.ExternalAdmissionHook{{ - Name: "disallowReason", + Name: "disallowReason/disallowReason", ClientConfig: ccfg, Rules: matchEverythingRules, }}, diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go index baa1e2a0451a..748c7009f8d9 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go @@ -137,12 +137,13 @@ func NewFramework(baseName string, options FrameworkOptions, client clientset.In // a k8s.io/client-go/pkg/client/restclient.Config. It's not a deep copy. Two // configs may share some common struct. func getClientRepoConfig(src *restclient.Config) (dst *clientreporestclient.Config) { - skippedFields := sets.NewString("Transport", "WrapTransport", "RateLimiter", "AuthConfigPersister") + skippedFields := sets.NewString("Transport", "WrapTransport", "RateLimiter", "AuthConfigPersister", "Dial") dst = &clientreporestclient.Config{} dst.Transport = src.Transport dst.WrapTransport = src.WrapTransport dst.RateLimiter = src.RateLimiter dst.AuthConfigPersister = src.AuthConfigPersister + dst.Dial = src.Dial sv := reflect.ValueOf(src).Elem() dv := reflect.ValueOf(dst).Elem() for i := 0; i < sv.NumField(); i++ {