vendor dependencies

This commit is contained in:
Sergiusz Urbaniak 2019-04-24 11:06:03 +02:00
parent 604208ef4f
commit 72abf135d6
1156 changed files with 78178 additions and 105799 deletions

View file

@ -20,18 +20,19 @@ import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net"
"net/http"
goruntime "runtime"
"sort"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/emicklei/go-restful-swagger12"
jsonpatch "github.com/evanphx/json-patch"
"github.com/go-openapi/spec"
"github.com/pborman/uuid"
"k8s.io/klog"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
@ -62,10 +63,10 @@ import (
"k8s.io/client-go/informers"
restclient "k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert"
"k8s.io/component-base/logs"
openapicommon "k8s.io/kube-openapi/pkg/common"
// install apis
"github.com/golang/glog"
_ "k8s.io/apiserver/pkg/apis/apiserver/install"
)
@ -101,7 +102,6 @@ type Config struct {
AdmissionControl admission.Interface
CorsAllowedOriginList []string
EnableSwaggerUI bool
EnableIndex bool
EnableProfiling bool
EnableDiscovery bool
@ -113,8 +113,6 @@ type Config struct {
// Version will enable the /version endpoint if non-nil
Version *version.Info
// LegacyAuditWriter is the destination for audit logs. If nil, they will not be written.
LegacyAuditWriter io.Writer
// AuditBackend is where audit events are sent to.
AuditBackend audit.Backend
// AuditPolicyChecker makes the decision of whether and how to audit log a request.
@ -147,8 +145,6 @@ type Config struct {
Serializer runtime.NegotiatedSerializer
// OpenAPIConfig will be used in generating OpenAPI spec. This is nil by default. Use DefaultOpenAPIConfig for "working" defaults.
OpenAPIConfig *openapicommon.Config
// SwaggerConfig will be used in generating Swagger spec. This is nil by default. Use DefaultSwaggerConfig for "working" defaults.
SwaggerConfig *swagger.Config
// RESTOptionsGetter is used to construct RESTStorage types via the generic registry.
RESTOptionsGetter genericregistry.RESTOptionsGetter
@ -159,6 +155,13 @@ type Config struct {
// If specified, long running requests such as watch will be allocated a random timeout between this value, and
// twice this value. Note that it is up to the request handlers to ignore or honor this timeout. In seconds.
MinRequestTimeout int
// The limit on the total size increase all "copy" operations in a json
// patch may cause.
// This affects all places that applies json patch in the binary.
JSONPatchMaxCopyBytes int64
// The limit on the request body size that would be accepted and decoded in a write request.
// 0 means no limit.
MaxRequestBodyBytes int64
// MaxRequestsInFlight is the maximum number of parallel non-long-running requests. Every further
// request has to wait. Applies only to non-mutating requests.
MaxRequestsInFlight int
@ -181,9 +184,6 @@ type Config struct {
// values below here are targets for removal
//===========================================================================
// The port on PublicAddress where a read-write server will be installed.
// Defaults to 6443 if not set.
ReadWritePort int
// PublicAddress is the IP address where members of the cluster (kubelet,
// kube-proxy, services, etc.) can reach the GenericAPIServer.
// If nil or 0.0.0.0, the host's default interface will be used.
@ -232,6 +232,9 @@ type SecureServingInfo struct {
}
type AuthenticationInfo struct {
// APIAudiences is a list of identifier that the API identifies as. This is
// used by some authenticators to validate audience bound credentials.
APIAudiences authenticator.Audiences
// Authenticator determines which subject is making the request
Authenticator authenticator.Request
// SupportsBasicAuth indicates that's at least one Authenticator supports basic auth
@ -249,21 +252,36 @@ type AuthorizationInfo struct {
// NewConfig returns a Config struct with the default values
func NewConfig(codecs serializer.CodecFactory) *Config {
return &Config{
Serializer: codecs,
ReadWritePort: 443,
BuildHandlerChainFunc: DefaultBuildHandlerChain,
HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup),
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
DisabledPostStartHooks: sets.NewString(),
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz},
EnableIndex: true,
EnableDiscovery: true,
EnableProfiling: true,
EnableMetrics: true,
MaxRequestsInFlight: 400,
MaxMutatingRequestsInFlight: 200,
RequestTimeout: time.Duration(60) * time.Second,
MinRequestTimeout: 1800,
Serializer: codecs,
BuildHandlerChainFunc: DefaultBuildHandlerChain,
HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup),
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
DisabledPostStartHooks: sets.NewString(),
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz, healthz.LogHealthz},
EnableIndex: true,
EnableDiscovery: true,
EnableProfiling: true,
EnableMetrics: true,
MaxRequestsInFlight: 400,
MaxMutatingRequestsInFlight: 200,
RequestTimeout: time.Duration(60) * time.Second,
MinRequestTimeout: 1800,
// 10MB is the recommended maximum client request size in bytes
// the etcd server should accept. See
// https://github.com/etcd-io/etcd/blob/release-3.3/etcdserver/server.go#L90.
// A request body might be encoded in json, and is converted to
// proto when persisted in etcd. Assuming the upper bound of
// the size ratio is 10:1, we set 100MB as the largest size
// increase the "copy" operations in a json patch may cause.
JSONPatchMaxCopyBytes: int64(100 * 1024 * 1024),
// 10MB is the recommended maximum client request size in bytes
// the etcd server should accept. See
// https://github.com/etcd-io/etcd/blob/release-3.3/etcdserver/server.go#L90.
// A request body might be encoded in json, and is converted to
// proto when persisted in etcd. Assuming the upper bound of
// the size ratio is 10:1, we set 100MB as the largest request
// body size to be accepted and decoded in a write request.
MaxRequestBodyBytes: int64(100 * 1024 * 1024),
EnableAPIResponseCompression: utilfeature.DefaultFeatureGate.Enabled(features.APIResponseCompression),
// Default to treating watch as a long-running operation
@ -282,7 +300,7 @@ func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig {
func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, defNamer *apiopenapi.DefinitionNamer) *openapicommon.Config {
return &openapicommon.Config{
ProtocolList: []string{"https"},
IgnorePrefixes: []string{"/swaggerapi"},
IgnorePrefixes: []string{},
Info: &spec.Info{
InfoProps: spec.InfoProps{
Title: "Generic API Server",
@ -299,23 +317,6 @@ func DefaultOpenAPIConfig(getDefinitions openapicommon.GetOpenAPIDefinitions, de
}
}
// DefaultSwaggerConfig returns a default configuration without WebServiceURL and
// WebServices set.
func DefaultSwaggerConfig() *swagger.Config {
return &swagger.Config{
ApiPath: "/swaggerapi",
SwaggerPath: "/swaggerui/",
SwaggerFilePath: "/swagger-ui/",
SchemaFormatHandler: func(typeName string) string {
switch typeName {
case "metav1.Time", "*metav1.Time":
return "date-time"
}
return ""
},
}
}
func (c *AuthenticationInfo) ApplyClientCert(clientCAFile string, servingInfo *SecureServingInfo) error {
if servingInfo != nil {
if len(clientCAFile) > 0 {
@ -354,39 +355,47 @@ type CompletedConfig struct {
// Complete fills in any fields not set that are required to have valid data and can be derived
// from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver.
func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
host := c.ExternalAddress
if host == "" && c.PublicAddress != nil {
host = c.PublicAddress.String()
if len(c.ExternalAddress) == 0 && c.PublicAddress != nil {
c.ExternalAddress = c.PublicAddress.String()
}
// if there is no port, and we have a ReadWritePort, use that
if _, _, err := net.SplitHostPort(host); err != nil && c.ReadWritePort != 0 {
host = net.JoinHostPort(host, strconv.Itoa(c.ReadWritePort))
// if there is no port, and we listen on one securely, use that one
if _, _, err := net.SplitHostPort(c.ExternalAddress); err != nil {
if c.SecureServing == nil {
klog.Fatalf("cannot derive external address port without listening on a secure port.")
}
_, port, err := c.SecureServing.HostPort()
if err != nil {
klog.Fatalf("cannot derive external address from the secure port: %v", err)
}
c.ExternalAddress = net.JoinHostPort(c.ExternalAddress, strconv.Itoa(port))
}
c.ExternalAddress = host
if c.OpenAPIConfig != nil && c.OpenAPIConfig.SecurityDefinitions != nil {
// Setup OpenAPI security: all APIs will have the same authentication for now.
c.OpenAPIConfig.DefaultSecurity = []map[string][]string{}
keys := []string{}
for k := range *c.OpenAPIConfig.SecurityDefinitions {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
c.OpenAPIConfig.DefaultSecurity = append(c.OpenAPIConfig.DefaultSecurity, map[string][]string{k: {}})
}
if c.OpenAPIConfig.CommonResponses == nil {
c.OpenAPIConfig.CommonResponses = map[int]spec.Response{}
}
if _, exists := c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized]; !exists {
c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized] = spec.Response{
ResponseProps: spec.ResponseProps{
Description: "Unauthorized",
},
if c.OpenAPIConfig != nil {
if c.OpenAPIConfig.SecurityDefinitions != nil {
// Setup OpenAPI security: all APIs will have the same authentication for now.
c.OpenAPIConfig.DefaultSecurity = []map[string][]string{}
keys := []string{}
for k := range *c.OpenAPIConfig.SecurityDefinitions {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
c.OpenAPIConfig.DefaultSecurity = append(c.OpenAPIConfig.DefaultSecurity, map[string][]string{k: {}})
}
if c.OpenAPIConfig.CommonResponses == nil {
c.OpenAPIConfig.CommonResponses = map[int]spec.Response{}
}
if _, exists := c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized]; !exists {
c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized] = spec.Response{
ResponseProps: spec.ResponseProps{
Description: "Unauthorized",
},
}
}
}
// make sure we populate info, and info.version, if not manually set
if c.OpenAPIConfig.Info == nil {
c.OpenAPIConfig.Info = &spec.Info{}
}
@ -398,35 +407,11 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo
}
}
}
if c.SwaggerConfig != nil && len(c.SwaggerConfig.WebServicesUrl) == 0 {
if c.SecureServing != nil {
c.SwaggerConfig.WebServicesUrl = "https://" + c.ExternalAddress
} else {
c.SwaggerConfig.WebServicesUrl = "http://" + c.ExternalAddress
}
}
if c.DiscoveryAddresses == nil {
c.DiscoveryAddresses = discovery.DefaultAddresses{DefaultAddress: c.ExternalAddress}
}
// If the loopbackclientconfig is specified AND it has a token for use against the API server
// wrap the authenticator and authorizer in loopback authentication logic
if c.Authentication.Authenticator != nil && c.Authorization.Authorizer != nil && c.LoopbackClientConfig != nil && len(c.LoopbackClientConfig.BearerToken) > 0 {
privilegedLoopbackToken := c.LoopbackClientConfig.BearerToken
var uid = uuid.NewRandom().String()
tokens := make(map[string]*user.DefaultInfo)
tokens[privilegedLoopbackToken] = &user.DefaultInfo{
Name: user.APIServerUser,
UID: uid,
Groups: []string{user.SystemPrivilegedGroup},
}
tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens)
c.Authentication.Authenticator = authenticatorunion.New(tokenAuthenticator, c.Authentication.Authenticator)
tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
c.Authorization.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorization.Authorizer)
}
AuthorizeClientBearerToken(c.LoopbackClientConfig, &c.Authentication, &c.Authorization)
if c.RequestInfoResolver == nil {
c.RequestInfoResolver = NewRequestInfoResolver(c)
@ -464,6 +449,7 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
admissionControl: c.AdmissionControl,
Serializer: c.Serializer,
AuditBackend: c.AuditBackend,
Authorizer: c.Authorization.Authorizer,
delegationTarget: delegationTarget,
HandlerChainWaitGroup: c.HandlerChainWaitGroup,
@ -477,7 +463,6 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
listedPathProvider: apiServerHandler,
swaggerConfig: c.SwaggerConfig,
openAPIConfig: c.OpenAPIConfig,
postStartHooks: map[string]postStartHookEntry{},
@ -489,6 +474,20 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer),
enableAPIResponseCompression: c.EnableAPIResponseCompression,
maxRequestBodyBytes: c.MaxRequestBodyBytes,
}
for {
if c.JSONPatchMaxCopyBytes <= 0 {
break
}
existing := atomic.LoadInt64(&jsonpatch.AccumulatedCopySizeLimit)
if existing > 0 && existing < c.JSONPatchMaxCopyBytes {
break
}
if atomic.CompareAndSwapInt64(&jsonpatch.AccumulatedCopySizeLimit, existing, c.JSONPatchMaxCopyBytes) {
break
}
}
for k, v := range delegationTarget.PostStartHooks() {
@ -545,16 +544,10 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
handler := genericapifilters.WithAuthorization(apiHandler, c.Authorization.Authorizer, c.Serializer)
handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.LongRunningFunc)
handler = genericapifilters.WithImpersonation(handler, c.Authorization.Authorizer, c.Serializer)
if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) {
handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc)
} else {
handler = genericapifilters.WithLegacyAudit(handler, c.LegacyAuditWriter)
}
handler = genericapifilters.WithAudit(handler, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc)
failedHandler := genericapifilters.Unauthorized(c.Serializer, c.Authentication.SupportsBasicAuth)
if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) {
failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.AuditBackend, c.AuditPolicyChecker)
}
handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler)
failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.AuditBackend, c.AuditPolicyChecker)
handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences)
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc, c.RequestTimeout)
handler = genericfilters.WithWaitGroup(handler, c.LongRunningFunc, c.HandlerChainWaitGroup)
@ -567,24 +560,13 @@ func installAPI(s *GenericAPIServer, c *Config) {
if c.EnableIndex {
routes.Index{}.Install(s.listedPathProvider, s.Handler.NonGoRestfulMux)
}
if c.SwaggerConfig != nil && c.EnableSwaggerUI {
routes.SwaggerUI{}.Install(s.Handler.NonGoRestfulMux)
}
if c.EnableProfiling {
routes.Profiling{}.Install(s.Handler.NonGoRestfulMux)
if c.EnableContentionProfiling {
goruntime.SetBlockProfileRate(1)
}
// so far, only logging related endpoints are considered valid to add for these debug flags.
routes.DebugFlags{}.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler(
routes.StringFlagSetterFunc(func(val string) (string, error) {
var level glog.Level
if err := level.Set(val); err != nil {
return "", fmt.Errorf("failed set glog.logging.verbosity %s: %v", val, err)
}
return "successfully set glog.logging.verbosity to " + val, nil
}),
))
routes.DebugFlags{}.Install(s.Handler.NonGoRestfulMux, "v", routes.StringFlagPutHandler(logs.GlogSetter))
}
if c.EnableMetrics {
if c.EnableProfiling {
@ -614,3 +596,42 @@ func NewRequestInfoResolver(c *Config) *apirequest.RequestInfoFactory {
GrouplessAPIPrefixes: legacyAPIPrefixes,
}
}
func (s *SecureServingInfo) HostPort() (string, int, error) {
if s == nil || s.Listener == nil {
return "", 0, fmt.Errorf("no listener found")
}
addr := s.Listener.Addr().String()
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
return "", 0, fmt.Errorf("failed to get port from listener address %q: %v", addr, err)
}
port, err := strconv.Atoi(portStr)
if err != nil {
return "", 0, fmt.Errorf("invalid non-numeric port %q", portStr)
}
return host, port, nil
}
// AuthorizeClientBearerToken wraps the authenticator and authorizer in loopback authentication logic
// if the loopback client config is specified AND it has a bearer token.
func AuthorizeClientBearerToken(loopback *restclient.Config, authn *AuthenticationInfo, authz *AuthorizationInfo) {
if loopback == nil || authn == nil || authz == nil || authn.Authenticator == nil && authz.Authorizer == nil || len(loopback.BearerToken) == 0 {
return
}
privilegedLoopbackToken := loopback.BearerToken
var uid = uuid.NewRandom().String()
tokens := make(map[string]*user.DefaultInfo)
tokens[privilegedLoopbackToken] = &user.DefaultInfo{
Name: user.APIServerUser,
UID: uid,
Groups: []string{user.SystemPrivilegedGroup},
}
tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens)
authn.Authenticator = authenticatorunion.New(tokenAuthenticator, authn.Authenticator)
tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
authz.Authorizer = authorizerunion.New(tokenAuthorizer, authz.Authorizer)
}