From cd297546807fc08546905a2b96879d13bcf3a30b Mon Sep 17 00:00:00 2001 From: deads2k Date: Thu, 9 Mar 2017 14:39:56 -0500 Subject: [PATCH] move legacy insecure options out of the main flow --- cmd/kube-apiserver/app/BUILD | 1 + cmd/kube-apiserver/app/server.go | 70 ++++++----- federation/cmd/federation-apiserver/app/BUILD | 1 + .../cmd/federation-apiserver/app/server.go | 12 +- pkg/kubeapiserver/BUILD | 1 + pkg/kubeapiserver/options/BUILD | 1 + pkg/kubeapiserver/options/serving.go | 13 +- pkg/kubeapiserver/server/BUILD | 35 ++++++ pkg/kubeapiserver/server/insecure_handler.go | 113 ++++++++++++++++++ pkg/master/master_test.go | 2 +- .../src/k8s.io/apiserver/pkg/server/config.go | 57 +++------ .../apiserver/pkg/server/config_selfclient.go | 30 +---- .../apiserver/pkg/server/genericapiserver.go | 15 +-- .../pkg/server/genericapiserver_test.go | 19 ++- .../apiserver/pkg/server/options/serving.go | 4 +- .../pkg/server/options/serving_test.go | 1 - .../src/k8s.io/apiserver/pkg/server/serve.go | 21 +--- test/integration/examples/apiserver_test.go | 6 +- test/integration/federation/framework/api.go | 2 +- 19 files changed, 253 insertions(+), 151 deletions(-) create mode 100644 pkg/kubeapiserver/server/BUILD create mode 100644 pkg/kubeapiserver/server/insecure_handler.go diff --git a/cmd/kube-apiserver/app/BUILD b/cmd/kube-apiserver/app/BUILD index d1dfbcad7d..a0216e0da2 100644 --- a/cmd/kube-apiserver/app/BUILD +++ b/cmd/kube-apiserver/app/BUILD @@ -33,6 +33,7 @@ go_library( "//pkg/kubeapiserver/admission:go_default_library", "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/kubeapiserver/options:go_default_library", + "//pkg/kubeapiserver/server:go_default_library", "//pkg/master:go_default_library", "//pkg/master/thirdparty:go_default_library", "//pkg/master/tunneler:go_default_library", diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 609bfbcaf7..c23716fd2e 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -67,6 +67,7 @@ import ( kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" + kubeserver "k8s.io/kubernetes/pkg/kubeapiserver/server" "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/master/tunneler" "k8s.io/kubernetes/pkg/registry/cachesize" @@ -96,7 +97,7 @@ cluster's shared state through which all other components interact.`, // Run runs the specified APIServer. This should never exit. func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { - kubeAPIServerConfig, sharedInformers, err := CreateKubeAPIServerConfig(runOptions) + kubeAPIServerConfig, sharedInformers, insecureServingOptions, err := CreateKubeAPIServerConfig(runOptions) if err != nil { return err } @@ -105,6 +106,14 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { return err } + // run the insecure server now, don't block. It doesn't have any aggregator goodies since authentication wouldn't work + if insecureServingOptions != nil { + insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(kubeAPIServer.GenericAPIServer.HandlerContainer.ServeMux, kubeAPIServerConfig.GenericConfig) + if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil { + return err + } + } + // if we're starting up a hacked up version of this API server for a weird test case, // just start the API server as is because clients don't get built correctly when you do this if len(os.Getenv("KUBE_API_VERSIONS")) > 0 { @@ -140,24 +149,24 @@ func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, sharedInformers inf } // CreateKubeAPIServerConfig creates all the resources for running the API server, but runs none of them -func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, informers.SharedInformerFactory, error) { +func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, informers.SharedInformerFactory, *kubeserver.InsecureServingInfo, error) { // set defaults in the options before trying to create the generic config if err := defaultOptions(s); err != nil { - return nil, nil, err + return nil, nil, nil, err } // validate options if errs := s.Validate(); len(errs) != 0 { - return nil, nil, utilerrors.NewAggregate(errs) + return nil, nil, nil, utilerrors.NewAggregate(errs) } - genericConfig, sharedInformers, err := BuildGenericConfig(s) + genericConfig, sharedInformers, insecureServingOptions, err := BuildGenericConfig(s) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if err := utilwait.PollImmediate(etcdRetryInterval, etcdRetryLimit*etcdRetryInterval, preflight.EtcdConnection{ServerList: s.Etcd.StorageConfig.ServerList}.CheckEtcdServers); err != nil { - return nil, nil, fmt.Errorf("error waiting for etcd connection: %v", err) + return nil, nil, nil, fmt.Errorf("error waiting for etcd connection: %v", err) } capabilities.Initialize(capabilities.Capabilities{ @@ -179,7 +188,7 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, inf var installSSHKey tunneler.InstallSSHKey cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider.CloudProvider, s.CloudProvider.CloudConfigFile) if err != nil { - return nil, nil, fmt.Errorf("cloud provider could not be initialized: %v", err) + return nil, nil, nil, fmt.Errorf("cloud provider could not be initialized: %v", err) } if cloud != nil { if instances, supported := cloud.Instances(); supported { @@ -187,10 +196,10 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, inf } } if s.KubeletConfig.Port == 0 { - return nil, nil, fmt.Errorf("must enable kubelet port if proxy ssh-tunneling is specified") + return nil, nil, nil, fmt.Errorf("must enable kubelet port if proxy ssh-tunneling is specified") } if s.KubeletConfig.ReadOnlyPort == 0 { - return nil, nil, fmt.Errorf("must enable kubelet readonly port if proxy ssh-tunneling is specified") + return nil, nil, nil, fmt.Errorf("must enable kubelet readonly port if proxy ssh-tunneling is specified") } // Set up the nodeTunneler // TODO(cjcullen): If we want this to handle per-kubelet ports or other @@ -216,21 +225,21 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, inf serviceIPRange, apiServerServiceIP, err := master.DefaultServiceIPRange(s.ServiceClusterIPRange) if err != nil { - return nil, nil, err + return nil, nil, nil, err } storageFactory, err := BuildStorageFactory(s) if err != nil { - return nil, nil, err + return nil, nil, nil, err } clientCA, err := readCAorNil(s.Authentication.ClientCert.ClientCA) if err != nil { - return nil, nil, err + return nil, nil, nil, err } requestHeaderProxyCA, err := readCAorNil(s.Authentication.RequestHeader.ClientCAFile) if err != nil { - return nil, nil, err + return nil, nil, nil, err } config := &master.Config{ @@ -266,29 +275,30 @@ func CreateKubeAPIServerConfig(s *options.ServerRunOptions) (*master.Config, inf MasterCount: s.MasterCount, } - return config, sharedInformers, nil + return config, sharedInformers, insecureServingOptions, nil } // BuildGenericConfig takes the master server options and produces the genericapiserver.Config associated with it -func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, informers.SharedInformerFactory, error) { +func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, informers.SharedInformerFactory, *kubeserver.InsecureServingInfo, error) { genericConfig := genericapiserver.NewConfig(api.Codecs) if err := s.GenericServerRunOptions.ApplyTo(genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } - if err := s.InsecureServing.ApplyTo(genericConfig); err != nil { - return nil, nil, err + insecureServingOptions, err := s.InsecureServing.ApplyTo(genericConfig) + if err != nil { + return nil, nil, nil, err } if err := s.SecureServing.ApplyTo(genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } if err := s.Authentication.ApplyTo(genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } if err := s.Audit.ApplyTo(genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } if err := s.Features.ApplyTo(genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } genericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions, api.Scheme) @@ -306,10 +316,10 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, storageFactory, err := BuildStorageFactory(s) if err != nil { - return nil, nil, err + return nil, nil, nil, err } if err := s.Etcd.ApplyWithStorageFactoryTo(storageFactory, genericConfig); err != nil { - return nil, nil, err + return nil, nil, nil, err } // Use protobufs for self-communication. @@ -322,7 +332,7 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, if err != nil { kubeAPIVersions := os.Getenv("KUBE_API_VERSIONS") if len(kubeAPIVersions) == 0 { - return nil, nil, fmt.Errorf("failed to create clientset: %v", err) + return nil, nil, nil, fmt.Errorf("failed to create clientset: %v", err) } // KUBE_API_VERSIONS is used in test-update-storage-objects.sh, disabling a number of API @@ -335,20 +345,20 @@ func BuildGenericConfig(s *options.ServerRunOptions) (*genericapiserver.Config, genericConfig.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, storageFactory, client, sharedInformers) if err != nil { - return nil, nil, fmt.Errorf("invalid authentication config: %v", err) + return nil, nil, nil, fmt.Errorf("invalid authentication config: %v", err) } genericConfig.Authorizer, err = BuildAuthorizer(s, sharedInformers) if err != nil { - return nil, nil, fmt.Errorf("invalid authorization config: %v", err) + return nil, nil, nil, fmt.Errorf("invalid authorization config: %v", err) } genericConfig.AdmissionControl, err = BuildAdmission(s, client, sharedInformers, genericConfig.Authorizer) if err != nil { - return nil, nil, fmt.Errorf("failed to initialize admission: %v", err) + return nil, nil, nil, fmt.Errorf("failed to initialize admission: %v", err) } - return genericConfig, sharedInformers, nil + return genericConfig, sharedInformers, insecureServingOptions, nil } // BuildAdmission constructs the admission chain diff --git a/federation/cmd/federation-apiserver/app/BUILD b/federation/cmd/federation-apiserver/app/BUILD index b5cf9574af..b95951d13d 100644 --- a/federation/cmd/federation-apiserver/app/BUILD +++ b/federation/cmd/federation-apiserver/app/BUILD @@ -42,6 +42,7 @@ go_library( "//pkg/kubeapiserver:go_default_library", "//pkg/kubeapiserver/admission:go_default_library", "//pkg/kubeapiserver/options:go_default_library", + "//pkg/kubeapiserver/server:go_default_library", "//pkg/registry/autoscaling/horizontalpodautoscaler/storage:go_default_library", "//pkg/registry/batch/job/storage:go_default_library", "//pkg/registry/cachesize:go_default_library", diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index f1cb004c7d..0af1beff32 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -46,6 +46,7 @@ import ( "k8s.io/kubernetes/pkg/kubeapiserver" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" + kubeserver "k8s.io/kubernetes/pkg/kubeapiserver/server" "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/routes" "k8s.io/kubernetes/pkg/version" @@ -106,7 +107,8 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { if err := s.GenericServerRunOptions.ApplyTo(genericConfig); err != nil { return err } - if err := s.InsecureServing.ApplyTo(genericConfig); err != nil { + insecureServingOptions, err := s.InsecureServing.ApplyTo(genericConfig) + if err != nil { return err } if err := s.SecureServing.ApplyTo(genericConfig); err != nil { @@ -236,6 +238,14 @@ func NonBlockingRun(s *options.ServerRunOptions, stopCh <-chan struct{}) error { // installBatchAPIs(m, genericConfig.RESTOptionsGetter) // installAutoscalingAPIs(m, genericConfig.RESTOptionsGetter) + // run the insecure server now + if insecureServingOptions != nil { + insecureHandlerChain := kubeserver.BuildInsecureHandlerChain(m.HandlerContainer.ServeMux, genericConfig) + if err := kubeserver.NonBlockingRun(insecureServingOptions, insecureHandlerChain, stopCh); err != nil { + return err + } + } + err = m.PrepareRun().NonBlockingRun(stopCh) if err == nil { sharedInformers.Start(stopCh) diff --git a/pkg/kubeapiserver/BUILD b/pkg/kubeapiserver/BUILD index 064b1cc64b..1cf2c61888 100644 --- a/pkg/kubeapiserver/BUILD +++ b/pkg/kubeapiserver/BUILD @@ -40,6 +40,7 @@ filegroup( "//pkg/kubeapiserver/authenticator:all-srcs", "//pkg/kubeapiserver/authorizer:all-srcs", "//pkg/kubeapiserver/options:all-srcs", + "//pkg/kubeapiserver/server:all-srcs", ], tags = ["automanaged"], ) diff --git a/pkg/kubeapiserver/options/BUILD b/pkg/kubeapiserver/options/BUILD index 011ae259c3..b265143b8a 100644 --- a/pkg/kubeapiserver/options/BUILD +++ b/pkg/kubeapiserver/options/BUILD @@ -27,6 +27,7 @@ go_library( "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/kubeapiserver/authorizer:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", + "//pkg/kubeapiserver/server:go_default_library", "//vendor:github.com/golang/glog", "//vendor:github.com/pborman/uuid", "//vendor:github.com/spf13/pflag", diff --git a/pkg/kubeapiserver/options/serving.go b/pkg/kubeapiserver/options/serving.go index 4b6e2b7d10..d6d18c1acb 100644 --- a/pkg/kubeapiserver/options/serving.go +++ b/pkg/kubeapiserver/options/serving.go @@ -28,6 +28,7 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/server" genericoptions "k8s.io/apiserver/pkg/server/options" + kubeserver "k8s.io/kubernetes/pkg/kubeapiserver/server" ) // NewSecureServingOptions gives default values for the kube-apiserver and federation-apiserver which are not the options wanted by @@ -115,20 +116,20 @@ func (s *InsecureServingOptions) AddDeprecatedFlags(fs *pflag.FlagSet) { fs.MarkDeprecated("port", "see --insecure-port instead.") } -func (s *InsecureServingOptions) ApplyTo(c *server.Config) error { +func (s *InsecureServingOptions) ApplyTo(c *server.Config) (*kubeserver.InsecureServingInfo, error) { if s.BindPort <= 0 { - return nil + return nil, nil } - c.InsecureServingInfo = &server.ServingInfo{ + ret := &kubeserver.InsecureServingInfo{ BindAddress: net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort)), } var err error privilegedLoopbackToken := uuid.NewRandom().String() - if c.LoopbackClientConfig, err = c.InsecureServingInfo.NewLoopbackClientConfig(privilegedLoopbackToken); err != nil { - return err + if c.LoopbackClientConfig, err = ret.NewLoopbackClientConfig(privilegedLoopbackToken); err != nil { + return nil, err } - return nil + return ret, nil } diff --git a/pkg/kubeapiserver/server/BUILD b/pkg/kubeapiserver/server/BUILD new file mode 100644 index 0000000000..5a21a39266 --- /dev/null +++ b/pkg/kubeapiserver/server/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["insecure_handler.go"], + tags = ["automanaged"], + deps = [ + "//vendor:github.com/golang/glog", + "//vendor:k8s.io/apiserver/pkg/endpoints/filters", + "//vendor:k8s.io/apiserver/pkg/endpoints/request", + "//vendor:k8s.io/apiserver/pkg/server", + "//vendor:k8s.io/apiserver/pkg/server/filters", + "//vendor:k8s.io/client-go/rest", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/pkg/kubeapiserver/server/insecure_handler.go b/pkg/kubeapiserver/server/insecure_handler.go new file mode 100644 index 0000000000..80a4bc7288 --- /dev/null +++ b/pkg/kubeapiserver/server/insecure_handler.go @@ -0,0 +1,113 @@ +/* +Copyright 2016 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 server + +import ( + "net" + "net/http" + + "github.com/golang/glog" + + genericapifilters "k8s.io/apiserver/pkg/endpoints/filters" + apirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/server" + genericfilters "k8s.io/apiserver/pkg/server/filters" + "k8s.io/client-go/rest" +) + +// InsecureServingInfo is required to serve http. HTTP does NOT include authentication or authorization. +// You shouldn't be using this. It makes sig-auth sad. +// InsecureServingInfo *ServingInfo + +func BuildInsecureHandlerChain(apiHandler http.Handler, c *server.Config) http.Handler { + handler := genericapifilters.WithAudit(apiHandler, c.RequestContextMapper, c.AuditWriter) + handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") + handler = genericfilters.WithPanicRecovery(handler, c.RequestContextMapper) + handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc) + handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) + handler = genericapifilters.WithRequestInfo(handler, server.NewRequestInfoResolver(c), c.RequestContextMapper) + handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + + return handler +} + +type InsecureServingInfo struct { + // BindAddress is the ip:port to serve on + BindAddress string + // BindNetwork is the type of network to bind to - defaults to "tcp", accepts "tcp", + // "tcp4", and "tcp6". + BindNetwork string +} + +func (s *InsecureServingInfo) NewLoopbackClientConfig(token string) (*rest.Config, error) { + if s == nil { + return nil, nil + } + + host, port, err := server.LoopbackHostPort(s.BindAddress) + if err != nil { + return nil, err + } + + return &rest.Config{ + Host: "http://" + net.JoinHostPort(host, port), + // Increase QPS limits. The client is currently passed to all admission plugins, + // and those can be throttled in case of higher load on apiserver - see #22340 and #22422 + // for more details. Once #22422 is fixed, we may want to remove it. + QPS: 50, + Burst: 100, + }, nil +} + +// NonBlockingRun spawns the insecure http server. An error is +// returned if the ports cannot be listened on. +func NonBlockingRun(insecureServingInfo *InsecureServingInfo, insecureHandler http.Handler, stopCh <-chan struct{}) error { + // Use an internal stop channel to allow cleanup of the listeners on error. + internalStopCh := make(chan struct{}) + + if insecureServingInfo != nil && insecureHandler != nil { + if err := serveInsecurely(insecureServingInfo, insecureHandler, internalStopCh); err != nil { + close(internalStopCh) + return err + } + } + + // Now that the listener has bound successfully, it is the + // responsibility of the caller to close the provided channel to + // ensure cleanup. + go func() { + <-stopCh + close(internalStopCh) + }() + + return nil +} + +// serveInsecurely run the insecure http server. It fails only if the initial listen +// call fails. The actual server loop (stoppable by closing stopCh) runs in a go +// routine, i.e. serveInsecurely does not block. +func serveInsecurely(insecureServingInfo *InsecureServingInfo, insecureHandler http.Handler, stopCh <-chan struct{}) error { + insecureServer := &http.Server{ + Addr: insecureServingInfo.BindAddress, + Handler: insecureHandler, + MaxHeaderBytes: 1 << 20, + } + glog.Infof("Serving insecurely on %s", insecureServingInfo.BindAddress) + var err error + _, err = server.RunServer(insecureServer, insecureServingInfo.BindNetwork, stopCh) + return err +} diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index fdc028b7fb..f9b45c143c 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -148,7 +148,7 @@ func TestVersion(t *testing.T) { req, _ := http.NewRequest("GET", "/version", nil) resp := httptest.NewRecorder() - s.GenericAPIServer.InsecureHandler.ServeHTTP(resp, req) + s.GenericAPIServer.Handler.ServeHTTP(resp, req) if resp.Code != 200 { t.Fatalf("expected http 200, got: %d", resp.Code) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index 8b96194ec4..6efd6e8bef 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -116,8 +116,8 @@ type Config struct { // Fields you probably don't care about changing //=========================================================================== - // BuildHandlerChainsFunc allows you to build custom handler chains by decorating the apiHandler. - BuildHandlerChainsFunc func(apiHandler http.Handler, c *Config) (secure, insecure http.Handler) + // BuildHandlerChainFunc allows you to build custom handler chains by decorating the apiHandler. + BuildHandlerChainFunc func(apiHandler http.Handler, c *Config) (secure http.Handler) // DiscoveryAddresses is used to build the IPs pass to discovery. If nil, the ExternalAddress is // always reported DiscoveryAddresses DiscoveryAddresses @@ -152,10 +152,6 @@ type Config struct { // Predicate which is true for paths of long-running http requests LongRunningFunc genericfilters.LongRunningRequestCheck - // InsecureServingInfo is required to serve http. HTTP does NOT include authentication or authorization. - // You shouldn't be using this. It makes sig-auth sad. - InsecureServingInfo *ServingInfo - //=========================================================================== // values below here are targets for removal //=========================================================================== @@ -169,16 +165,12 @@ type Config struct { PublicAddress net.IP } -type ServingInfo struct { +type SecureServingInfo struct { // BindAddress is the ip:port to serve on BindAddress string // BindNetwork is the type of network to bind to - defaults to "tcp", accepts "tcp", // "tcp4", and "tcp6". BindNetwork string -} - -type SecureServingInfo struct { - ServingInfo // Cert is the main server cert which is used if SNI does not match. Cert must be non-nil and is // allowed to be in SNICerts. @@ -201,7 +193,7 @@ func NewConfig(codecs serializer.CodecFactory) *Config { Serializer: codecs, ReadWritePort: 443, RequestContextMapper: apirequest.NewRequestContextMapper(), - BuildHandlerChainsFunc: DefaultBuildHandlerChain, + BuildHandlerChainFunc: DefaultBuildHandlerChain, LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix), HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz}, EnableIndex: true, @@ -402,9 +394,8 @@ func (c completedConfig) constructServer() (*GenericAPIServer, error) { minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second, - SecureServingInfo: c.SecureServingInfo, - InsecureServingInfo: c.InsecureServingInfo, - ExternalAddress: c.ExternalAddress, + SecureServingInfo: c.SecureServingInfo, + ExternalAddress: c.ExternalAddress, apiGroupsForDiscovery: map[string]metav1.APIGroup{}, @@ -477,33 +468,23 @@ func (c completedConfig) buildHandlers(s *GenericAPIServer, delegate http.Handle installAPI(s, c.Config, delegate) - s.Handler, s.InsecureHandler = c.BuildHandlerChainsFunc(s.HandlerContainer.ServeMux, c.Config) + s.Handler = c.BuildHandlerChainFunc(s.HandlerContainer.ServeMux, c.Config) return s, nil } -func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) (secure, insecure http.Handler) { - generic := func(handler http.Handler) http.Handler { - handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") - handler = genericfilters.WithPanicRecovery(handler, c.RequestContextMapper) - handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc) - handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) - handler = genericapifilters.WithRequestInfo(handler, NewRequestInfoResolver(c), c.RequestContextMapper) - handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) - return handler - } - audit := func(handler http.Handler) http.Handler { - return genericapifilters.WithAudit(handler, c.RequestContextMapper, c.AuditWriter) - } - protect := func(handler http.Handler) http.Handler { - handler = genericapifilters.WithAuthorization(handler, c.RequestContextMapper, c.Authorizer) - handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer) - handler = audit(handler) // before impersonation to read original user - handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.SupportsBasicAuth)) - return handler - } - - return generic(protect(apiHandler)), generic(audit(apiHandler)) +func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { + handler := genericapifilters.WithAuthorization(apiHandler, c.RequestContextMapper, c.Authorizer) + handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer) + handler = genericapifilters.WithAudit(handler, c.RequestContextMapper, c.AuditWriter) + handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.SupportsBasicAuth)) + handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") + handler = genericfilters.WithPanicRecovery(handler, c.RequestContextMapper) + handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc) + handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) + handler = genericapifilters.WithRequestInfo(handler, NewRequestInfoResolver(c), c.RequestContextMapper) + handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + return handler } func installAPI(s *GenericAPIServer, c *Config, delegate http.Handler) { diff --git a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go index ba79760175..a027b60764 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient.go @@ -33,7 +33,7 @@ func (s *SecureServingInfo) NewLoopbackClientConfig(token string, loopbackCert [ return nil, nil } - host, port, err := s.ServingInfo.loopbackHostPort() + host, port, err := LoopbackHostPort(s.BindAddress) if err != nil { return nil, err } @@ -90,13 +90,13 @@ func findCA(chain []*x509.Certificate) (*x509.Certificate, error) { return nil, fmt.Errorf("no certificate with CA:TRUE found in chain") } -// loopbackHostPort returns the host and port loopback REST clients should use +// LoopbackHostPort returns the host and port loopback REST clients should use // to contact the server. -func (s *ServingInfo) loopbackHostPort() (string, string, error) { - host, port, err := net.SplitHostPort(s.BindAddress) +func LoopbackHostPort(bindAddress string) (string, string, error) { + host, port, err := net.SplitHostPort(bindAddress) if err != nil { // should never happen - return "", "", fmt.Errorf("invalid server bind address: %q", s.BindAddress) + return "", "", fmt.Errorf("invalid server bind address: %q", bindAddress) } // Value is expected to be an IP or DNS name, not "0.0.0.0". @@ -107,26 +107,6 @@ func (s *ServingInfo) loopbackHostPort() (string, string, error) { return host, port, nil } -func (s *ServingInfo) NewLoopbackClientConfig(token string) (*restclient.Config, error) { - if s == nil { - return nil, nil - } - - host, port, err := s.loopbackHostPort() - if err != nil { - return nil, err - } - - return &restclient.Config{ - Host: "http://" + net.JoinHostPort(host, port), - // Increase QPS limits. The client is currently passed to all admission plugins, - // and those can be throttled in case of higher load on apiserver - see #22340 and #22422 - // for more details. Once #22422 is fixed, we may want to remove it. - QPS: 50, - Burst: 100, - }, nil -} - func certMatchesName(cert *x509.Certificate, name string) bool { for _, certName := range cert.DNSNames { if certName == name { diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 21bb8af9da..4a62e65c3a 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -105,11 +105,10 @@ type GenericAPIServer struct { // The registered APIs HandlerContainer *genericmux.APIContainer - SecureServingInfo *SecureServingInfo - InsecureServingInfo *ServingInfo + SecureServingInfo *SecureServingInfo // numerical ports, set after listening - effectiveSecurePort, effectiveInsecurePort int + effectiveSecurePort int // ExternalAddress is the address (hostname or IP and port) that should be used in // external (public internet) URLs for this GenericAPIServer. @@ -123,8 +122,7 @@ type GenericAPIServer struct { Serializer runtime.NegotiatedSerializer // "Outputs" - Handler http.Handler - InsecureHandler http.Handler + Handler http.Handler // FallThroughHandler is the final HTTP handler in the chain. // It comes after all filters and the API handling FallThroughHandler *mux.PathRecorderMux @@ -277,13 +275,6 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error { } } - if s.InsecureServingInfo != nil && s.InsecureHandler != nil { - if err := s.serveInsecurely(internalStopCh); err != nil { - close(internalStopCh) - return err - } - } - // Now that both listeners have bound successfully, it is the // responsibility of the caller to close the provided channel to // ensure cleanup. diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index 58a0943264..bc500cefe3 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -202,7 +202,7 @@ func TestInstallAPIGroups(t *testing.T) { groupPaths = append(groupPaths, APIGroupPrefix+"/"+api.GroupMeta.GroupVersion.Group) // /apis/ } - server := httptest.NewServer(s.InsecureHandler) + server := httptest.NewServer(s.Handler) defer server.Close() for i := range apis { @@ -336,14 +336,11 @@ func TestCustomHandlerChain(t *testing.T) { var protected, called bool - config.BuildHandlerChainsFunc = func(apiHandler http.Handler, c *Config) (secure, insecure http.Handler) { + config.BuildHandlerChainFunc = func(apiHandler http.Handler, c *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - protected = true - apiHandler.ServeHTTP(w, req) - }), http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - protected = false - apiHandler.ServeHTTP(w, req) - }) + protected = true + apiHandler.ServeHTTP(w, req) + }) } handler := http.HandlerFunc(func(r http.ResponseWriter, req *http.Request) { called = true @@ -365,8 +362,6 @@ func TestCustomHandlerChain(t *testing.T) { for i, test := range []Test{ {s.Handler, "/nonswagger", true}, {s.Handler, "/secret", true}, - {s.InsecureHandler, "/nonswagger", false}, - {s.InsecureHandler, "/secret", false}, } { protected, called = false, false @@ -485,7 +480,7 @@ func TestDiscoveryAtAPIS(t *testing.T) { master, etcdserver, _, assert := newMaster(t) defer etcdserver.Terminate(t) - server := httptest.NewServer(master.InsecureHandler) + server := httptest.NewServer(master.Handler) groupList, err := getGroupList(server) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -535,7 +530,7 @@ func TestDiscoveryOrdering(t *testing.T) { master, etcdserver, _, assert := newMaster(t) defer etcdserver.Terminate(t) - server := httptest.NewServer(master.InsecureHandler) + server := httptest.NewServer(master.Handler) groupList, err := getGroupList(server) if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go index 103a99c47a..cfa4d1dba8 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -176,9 +176,7 @@ func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error { } secureServingInfo := &server.SecureServingInfo{ - ServingInfo: server.ServingInfo{ - BindAddress: net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort)), - }, + BindAddress: net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort)), } serverCertFile, serverKeyFile := s.ServerCert.CertKey.CertFile, s.ServerCert.CertKey.KeyFile diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go index d746a5c730..4d974d22f4 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go @@ -474,7 +474,6 @@ NextTest: t.Errorf("%q - failed applying the SecureServingOptions: %v", title, err) return } - config.InsecureServingInfo = nil s, err := config.Complete().New() if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/server/serve.go b/staging/src/k8s.io/apiserver/pkg/server/serve.go index 9c9712f085..4a1da40d58 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/serve.go +++ b/staging/src/k8s.io/apiserver/pkg/server/serve.go @@ -78,28 +78,13 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error { glog.Infof("Serving securely on %s", s.SecureServingInfo.BindAddress) var err error - s.effectiveSecurePort, err = runServer(secureServer, s.SecureServingInfo.BindNetwork, stopCh) + s.effectiveSecurePort, err = RunServer(secureServer, s.SecureServingInfo.BindNetwork, stopCh) return err } -// serveInsecurely run the insecure http server. It fails only if the initial listen -// call fails. The actual server loop (stoppable by closing stopCh) runs in a go -// routine, i.e. serveInsecurely does not block. -func (s *GenericAPIServer) serveInsecurely(stopCh <-chan struct{}) error { - insecureServer := &http.Server{ - Addr: s.InsecureServingInfo.BindAddress, - Handler: s.InsecureHandler, - MaxHeaderBytes: 1 << 20, - } - glog.Infof("Serving insecurely on %s", s.InsecureServingInfo.BindAddress) - var err error - s.effectiveInsecurePort, err = runServer(insecureServer, s.InsecureServingInfo.BindNetwork, stopCh) - return err -} - -// runServer listens on the given port, then spawns a go-routine continuously serving +// RunServer listens on the given port, then spawns a go-routine continuously serving // until the stopCh is closed. The port is returned. This function does not block. -func runServer(server *http.Server, network string, stopCh <-chan struct{}) (int, error) { +func RunServer(server *http.Server, network string, stopCh <-chan struct{}) (int, error) { if len(server.Addr) == 0 { return 0, errors.New("address cannot be empty") } diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index ad6dea52a1..368b8b9959 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -98,8 +98,8 @@ func TestAggregatedAPIServer(t *testing.T) { } kubeAPIServerOptions := options.NewServerRunOptions() - kubeAPIServerOptions.SecureServing.ServingOptions.BindAddress = net.ParseIP("127.0.0.1") - kubeAPIServerOptions.SecureServing.ServingOptions.BindPort = kubePort + kubeAPIServerOptions.SecureServing.BindAddress = net.ParseIP("127.0.0.1") + kubeAPIServerOptions.SecureServing.BindPort = kubePort kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir kubeAPIServerOptions.InsecureServing.BindPort = 0 kubeAPIServerOptions.Etcd.StorageConfig.ServerList = []string{framework.GetEtcdURLFromEnv()} @@ -112,7 +112,7 @@ func TestAggregatedAPIServer(t *testing.T) { kubeAPIServerOptions.Authentication.ClientCert.ClientCA = clientCACertFile.Name() kubeAPIServerOptions.Authorization.Mode = "RBAC" - kubeAPIServerConfig, sharedInformers, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions) + kubeAPIServerConfig, sharedInformers, _, err := app.CreateKubeAPIServerConfig(kubeAPIServerOptions) if err != nil { t.Fatal(err) } diff --git a/test/integration/federation/framework/api.go b/test/integration/federation/framework/api.go index ffcd1eccef..f4d92d8cd6 100644 --- a/test/integration/federation/framework/api.go +++ b/test/integration/federation/framework/api.go @@ -41,7 +41,7 @@ func getRunOptions() *options.ServerRunOptions { // Use a unique prefix to ensure isolation from other tests using the same etcd instance r.Etcd.StorageConfig.Prefix = uuid.New() // Disable secure serving - r.SecureServing.ServingOptions.BindPort = 0 + r.SecureServing.BindPort = 0 return r }