From 9bd012be7a5d90b12aa57c29a145dfa6146f22ee Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Fri, 13 Jul 2018 10:16:55 +0200 Subject: [PATCH] UPSTREAM: 65899: use self-signed cert fixtures in integration test servers --- .../cmd/kube-apiserver/app/testing/BUILD | 1 + ...ubernetes.default-kubernetes-localhost.crt | 38 ++++++++++++ ...ubernetes.default-kubernetes-localhost.key | 27 +++++++++ .../kube-apiserver/app/testing/testserver.go | 17 ++++-- .../apiserver/pkg/server/options/serving.go | 13 +++- .../src/k8s.io/client-go/util/cert/cert.go | 60 +++++++++++++++++-- 6 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.crt create mode 100644 vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.key diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/BUILD b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/BUILD index 81763ecbaaf7..295dcf331745 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/BUILD +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/BUILD @@ -8,6 +8,7 @@ load( go_library( name = "go_default_library", srcs = ["testserver.go"], + data = glob(["testdata/**"]), importpath = "k8s.io/kubernetes/cmd/kube-apiserver/app/testing", deps = [ "//cmd/kube-apiserver/app:go_default_library", diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.crt b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.crt new file mode 100644 index 000000000000..d144d04f5e56 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.crt @@ -0,0 +1,38 @@ +-----BEGIN CERTIFICATE----- +MIIDTzCCAjegAwIBAgIBAjANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBcxMjcu +MC4wLjEtY2FAMTUzMTQ2NzU5MzAgFw0xODA3MTMwNjM5NTNaGA8yMTE4MDYxOTA2 +Mzk1M1owHzEdMBsGA1UEAwwUMTI3LjAuMC4xQDE1MzE0Njc1OTMwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdTNF7rRKBvDtLOvCTDgj3utt+zv5u+23x +kCz2475DPnTZ7JK2ipCuHemyCY88M6VyaBkIqAVvvl3LZiS+Hu3gd+8elbdGrCxQ +sui1MrUcAg8OoBM+97UzoKC3HMFIFEpqzKjVJKr5PbV3F8XXIBQeS3YUCePo3m7u +OkGCXUXtWRtQTu4Dcq+tJKlJBsY+Q8CUvb1l0n5hafIFEMnFF/sKGP28CWd8gfzD +ZKKtVumvQlgcp1GdfxqKHfjQOtBo+ZBFiHgDGDrrghuQ2CxROvk5/bNrViqbWbw4 +lUbU3Yn18L4UHR5xOOvQyLP2QdWAaoPutT7Xba40RMgWYlsNRaatAgMBAAGjgZAw +gY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB +/wQCMAAwWAYDVR0RBFEwT4IWa3ViZXJuZXRlcy5kZWZhdWx0LnN2Y4ISa3ViZXJu +ZXRlcy5kZWZhdWx0ggprdWJlcm5ldGVzgglsb2NhbGhvc3SHBH8AAAGHBAoAAAEw +DQYJKoZIhvcNAQELBQADggEBAFkRV1oBLrY3IJDI6E9nxAK30EdyfYZqvybPCZB8 +6AAErj+WleJVFi0rZJ3fRDoQ5Gelwe4Ud21DknW4+L7nZ8JRbzNkLTYTJxtkujSW +aEz7xKW1IxD+o9TEceqiVko4xGawXjUVTun7n0Upv6T4D4jC0GN9zu8oT6xbUHmd +WSSc2HjGLs8vF130xt2Oj0jx03i7AoJF4ZxMRt7dqSK7j5tfflfTS9Dxhmd9Gg5P +eGH4BWJ3IJI3r0+WUtiIgMSgV2ppTSNY2UNbNNpudsRCq55IzyHuRioFt/FH9t+8 +xFaar6D9RDsm87JCv5JZ3BoVZJglmX8iqye+OBXgHgMZxx4= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5DCCAcygAwIBAgIBATANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBcxMjcu +MC4wLjEtY2FAMTUzMTQ2NzU5MzAgFw0xODA3MTMwNjM5NTNaGA8yMTE4MDYxOTA2 +Mzk1M1owIjEgMB4GA1UEAwwXMTI3LjAuMC4xLWNhQDE1MzE0Njc1OTMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRfS+rc4EPpDafeiRo+uIvV1812UQM +ddoaCrn2yIVSYiupsFc7goieXOpqxgI6ksUCMDUOfi3DQGC8067wX2HpMzz5J9yz +Qfamcg3SL7G9u5Vx+x+EU6qmBhXa4Z46JwTY0vYeccz2PR+Nx+HHO0DglIh3tip8 +ECQ2rtpMc5YxJOCwJg3zh8pnEqLNEahm3p1lNGLbY7Kpqp7al68ZVReVg/YaoJt5 +Voi7vbR38OWBChbBmwKRP4gJD8aKY2eY6Xgn8+UAAytYGOEp18y/eAvba7awKp56 +wG1Y3JqWD06D8NnUCPQOO/g/KyGU77sM66xdlsOwLpSbtwWLcjC3nnvHAgMBAAGj +IzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQCECJvqzrh57MrVT5sj+TDmhtSwkblBBqNG03X8gvmj7PsYAnZVpaev +KbN0xfDhK6yaCJX41sZCoTaQa55a0Y9n/Lr6d2LREYPf2NdhHU2aj1UjNhhamoZk +0/MJtn/7t6UmYsdFIRlYtLJZQRfNaeO+ULpjjQeGj+Y4mR87VzyDZk2zi/fLJCtk +aVKsI2Tan9KFzwmsCp/9RH7uPhOIFsaa8ePBCvzrahMrG+b9FGV670bQTS104Gyt +HB73ixOheUPL9PuvahXKz0xlJfeKu4nFFJkqUmThj2Ybv8cyzDNrSyDywZxzNe3e +nMA3i/kfmIj33gkmwcFgYPqfKleeVZQo +-----END CERTIFICATE----- diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.key b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.key new file mode 100644 index 000000000000..ec43d5e87666 --- /dev/null +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testdata/127.0.0.1_10.0.0.1_kubernetes.default.svc-kubernetes.default-kubernetes-localhost.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA3UzRe60Sgbw7Szrwkw4I97rbfs7+bvtt8ZAs9uO+Qz502eyS +toqQrh3psgmPPDOlcmgZCKgFb75dy2Ykvh7t4HfvHpW3RqwsULLotTK1HAIPDqAT +Pve1M6CgtxzBSBRKasyo1SSq+T21dxfF1yAUHkt2FAnj6N5u7jpBgl1F7VkbUE7u +A3KvrSSpSQbGPkPAlL29ZdJ+YWnyBRDJxRf7Chj9vAlnfIH8w2SirVbpr0JYHKdR +nX8aih340DrQaPmQRYh4Axg664IbkNgsUTr5Of2za1Yqm1m8OJVG1N2J9fC+FB0e +cTjr0Miz9kHVgGqD7rU+122uNETIFmJbDUWmrQIDAQABAoIBAFXzdhFhASUeZLEt +bS7Qbq85BfNUlgGo6eS+qJgjkEwxv9S8S6dWXiciOxgJGna5YHL093QjPilOeMN9 +IpwtCxr5ugfZAlwSlwuo0TU/QpRkQFDf31m/f8NTidhU9MT4DIc6ggB2w2kWjJp6 +wz5wmR/DE1NpG/ngGpmwSq1FaNlr3xz4e6b0A56ReqQr5YwYsZl2Fxf8sOBWTiPe +Iv41q8jyRXL2ytv9uTgdD7i+qLMz1/NGvy4ZWxD3yCMsDm5eEI8/4l2pOmRrrpKY +Fc14eUkbHBMyT6ibI4d7Y2aZJslq8d0HMMX1XNLvzLEnGT1+mrOjWwerI+60B0t1 +6EvTfUkCgYEA/rVROq6JupfnT7BM04jEx5UuaokcLoNpn6bptZwmMakioLjgZoa2 +XEZrNoRWVMQ82JuguxkLtUgLgqKQRreolDCyQtaGFjFnWdVs+1W0oIHY7oMdwOLh +XsQRtPW3HCK4HYZJcBBIh8t4USiBTrRtTpXmDinLkbCRXYOcehbRZ2cCgYEA3mwg +tsbnSDYTcFmPjJEGjISfMEjAHoka8ubPKzU6VylDnrb2k/NbDYL3NidzGbJaVJFk +YNfCsja4COz+0pBiMY2fBEzHU4RwDaRrxUr0fLVxvH7/E9JPP8y/e5CJR2Z2sDQa +yed3ArkNh0MaecGr+7IZFbv+Uj4QaBq3W77hGMsCgYB/keC1O2XQBvTbfLl92Sp1 +q8orobBzu23TgI3dX+/hP40QYohB0YbUgJCCJZX3rrGq64d9LfYnPYZGT5VjVekh +D6K4xykxRF03KSYEW9Cz81TrYNAuI3QtOpaDw+2KMfl1ECUH85/gI5CHVXouKT/1 +9C3dOiGzPnQQGjLtEzCeUQKBgFacZGDIM2e7Jvao6W0jTBmLyzFSIv3BBe1wU1vP +7lfiiaJUPNCAAwTP6tP7qKZo/SPROfU8D2S2ShOvtcrozlPdgf56p2OuPrQRQqYg ++fNV9GQiT9G4I4QEhsvnDI3xKGaU45mbuIwm4024o6al9AKe54W/HtmHsXvYa24e +dijhAoGARcbgcE/aT8jhdVHHCRBuSD4ZzXbB+JCetHsrjhOYnifc0graq0umiuRI +c0i+IT5OhGTdVbjnPgySHn/V/IuSYLLtKvfqSV8tQk3womXRPJ/K9BsFhelo1Vd5 +MTyZ2j0XjLWHOo0DKxIPLW3P7sBYAFM2Z+/RAe1uKjISmggDhBs= +-----END RSA PRIVATE KEY----- diff --git a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go index d5c1e64298ee..628ccdefd301 100644 --- a/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go +++ b/vendor/k8s.io/kubernetes/cmd/kube-apiserver/app/testing/testserver.go @@ -21,6 +21,8 @@ import ( "io/ioutil" "net" "os" + "path" + "runtime" "time" pflag "github.com/spf13/pflag" @@ -111,11 +113,19 @@ func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, custo s.InsecureServing.BindPort = 0 - s.SecureServing.Listener, s.SecureServing.BindPort, err = createListenerOnFreePort() + s.SecureServing.Listener, s.SecureServing.BindPort, err = createLocalhostListenerOnFreePort() if err != nil { return result, fmt.Errorf("failed to create listener: %v", err) } s.SecureServing.ServerCert.CertDirectory = result.TmpDir + s.SecureServing.ExternalAddress = s.SecureServing.Listener.Addr().(*net.TCPAddr).IP // use listener addr although it is a loopback device + + _, thisFile, _, ok := runtime.Caller(0) + if !ok { + return result, fmt.Errorf("failed to get current file") + } + s.SecureServing.ServerCert.FixtureDirectory = path.Join(path.Dir(thisFile), "testdata") + s.ServiceClusterIPRange.IP = net.IPv4(10, 0, 0, 0) s.ServiceClusterIPRange.Mask = net.CIDRMask(16, 32) s.Etcd.StorageConfig = *storageConfig @@ -132,7 +142,6 @@ func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, custo server, err := app.CreateServerChain(completedOptions, stopCh) if err != nil { return result, fmt.Errorf("failed to create server chain: %v", err) - } go func(stopCh <-chan struct{}) { if err := server.PrepareRun().Run(stopCh); err != nil { @@ -178,8 +187,8 @@ func StartTestServerOrDie(t Logger, instanceOptions *TestServerInstanceOptions, return nil } -func createListenerOnFreePort() (net.Listener, int, error) { - ln, err := net.Listen("tcp", ":0") +func createLocalhostListenerOnFreePort() (net.Listener, int, error) { + ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return nil, 0, err } diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go index 5d21da26179d..7d394f5d5945 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -40,6 +40,9 @@ type SecureServingOptions struct { // BindNetwork is the type of network to bind to - defaults to "tcp", accepts "tcp", // "tcp4", and "tcp6". BindNetwork string + // ExternalAddress is the address advertised, even if BindAddress is a loopback. By default this + // is set to BindAddress if the later no loopback, or to the first host interface address. + ExternalAddress net.IP // Listener is the secure server network listener. // either Listener or BindAddress/BindPort/BindNetwork is set, @@ -75,6 +78,11 @@ type GeneratableKeyCert struct { // CertDirectory is a directory that will contain the certificates. If the cert and key aren't specifically set // this will be used to derive a match with the "pair-name" CertDirectory string + // FixtureDirectory is a directory that contains test fixture used to avoid regeneration of certs during tests. + // The format is: + // _-_-.crt + // _-_-.key + FixtureDirectory string // PairName is the name which will be used with CertDirectory to make a cert and key names // It becomes CertDirector/PairName.crt and CertDirector/PairName.key PairName string @@ -92,6 +100,9 @@ func NewSecureServingOptions() *SecureServingOptions { } func (s *SecureServingOptions) DefaultExternalAddress() (net.IP, error) { + if !s.ExternalAddress.IsUnspecified() { + return s.ExternalAddress, nil + } return utilnet.ChooseBindAddress(s.BindAddress) } @@ -260,7 +271,7 @@ func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress str alternateIPs = append(alternateIPs, s.BindAddress) } - if cert, key, err := certutil.GenerateSelfSignedCertKey(publicAddress, alternateIPs, alternateDNS); err != nil { + if cert, key, err := certutil.GenerateSelfSignedCertKeyWithFixtures(publicAddress, alternateIPs, alternateDNS, s.ServerCert.FixtureDirectory); err != nil { return fmt.Errorf("unable to generate self signed cert: %v", err) } else { if err := certutil.WriteCert(keyCert.CertFile, cert); err != nil { diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go index fb7f5facc7ce..0d6794bb5dec 100644 --- a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go @@ -27,9 +27,12 @@ import ( "encoding/pem" "errors" "fmt" + "io/ioutil" "math" "math/big" "net" + "path" + "strings" "time" ) @@ -136,8 +139,38 @@ func MakeEllipticPrivateKeyPEM() ([]byte, error) { // GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host. // Host may be an IP or a DNS name -// You may also specify additional subject alt names (either ip or dns names) for the certificate +// You may also specify additional subject alt names (either ip or dns names) for the certificate. func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) { + return GenerateSelfSignedCertKeyWithFixtures(host, alternateIPs, alternateDNS, "") +} + +// GenerateSelfSignedCertKeyWithFixtures creates a self-signed certificate and key for the given host. +// Host may be an IP or a DNS name. You may also specify additional subject alt names (either ip or dns names) +// for the certificate. +// +// If fixtureDirectory is non-empty, it is a directory path which can contain pre-generated certs. The format is: +// _-_-.crt +// _-_-.key +// Certs/keys not existing in that directory are created. +func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, alternateDNS []string, fixtureDirectory string) ([]byte, []byte, error) { + validFrom := time.Now().Add(-time.Hour) // valid an hour earlier to avoid flakes due to clock skew + maxAge := time.Hour * 24 * 365 // one year self-signed certs + + baseName := fmt.Sprintf("%s_%s_%s", host, strings.Join(ipsToStrings(alternateIPs), "-"), strings.Join(alternateDNS, "-")) + certFixturePath := path.Join(fixtureDirectory, baseName+".crt") + keyFixturePath := path.Join(fixtureDirectory, baseName+".key") + if len(fixtureDirectory) > 0 { + cert, err := ioutil.ReadFile(certFixturePath) + if err == nil { + key, err := ioutil.ReadFile(keyFixturePath) + if err == nil { + return cert, key, nil + } + return nil, nil, fmt.Errorf("cert %s can be read, but key %s cannot: %v", certFixturePath, keyFixturePath, err) + } + maxAge = 100 * time.Hour * 24 * 365 // 100 years fixtures + } + caKey, err := rsa.GenerateKey(cryptorand.Reader, 2048) if err != nil { return nil, nil, err @@ -148,8 +181,8 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS Subject: pkix.Name{ CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()), }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 365), + NotBefore: validFrom, + NotAfter: validFrom.Add(maxAge), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, @@ -176,8 +209,8 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS Subject: pkix.Name{ CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()), }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 365), + NotBefore: validFrom, + NotAfter: validFrom.Add(maxAge), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, @@ -213,6 +246,15 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS return nil, nil, err } + if len(fixtureDirectory) > 0 { + if err := ioutil.WriteFile(certFixturePath, certBuffer.Bytes(), 0644); err != nil { + return nil, nil, fmt.Errorf("failed to write cert fixture to %s: %v", certFixturePath, err) + } + if err := ioutil.WriteFile(keyFixturePath, keyBuffer.Bytes(), 0644); err != nil { + return nil, nil, fmt.Errorf("failed to write key fixture to %s: %v", certFixturePath, err) + } + } + return certBuffer.Bytes(), keyBuffer.Bytes(), nil } @@ -243,3 +285,11 @@ func FormatCert(c *x509.Certificate) string { } return res } + +func ipsToStrings(ips []net.IP) []string { + ss := make([]string, 0, len(ips)) + for _, ip := range ips { + ss = append(ss, ip.String()) + } + return ss +}