Merge pull request #82090 from liggitt/webhook-http2

Use http/1.1 for apiserver->webhook clients

Kubernetes-commit: f442b6ef320140730f544527597a140e535f1e1d
This commit is contained in:
Kubernetes Publisher 2019-08-30 06:26:54 -07:00
commit d4d906eb58
11 changed files with 42 additions and 14 deletions

4
Godeps/Godeps.json generated
View File

@ -344,11 +344,11 @@
}, },
{ {
"ImportPath": "k8s.io/api", "ImportPath": "k8s.io/api",
"Rev": "63b8484e5766" "Rev": "c43c3e1d5a79"
}, },
{ {
"ImportPath": "k8s.io/apimachinery", "ImportPath": "k8s.io/apimachinery",
"Rev": "e709f673dfd9" "Rev": "f1cbc0c8ff07"
}, },
{ {
"ImportPath": "k8s.io/gengo", "ImportPath": "k8s.io/gengo",

8
go.mod
View File

@ -26,8 +26,8 @@ require (
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c golang.org/x/time v0.0.0-20181108054448-85acf8d2951c
google.golang.org/appengine v1.5.0 // indirect google.golang.org/appengine v1.5.0 // indirect
k8s.io/api v0.0.0-20190830034750-63b8484e5766 k8s.io/api v0.0.0-20190830074751-c43c3e1d5a79
k8s.io/apimachinery v0.0.0-20190830034626-e709f673dfd9 k8s.io/apimachinery v0.0.0-20190830154629-f1cbc0c8ff07
k8s.io/klog v0.4.0 k8s.io/klog v0.4.0
k8s.io/utils v0.0.0-20190801114015-581e00157fb1 k8s.io/utils v0.0.0-20190801114015-581e00157fb1
sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml v1.1.0
@ -41,6 +41,6 @@ replace (
golang.org/x/sys => golang.org/x/sys v0.0.0-20190209173611-3b5209105503 golang.org/x/sys => golang.org/x/sys v0.0.0-20190209173611-3b5209105503
golang.org/x/text => golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db golang.org/x/text => golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db
golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d
k8s.io/api => k8s.io/api v0.0.0-20190830034750-63b8484e5766 k8s.io/api => k8s.io/api v0.0.0-20190830074751-c43c3e1d5a79
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190830034626-e709f673dfd9 k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190830154629-f1cbc0c8ff07
) )

4
go.sum
View File

@ -178,8 +178,8 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.0.0-20190830034750-63b8484e5766/go.mod h1:ZPzpiABYnAONRNqslkGU1hppe1VEXgsEJlFRIbP75G8= k8s.io/api v0.0.0-20190830074751-c43c3e1d5a79/go.mod h1:ZPzpiABYnAONRNqslkGU1hppe1VEXgsEJlFRIbP75G8=
k8s.io/apimachinery v0.0.0-20190830034626-e709f673dfd9/go.mod h1:OOC7vMsHyCzra5xu6r1bRXkXMH76iww9BeHOAAJof4U= k8s.io/apimachinery v0.0.0-20190830154629-f1cbc0c8ff07/go.mod h1:OOC7vMsHyCzra5xu6r1bRXkXMH76iww9BeHOAAJof4U=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=

View File

@ -211,6 +211,12 @@ type TLSClientConfig struct {
// CAData holds PEM-encoded bytes (typically read from a root certificates bundle). // CAData holds PEM-encoded bytes (typically read from a root certificates bundle).
// CAData takes precedence over CAFile // CAData takes precedence over CAFile
CAData []byte CAData []byte
// NextProtos is a list of supported application level protocols, in order of preference.
// Used to populate tls.Config.NextProtos.
// To indicate to the server http/1.1 is preferred over http/2, set to ["http/1.1", "h2"] (though the server is free to ignore that preference).
// To use only http/1.1, set to ["http/1.1"].
NextProtos []string
} }
var _ fmt.Stringer = TLSClientConfig{} var _ fmt.Stringer = TLSClientConfig{}
@ -236,6 +242,7 @@ func (c TLSClientConfig) String() string {
CertData: c.CertData, CertData: c.CertData,
KeyData: c.KeyData, KeyData: c.KeyData,
CAData: c.CAData, CAData: c.CAData,
NextProtos: c.NextProtos,
} }
// Explicitly mark non-empty credential fields as redacted. // Explicitly mark non-empty credential fields as redacted.
if len(cc.CertData) != 0 { if len(cc.CertData) != 0 {
@ -503,6 +510,7 @@ func AnonymousClientConfig(config *Config) *Config {
ServerName: config.ServerName, ServerName: config.ServerName,
CAFile: config.TLSClientConfig.CAFile, CAFile: config.TLSClientConfig.CAFile,
CAData: config.TLSClientConfig.CAData, CAData: config.TLSClientConfig.CAData,
NextProtos: config.TLSClientConfig.NextProtos,
}, },
RateLimiter: config.RateLimiter, RateLimiter: config.RateLimiter,
UserAgent: config.UserAgent, UserAgent: config.UserAgent,
@ -541,6 +549,7 @@ func CopyConfig(config *Config) *Config {
CertData: config.TLSClientConfig.CertData, CertData: config.TLSClientConfig.CertData,
KeyData: config.TLSClientConfig.KeyData, KeyData: config.TLSClientConfig.KeyData,
CAData: config.TLSClientConfig.CAData, CAData: config.TLSClientConfig.CAData,
NextProtos: config.TLSClientConfig.NextProtos,
}, },
UserAgent: config.UserAgent, UserAgent: config.UserAgent,
DisableCompression: config.DisableCompression, DisableCompression: config.DisableCompression,

View File

@ -497,6 +497,7 @@ func TestConfigSprint(t *testing.T) {
KeyFile: "a.key", KeyFile: "a.key",
CertData: []byte("fake cert"), CertData: []byte("fake cert"),
KeyData: []byte("fake key"), KeyData: []byte("fake key"),
NextProtos: []string{"h2", "http/1.1"},
}, },
UserAgent: "gobot", UserAgent: "gobot",
Transport: &fakeRoundTripper{}, Transport: &fakeRoundTripper{},
@ -508,7 +509,7 @@ func TestConfigSprint(t *testing.T) {
Dial: fakeDialFunc, Dial: fakeDialFunc,
} }
want := fmt.Sprintf( want := fmt.Sprintf(
`&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.AuthProviderConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: ""}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil)}, UserAgent:"gobot", DisableCompression:false, Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p)}`, `&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.AuthProviderConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: ""}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil), NextProtos:[]string{"h2", "http/1.1"}}, UserAgent:"gobot", DisableCompression:false, Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p)}`,
c.Transport, fakeWrapperFunc, c.RateLimiter, fakeDialFunc, c.Transport, fakeWrapperFunc, c.RateLimiter, fakeDialFunc,
) )

View File

@ -74,6 +74,7 @@ func (c *Config) TransportConfig() (*transport.Config, error) {
CertData: c.CertData, CertData: c.CertData,
KeyFile: c.KeyFile, KeyFile: c.KeyFile,
KeyData: c.KeyData, KeyData: c.KeyData,
NextProtos: c.NextProtos,
}, },
Username: c.Username, Username: c.Username,
Password: c.Password, Password: c.Password,

View File

@ -38,6 +38,11 @@ func (in *TLSClientConfig) DeepCopyInto(out *TLSClientConfig) {
*out = make([]byte, len(*in)) *out = make([]byte, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.NextProtos != nil {
in, out := &in.NextProtos, &out.NextProtos
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"strings"
"sync" "sync"
"time" "time"
@ -45,6 +46,7 @@ type tlsCacheKey struct {
keyData string keyData string
getCert string getCert string
serverName string serverName string
nextProtos string
dial string dial string
disableCompression bool disableCompression bool
} }
@ -114,6 +116,7 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) {
keyData: string(c.TLS.KeyData), keyData: string(c.TLS.KeyData),
getCert: fmt.Sprintf("%p", c.TLS.GetCert), getCert: fmt.Sprintf("%p", c.TLS.GetCert),
serverName: c.TLS.ServerName, serverName: c.TLS.ServerName,
nextProtos: strings.Join(c.TLS.NextProtos, ","),
dial: fmt.Sprintf("%p", c.Dial), dial: fmt.Sprintf("%p", c.Dial),
disableCompression: c.DisableCompression, disableCompression: c.DisableCompression,
}, nil }, nil

View File

@ -126,6 +126,8 @@ func TestTLSConfigKey(t *testing.T) {
GetCert: getCert, GetCert: getCert,
}, },
}, },
"http2, http1.1": {TLS: TLSConfig{NextProtos: []string{"h2", "http/1.1"}}},
"http1.1-only": {TLS: TLSConfig{NextProtos: []string{"http/1.1"}}},
} }
for nameA, valueA := range uniqueConfigurations { for nameA, valueA := range uniqueConfigurations {
for nameB, valueB := range uniqueConfigurations { for nameB, valueB := range uniqueConfigurations {

View File

@ -126,5 +126,11 @@ type TLSConfig struct {
CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile. CertData []byte // Bytes of the PEM-encoded client certificate. Supercedes CertFile.
KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile. KeyData []byte // Bytes of the PEM-encoded client key. Supercedes KeyFile.
// NextProtos is a list of supported application level protocols, in order of preference.
// Used to populate tls.Config.NextProtos.
// To indicate to the server http/1.1 is preferred over http/2, set to ["http/1.1", "h2"] (though the server is free to ignore that preference).
// To use only http/1.1, set to ["http/1.1"].
NextProtos []string
GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field.
} }

View File

@ -56,7 +56,7 @@ func New(config *Config) (http.RoundTripper, error) {
// TLSConfigFor returns a tls.Config that will provide the transport level security defined // TLSConfigFor returns a tls.Config that will provide the transport level security defined
// by the provided Config. Will return nil if no transport level security is requested. // by the provided Config. Will return nil if no transport level security is requested.
func TLSConfigFor(c *Config) (*tls.Config, error) { func TLSConfigFor(c *Config) (*tls.Config, error) {
if !(c.HasCA() || c.HasCertAuth() || c.HasCertCallback() || c.TLS.Insecure || len(c.TLS.ServerName) > 0) { if !(c.HasCA() || c.HasCertAuth() || c.HasCertCallback() || c.TLS.Insecure || len(c.TLS.ServerName) > 0 || len(c.TLS.NextProtos) > 0) {
return nil, nil return nil, nil
} }
if c.HasCA() && c.TLS.Insecure { if c.HasCA() && c.TLS.Insecure {
@ -73,6 +73,7 @@ func TLSConfigFor(c *Config) (*tls.Config, error) {
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
InsecureSkipVerify: c.TLS.Insecure, InsecureSkipVerify: c.TLS.Insecure,
ServerName: c.TLS.ServerName, ServerName: c.TLS.ServerName,
NextProtos: c.TLS.NextProtos,
} }
if c.HasCA() { if c.HasCA() {