From 18458392ca24c85c688e655aace1afd04f864cbd Mon Sep 17 00:00:00 2001 From: Andrew Lytvynov Date: Sun, 9 Dec 2018 16:24:38 -0800 Subject: [PATCH] Extract new keyutil package from client-go/util/cert This package contains public/private key utilities copied directly from client-go/util/cert. All imports were updated. Future PRs will actually refactor the libraries. Updates #71004 --- cmd/kube-apiserver/app/BUILD | 2 +- cmd/kube-apiserver/app/server.go | 4 +- cmd/kube-controller-manager/app/BUILD | 1 + .../app/controllermanager.go | 3 +- cmd/kubeadm/app/phases/kubeconfig/BUILD | 1 + .../app/phases/kubeconfig/kubeconfig.go | 7 +- cmd/kubeadm/app/util/certs/BUILD | 1 + cmd/kubeadm/app/util/certs/util.go | 9 +- cmd/kubeadm/app/util/pkiutil/BUILD | 1 + cmd/kubeadm/app/util/pkiutil/pki_helpers.go | 15 +- cmd/kubelet/app/BUILD | 1 + cmd/kubelet/app/server.go | 3 +- pkg/kubeapiserver/authenticator/BUILD | 1 + pkg/kubeapiserver/authenticator/config.go | 8 +- pkg/kubelet/certificate/bootstrap/BUILD | 3 +- .../certificate/bootstrap/bootstrap.go | 9 +- .../certificate/bootstrap/bootstrap_test.go | 6 +- pkg/serviceaccount/BUILD | 2 +- pkg/serviceaccount/jwt_test.go | 8 +- staging/src/BUILD | 1 + .../Godeps/Godeps.json | 4 + .../src/k8s.io/apiserver/Godeps/Godeps.json | 8 + .../k8s.io/apiserver/pkg/server/options/BUILD | 1 + .../apiserver/pkg/server/options/serving.go | 3 +- .../src/k8s.io/cli-runtime/Godeps/Godeps.json | 4 + staging/src/k8s.io/client-go/util/cert/BUILD | 7 +- .../src/k8s.io/client-go/util/cert/cert.go | 29 +- .../k8s.io/client-go/util/cert/csr_test.go | 4 +- staging/src/k8s.io/client-go/util/cert/io.go | 95 ------ staging/src/k8s.io/client-go/util/cert/pem.go | 189 +--------- .../k8s.io/client-go/util/certificate/BUILD | 1 + .../util/certificate/certificate_manager.go | 3 +- .../src/k8s.io/client-go/util/keyutil/BUILD | 33 ++ .../src/k8s.io/client-go/util/keyutil/OWNERS | 7 + .../src/k8s.io/client-go/util/keyutil/key.go | 323 ++++++++++++++++++ .../{cert/pem_test.go => keyutil/key_test.go} | 4 +- .../k8s.io/cloud-provider/Godeps/Godeps.json | 4 + staging/src/k8s.io/csi-api/Godeps/Godeps.json | 4 + .../k8s.io/kube-aggregator/Godeps/Godeps.json | 4 + staging/src/k8s.io/metrics/Godeps/Godeps.json | 4 + .../src/k8s.io/node-api/Godeps/Godeps.json | 4 + .../sample-apiserver/Godeps/Godeps.json | 4 + .../sample-cli-plugin/Godeps/Godeps.json | 4 + .../sample-controller/Godeps/Godeps.json | 4 + test/e2e/apimachinery/BUILD | 1 + test/e2e/apimachinery/certs.go | 15 +- test/e2e/auth/certificates.go | 5 +- test/integration/auth/BUILD | 2 +- test/integration/auth/svcaccttoken_test.go | 4 +- test/integration/examples/BUILD | 1 + test/integration/examples/apiserver_test.go | 17 +- test/integration/framework/test_server.go | 9 +- 52 files changed, 521 insertions(+), 366 deletions(-) create mode 100644 staging/src/k8s.io/client-go/util/keyutil/BUILD create mode 100644 staging/src/k8s.io/client-go/util/keyutil/OWNERS create mode 100644 staging/src/k8s.io/client-go/util/keyutil/key.go rename staging/src/k8s.io/client-go/util/{cert/pem_test.go => keyutil/key_test.go} (99%) diff --git a/cmd/kube-apiserver/app/BUILD b/cmd/kube-apiserver/app/BUILD index d210309f9a..a982cd82d7 100644 --- a/cmd/kube-apiserver/app/BUILD +++ b/cmd/kube-apiserver/app/BUILD @@ -61,7 +61,7 @@ go_library( "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 7daab88ceb..3dff4f9070 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -53,7 +53,7 @@ import ( "k8s.io/apiserver/pkg/util/webhook" clientgoinformers "k8s.io/client-go/informers" clientgoclientset "k8s.io/client-go/kubernetes" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" cloudprovider "k8s.io/cloud-provider" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/cli/globalflag" @@ -580,7 +580,7 @@ func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) { } if s.ServiceAccountSigningKeyFile != "" && s.Authentication.ServiceAccounts.Issuer != "" { - sk, err := certutil.PrivateKeyFromFile(s.ServiceAccountSigningKeyFile) + sk, err := keyutil.PrivateKeyFromFile(s.ServiceAccountSigningKeyFile) if err != nil { return options, fmt.Errorf("failed to parse service-account-issuer-key-file: %v", err) } diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index 749e20dc90..1d9dfafa9d 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -131,6 +131,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index 86a0febe1f..628dc4a23b 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -47,6 +47,7 @@ import ( "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" cloudprovider "k8s.io/cloud-provider" cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/cli/globalflag" @@ -514,7 +515,7 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController klog.Warningf("%q is disabled because there is no private key", saTokenControllerName) return nil, false, nil } - privateKey, err := certutil.PrivateKeyFromFile(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) + privateKey, err := keyutil.PrivateKeyFromFile(ctx.ComponentConfig.SAController.ServiceAccountKeyFile) if err != nil { return nil, true, fmt.Errorf("error reading key for service account token controller: %v", err) } diff --git a/cmd/kubeadm/app/phases/kubeconfig/BUILD b/cmd/kubeadm/app/phases/kubeconfig/BUILD index 47cdcdd7ba..b620253e16 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/BUILD +++ b/cmd/kubeadm/app/phases/kubeconfig/BUILD @@ -22,6 +22,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go index 63ebe94fd2..c8abf03110 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go @@ -29,6 +29,7 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" "k8s.io/klog" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -206,13 +207,17 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientc return nil, errors.Wrapf(err, "failure while creating %s client certificate", spec.ClientName) } + encodedClientKey, err := keyutil.MarshalPrivateKeyToPEM(clientKey) + if err != nil { + return nil, errors.Wrapf(err, "failed to marshal private key to PEM") + } // create a kubeconfig with the client certs return kubeconfigutil.CreateWithCerts( spec.APIServer, clustername, spec.ClientName, pkiutil.EncodeCertPEM(spec.CACert), - certutil.EncodePrivateKeyPEM(clientKey), + encodedClientKey, pkiutil.EncodeCertPEM(clientCert), ), nil } diff --git a/cmd/kubeadm/app/util/certs/BUILD b/cmd/kubeadm/app/util/certs/BUILD index d3007e29a7..d3a08ea29a 100644 --- a/cmd/kubeadm/app/util/certs/BUILD +++ b/cmd/kubeadm/app/util/certs/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/certs/util.go b/cmd/kubeadm/app/util/certs/util.go index e0831c5c8a..bf0d0210b7 100644 --- a/cmd/kubeadm/app/util/certs/util.go +++ b/cmd/kubeadm/app/util/certs/util.go @@ -24,6 +24,7 @@ import ( "testing" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" ) @@ -238,11 +239,15 @@ func WritePKIFiles(t *testing.T, dir string, files PKIFiles) { if err != nil { t.Errorf("unable to write public key to file %q: [%v]", filename, err) } - if err := certutil.WriteKey(path.Join(dir, filename), publicKeyBytes); err != nil { + if err := keyutil.WriteKey(path.Join(dir, filename), publicKeyBytes); err != nil { t.Errorf("unable to write public key to file %q: [%v]", filename, err) } case *rsa.PrivateKey: - if err := certutil.WriteKey(path.Join(dir, filename), certutil.EncodePrivateKeyPEM(body)); err != nil { + privateKey, err := keyutil.MarshalPrivateKeyToPEM(body) + if err != nil { + t.Errorf("unable to write private key to file %q: [%v]", filename, err) + } + if err := keyutil.WriteKey(path.Join(dir, filename), privateKey); err != nil { t.Errorf("unable to write private key to file %q: [%v]", filename, err) } } diff --git a/cmd/kubeadm/app/util/pkiutil/BUILD b/cmd/kubeadm/app/util/pkiutil/BUILD index 08debfbecf..e4cc53efcf 100644 --- a/cmd/kubeadm/app/util/pkiutil/BUILD +++ b/cmd/kubeadm/app/util/pkiutil/BUILD @@ -27,6 +27,7 @@ go_library( "//pkg/registry/core/service/ipallocator:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/github.com/pkg/errors:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go index f664a636e6..55338e4acc 100644 --- a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go +++ b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" @@ -141,7 +142,11 @@ func WriteKey(pkiPath, name string, key *rsa.PrivateKey) error { } privateKeyPath := pathForKey(pkiPath, name) - if err := certutil.WriteKey(privateKeyPath, certutil.EncodePrivateKeyPEM(key)); err != nil { + encoded, err := keyutil.MarshalPrivateKeyToPEM(key) + if err != nil { + return errors.Wrapf(err, "unable to marshal private key to PEM") + } + if err := keyutil.WriteKey(privateKeyPath, encoded); err != nil { return errors.Wrapf(err, "unable to write private key to file %s", privateKeyPath) } @@ -180,7 +185,7 @@ func WritePublicKey(pkiPath, name string, key *rsa.PublicKey) error { return err } publicKeyPath := pathForPublicKey(pkiPath, name) - if err := certutil.WriteKey(publicKeyPath, publicKeyBytes); err != nil { + if err := keyutil.WriteKey(publicKeyPath, publicKeyBytes); err != nil { return errors.Wrapf(err, "unable to write public key to file %s", publicKeyPath) } @@ -258,7 +263,7 @@ func TryLoadKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, error) { privateKeyPath := pathForKey(pkiPath, name) // Parse the private key from a file - privKey, err := certutil.PrivateKeyFromFile(privateKeyPath) + privKey, err := keyutil.PrivateKeyFromFile(privateKeyPath) if err != nil { return nil, errors.Wrapf(err, "couldn't load the private key file %s", privateKeyPath) } @@ -297,7 +302,7 @@ func TryLoadPrivatePublicKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, *rs privateKeyPath := pathForKey(pkiPath, name) // Parse the private key from a file - privKey, err := certutil.PrivateKeyFromFile(privateKeyPath) + privKey, err := keyutil.PrivateKeyFromFile(privateKeyPath) if err != nil { return nil, nil, errors.Wrapf(err, "couldn't load the private key file %s", privateKeyPath) } @@ -305,7 +310,7 @@ func TryLoadPrivatePublicKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, *rs publicKeyPath := pathForPublicKey(pkiPath, name) // Parse the public key from a file - pubKeys, err := certutil.PublicKeysFromFile(publicKeyPath) + pubKeys, err := keyutil.PublicKeysFromFile(publicKeyPath) if err != nil { return nil, nil, errors.Wrapf(err, "couldn't load the public key file %s", publicKeyPath) } diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index 43211aeb28..8b90ed13e3 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -132,6 +132,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/certificate:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library", diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 1118076723..5b80efe5bf 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -54,6 +54,7 @@ import ( "k8s.io/client-go/tools/record" certutil "k8s.io/client-go/util/cert" "k8s.io/client-go/util/certificate" + "k8s.io/client-go/util/keyutil" cloudprovider "k8s.io/cloud-provider" cliflag "k8s.io/component-base/cli/flag" csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned" @@ -899,7 +900,7 @@ func InitializeTLS(kf *options.KubeletFlags, kc *kubeletconfiginternal.KubeletCo return nil, err } - if err := certutil.WriteKey(kc.TLSPrivateKeyFile, key); err != nil { + if err := keyutil.WriteKey(kc.TLSPrivateKeyFile, key); err != nil { return nil, err } diff --git a/pkg/kubeapiserver/authenticator/BUILD b/pkg/kubeapiserver/authenticator/BUILD index 399657c211..d9140ba9c0 100644 --- a/pkg/kubeapiserver/authenticator/BUILD +++ b/pkg/kubeapiserver/authenticator/BUILD @@ -31,6 +31,7 @@ go_library( "//staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook:go_default_library", "//staging/src/k8s.io/client-go/plugin/pkg/client/auth:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library", ], ) diff --git a/pkg/kubeapiserver/authenticator/config.go b/pkg/kubeapiserver/authenticator/config.go index b34e6b8958..03e05d7974 100644 --- a/pkg/kubeapiserver/authenticator/config.go +++ b/pkg/kubeapiserver/authenticator/config.go @@ -38,9 +38,11 @@ import ( "k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth" "k8s.io/apiserver/plugin/pkg/authenticator/token/oidc" "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook" + // Initialize all known client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/serviceaccount" ) @@ -226,7 +228,7 @@ func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, er // IsValidServiceAccountKeyFile returns true if a valid public RSA key can be read from the given file func IsValidServiceAccountKeyFile(file string) bool { - _, err := certutil.PublicKeysFromFile(file) + _, err := keyutil.PublicKeysFromFile(file) return err == nil } @@ -279,7 +281,7 @@ func newAuthenticatorFromOIDCIssuerURL(opts oidc.Options) (authenticator.Token, func newLegacyServiceAccountAuthenticator(keyfiles []string, lookup bool, apiAudiences authenticator.Audiences, serviceAccountGetter serviceaccount.ServiceAccountTokenGetter) (authenticator.Token, error) { allPublicKeys := []interface{}{} for _, keyfile := range keyfiles { - publicKeys, err := certutil.PublicKeysFromFile(keyfile) + publicKeys, err := keyutil.PublicKeysFromFile(keyfile) if err != nil { return nil, err } @@ -294,7 +296,7 @@ func newLegacyServiceAccountAuthenticator(keyfiles []string, lookup bool, apiAud func newServiceAccountAuthenticator(iss string, keyfiles []string, apiAudiences authenticator.Audiences, serviceAccountGetter serviceaccount.ServiceAccountTokenGetter) (authenticator.Token, error) { allPublicKeys := []interface{}{} for _, keyfile := range keyfiles { - publicKeys, err := certutil.PublicKeysFromFile(keyfile) + publicKeys, err := keyutil.PublicKeysFromFile(keyfile) if err != nil { return nil, err } diff --git a/pkg/kubelet/certificate/bootstrap/BUILD b/pkg/kubelet/certificate/bootstrap/BUILD index 257ec672e1..229696a2c3 100644 --- a/pkg/kubelet/certificate/bootstrap/BUILD +++ b/pkg/kubelet/certificate/bootstrap/BUILD @@ -17,7 +17,7 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", - "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", ], ) @@ -40,6 +40,7 @@ go_library( "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/certificate:go_default_library", "//staging/src/k8s.io/client-go/util/certificate/csr:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/kubelet/certificate/bootstrap/bootstrap.go b/pkg/kubelet/certificate/bootstrap/bootstrap.go index 46491a45cb..0453165e1e 100644 --- a/pkg/kubelet/certificate/bootstrap/bootstrap.go +++ b/pkg/kubelet/certificate/bootstrap/bootstrap.go @@ -43,6 +43,7 @@ import ( certutil "k8s.io/client-go/util/cert" "k8s.io/client-go/util/certificate" "k8s.io/client-go/util/certificate/csr" + "k8s.io/client-go/util/keyutil" ) const tmpPrivateKeyFile = "kubelet-client.key.tmp" @@ -134,7 +135,7 @@ func LoadClientCert(kubeconfigPath, bootstrapPath, certDir string, nodeName type var keyData []byte if cert, err := store.Current(); err == nil { if cert.PrivateKey != nil { - keyData, err = certutil.MarshalPrivateKeyToPEM(cert.PrivateKey) + keyData, err = keyutil.MarshalPrivateKeyToPEM(cert.PrivateKey) if err != nil { keyData = nil } @@ -148,7 +149,7 @@ func LoadClientCert(kubeconfigPath, bootstrapPath, certDir string, nodeName type klog.V(2).Infof("No valid private key and/or certificate found, reusing existing private key or creating a new one") // Note: always call LoadOrGenerateKeyFile so that private key is // reused on next startup if CSR request fails. - keyData, _, err = certutil.LoadOrGenerateKeyFile(privKeyPath) + keyData, _, err = keyutil.LoadOrGenerateKeyFile(privKeyPath) if err != nil { return err } @@ -272,7 +273,7 @@ func verifyKeyData(data []byte) bool { if len(data) == 0 { return false } - _, err := certutil.ParsePrivateKeyPEM(data) + _, err := keyutil.ParsePrivateKeyPEM(data) return err == nil } @@ -316,7 +317,7 @@ func requestNodeCertificate(client certificatesv1beta1.CertificateSigningRequest CommonName: "system:node:" + string(nodeName), } - privateKey, err := certutil.ParsePrivateKeyPEM(privateKeyData) + privateKey, err := keyutil.ParsePrivateKeyPEM(privateKeyData) if err != nil { return nil, fmt.Errorf("invalid private key for certificate request: %v", err) } diff --git a/pkg/kubelet/certificate/bootstrap/bootstrap_test.go b/pkg/kubelet/certificate/bootstrap/bootstrap_test.go index 54c1646fc5..a3d47194c7 100644 --- a/pkg/kubelet/certificate/bootstrap/bootstrap_test.go +++ b/pkg/kubelet/certificate/bootstrap/bootstrap_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/apimachinery/pkg/watch" certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" restclient "k8s.io/client-go/rest" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" ) func TestLoadRESTClientConfig(t *testing.T) { @@ -104,7 +104,7 @@ func TestRequestNodeCertificateErrorCreatingCSR(t *testing.T) { client := &fakeClient{ failureType: createError, } - privateKeyData, err := certutil.MakeEllipticPrivateKeyPEM() + privateKeyData, err := keyutil.MakeEllipticPrivateKeyPEM() if err != nil { t.Fatalf("Unable to generate a new private key: %v", err) } @@ -119,7 +119,7 @@ func TestRequestNodeCertificateErrorCreatingCSR(t *testing.T) { } func TestRequestNodeCertificate(t *testing.T) { - privateKeyData, err := certutil.MakeEllipticPrivateKeyPEM() + privateKeyData, err := keyutil.MakeEllipticPrivateKeyPEM() if err != nil { t.Fatalf("Unable to generate a new private key: %v", err) } diff --git a/pkg/serviceaccount/BUILD b/pkg/serviceaccount/BUILD index 5639e80f19..8bd9e62960 100644 --- a/pkg/serviceaccount/BUILD +++ b/pkg/serviceaccount/BUILD @@ -59,7 +59,7 @@ go_test( "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", - "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/gopkg.in/square/go-jose.v2/jwt:go_default_library", ], ) diff --git a/pkg/serviceaccount/jwt_test.go b/pkg/serviceaccount/jwt_test.go index 6a74099ce2..a4fe25bc82 100644 --- a/pkg/serviceaccount/jwt_test.go +++ b/pkg/serviceaccount/jwt_test.go @@ -22,14 +22,14 @@ import ( "strings" "testing" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/authentication/authenticator" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" v1listers "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/serviceaccount" ) @@ -98,12 +98,12 @@ X2i8uIp/C/ASqiIGUeeKQtX0/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg== -----END PUBLIC KEY-----` func getPrivateKey(data string) interface{} { - key, _ := certutil.ParsePrivateKeyPEM([]byte(data)) + key, _ := keyutil.ParsePrivateKeyPEM([]byte(data)) return key } func getPublicKey(data string) interface{} { - keys, _ := certutil.ParsePublicKeysPEM([]byte(data)) + keys, _ := keyutil.ParsePublicKeysPEM([]byte(data)) return keys[0] } func TestTokenGenerateAndValidate(t *testing.T) { diff --git a/staging/src/BUILD b/staging/src/BUILD index 834cda541f..aa62767f80 100644 --- a/staging/src/BUILD +++ b/staging/src/BUILD @@ -181,6 +181,7 @@ filegroup( "//staging/src/k8s.io/client-go/util/flowcontrol:all-srcs", "//staging/src/k8s.io/client-go/util/homedir:all-srcs", "//staging/src/k8s.io/client-go/util/jsonpath:all-srcs", + "//staging/src/k8s.io/client-go/util/keyutil:all-srcs", "//staging/src/k8s.io/client-go/util/retry:all-srcs", "//staging/src/k8s.io/client-go/util/testing:all-srcs", "//staging/src/k8s.io/client-go/util/workqueue:all-srcs", diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index b47316ffb1..406f78856d 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -2206,6 +2206,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index 3465082ec2..950cbb50f3 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -1922,6 +1922,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -2042,6 +2046,10 @@ "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/component-base/cli/flag", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD index 98cb4b2934..6791981be1 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD @@ -75,6 +75,7 @@ go_library( "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//vendor/github.com/pborman/uuid:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", 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 605bf1a6d2..9a3841012c 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -30,6 +30,7 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/server" certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" cliflag "k8s.io/component-base/cli/flag" ) @@ -305,7 +306,7 @@ func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress str if err := certutil.WriteCert(keyCert.CertFile, cert); err != nil { return err } - if err := certutil.WriteKey(keyCert.KeyFile, key); err != nil { + if err := keyutil.WriteKey(keyCert.KeyFile, key); err != nil { return err } klog.Infof("Generated self-signed cert (%s, %s)", keyCert.CertFile, keyCert.KeyFile) diff --git a/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json b/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json index 273be20f3e..468be68bd8 100644 --- a/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json +++ b/staging/src/k8s.io/cli-runtime/Godeps/Godeps.json @@ -638,6 +638,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/klog", "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" diff --git a/staging/src/k8s.io/client-go/util/cert/BUILD b/staging/src/k8s.io/client-go/util/cert/BUILD index 2a42b716ef..661c5e3510 100644 --- a/staging/src/k8s.io/client-go/util/cert/BUILD +++ b/staging/src/k8s.io/client-go/util/cert/BUILD @@ -8,12 +8,10 @@ load( go_test( name = "go_default_test", - srcs = [ - "csr_test.go", - "pem_test.go", - ], + srcs = ["csr_test.go"], data = glob(["testdata/**"]), embed = [":go_default_library"], + deps = ["//staging/src/k8s.io/client-go/util/keyutil:go_default_library"], ) go_library( @@ -26,6 +24,7 @@ go_library( ], importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/util/cert", importpath = "k8s.io/client-go/util/cert", + deps = ["//staging/src/k8s.io/client-go/util/keyutil:go_default_library"], ) filegroup( diff --git a/staging/src/k8s.io/client-go/util/cert/cert.go b/staging/src/k8s.io/client-go/util/cert/cert.go index 7652fcc3e6..9fd097af5e 100644 --- a/staging/src/k8s.io/client-go/util/cert/cert.go +++ b/staging/src/k8s.io/client-go/util/cert/cert.go @@ -19,8 +19,6 @@ package cert import ( "bytes" "crypto" - "crypto/ecdsa" - "crypto/elliptic" cryptorand "crypto/rand" "crypto/rsa" "crypto/x509" @@ -33,11 +31,11 @@ import ( "path" "strings" "time" + + "k8s.io/client-go/util/keyutil" ) -const ( - duration365d = time.Hour * 24 * 365 -) +const duration365d = time.Hour * 24 * 365 // Config contains the basic fields required for creating a certificate type Config struct { @@ -78,25 +76,6 @@ func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, erro return x509.ParseCertificate(certDERBytes) } -// MakeEllipticPrivateKeyPEM creates an ECDSA private key -func MakeEllipticPrivateKeyPEM() ([]byte, error) { - privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader) - if err != nil { - return nil, err - } - - derBytes, err := x509.MarshalECPrivateKey(privateKey) - if err != nil { - return nil, err - } - - privateKeyPemBlock := &pem.Block{ - Type: ECPrivateKeyBlockType, - Bytes: derBytes, - } - return pem.EncodeToMemory(privateKeyPemBlock), nil -} - // 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. @@ -202,7 +181,7 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a // Generate key keyBuffer := bytes.Buffer{} - if err := pem.Encode(&keyBuffer, &pem.Block{Type: RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { + if err := pem.Encode(&keyBuffer, &pem.Block{Type: keyutil.RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { return nil, nil, err } diff --git a/staging/src/k8s.io/client-go/util/cert/csr_test.go b/staging/src/k8s.io/client-go/util/cert/csr_test.go index ed28f021ea..0e80aad2a1 100644 --- a/staging/src/k8s.io/client-go/util/cert/csr_test.go +++ b/staging/src/k8s.io/client-go/util/cert/csr_test.go @@ -23,6 +23,8 @@ import ( "io/ioutil" "net" "testing" + + "k8s.io/client-go/util/keyutil" ) func TestMakeCSR(t *testing.T) { @@ -37,7 +39,7 @@ func TestMakeCSR(t *testing.T) { if err != nil { t.Fatal(err) } - key, err := ParsePrivateKeyPEM(keyData) + key, err := keyutil.ParsePrivateKeyPEM(keyData) if err != nil { t.Fatal(err) } diff --git a/staging/src/k8s.io/client-go/util/cert/io.go b/staging/src/k8s.io/client-go/util/cert/io.go index a57bf09d5e..5efb248948 100644 --- a/staging/src/k8s.io/client-go/util/cert/io.go +++ b/staging/src/k8s.io/client-go/util/cert/io.go @@ -17,11 +17,7 @@ limitations under the License. package cert import ( - "crypto" - "crypto/ecdsa" - "crypto/rsa" "crypto/x509" - "encoding/pem" "fmt" "io/ioutil" "os" @@ -73,60 +69,6 @@ func WriteCert(certPath string, data []byte) error { return ioutil.WriteFile(certPath, data, os.FileMode(0644)) } -// WriteKey writes the pem-encoded key data to keyPath. -// The key file will be created with file mode 0600. -// If the key file already exists, it will be overwritten. -// The parent directory of the keyPath will be created as needed with file mode 0755. -func WriteKey(keyPath string, data []byte) error { - if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil { - return err - } - return ioutil.WriteFile(keyPath, data, os.FileMode(0600)) -} - -// LoadOrGenerateKeyFile looks for a key in the file at the given path. If it -// can't find one, it will generate a new key and store it there. -func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { - loadedData, err := ioutil.ReadFile(keyPath) - // Call verifyKeyData to ensure the file wasn't empty/corrupt. - if err == nil && verifyKeyData(loadedData) { - return loadedData, false, err - } - if !os.IsNotExist(err) { - return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err) - } - - generatedData, err := MakeEllipticPrivateKeyPEM() - if err != nil { - return nil, false, fmt.Errorf("error generating key: %v", err) - } - if err := WriteKey(keyPath, generatedData); err != nil { - return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err) - } - return generatedData, true, nil -} - -// MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to -// a PEM encoded block or returns an error. -func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) { - switch t := privateKey.(type) { - case *ecdsa.PrivateKey: - derBytes, err := x509.MarshalECPrivateKey(t) - if err != nil { - return nil, err - } - privateKeyPemBlock := &pem.Block{ - Type: ECPrivateKeyBlockType, - Bytes: derBytes, - } - return pem.EncodeToMemory(privateKeyPemBlock), nil - case *rsa.PrivateKey: - return EncodePrivateKeyPEM(t), nil - default: - return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey) - } -} - // NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file. // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates func NewPool(filename string) (*x509.CertPool, error) { @@ -154,40 +96,3 @@ func CertsFromFile(file string) ([]*x509.Certificate, error) { } return certs, nil } - -// PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file. -// Returns an error if the file could not be read or if the private key could not be parsed. -func PrivateKeyFromFile(file string) (interface{}, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - key, err := ParsePrivateKeyPEM(data) - if err != nil { - return nil, fmt.Errorf("error reading private key file %s: %v", file, err) - } - return key, nil -} - -// PublicKeysFromFile returns the public keys in rsa.PublicKey or ecdsa.PublicKey format from a given PEM-encoded file. -// Reads public keys from both public and private key files. -func PublicKeysFromFile(file string) ([]interface{}, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - keys, err := ParsePublicKeysPEM(data) - if err != nil { - return nil, fmt.Errorf("error reading public key file %s: %v", file, err) - } - return keys, nil -} - -// verifyKeyData returns true if the provided data appears to be a valid private key. -func verifyKeyData(data []byte) bool { - if len(data) == 0 { - return false - } - _, err := ParsePrivateKeyPEM(data) - return err == nil -} diff --git a/staging/src/k8s.io/client-go/util/cert/pem.go b/staging/src/k8s.io/client-go/util/cert/pem.go index 4c5b7c18e4..9185e2e22d 100644 --- a/staging/src/k8s.io/client-go/util/cert/pem.go +++ b/staging/src/k8s.io/client-go/util/cert/pem.go @@ -17,113 +17,18 @@ limitations under the License. package cert import ( - "crypto/ecdsa" - "crypto/rsa" "crypto/x509" "encoding/pem" "errors" - "fmt" ) const ( - - // ECPrivateKeyBlockType is a possible value for pem.Block.Type. - ECPrivateKeyBlockType = "EC PRIVATE KEY" - // RSAPrivateKeyBlockType is a possible value for pem.Block.Type. - RSAPrivateKeyBlockType = "RSA PRIVATE KEY" - // CertificateRequestBlockType is a possible value for pem.Block.Type. - CertificateRequestBlockType = "CERTIFICATE REQUEST" // CertificateBlockType is a possible value for pem.Block.Type. CertificateBlockType = "CERTIFICATE" - // PrivateKeyBlockType is a possible value for pem.Block.Type. - PrivateKeyBlockType = "PRIVATE KEY" + // CertificateRequestBlockType is a possible value for pem.Block.Type. + CertificateRequestBlockType = "CERTIFICATE REQUEST" ) -// ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data. -// Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY" -func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) { - var privateKeyPemBlock *pem.Block - for { - privateKeyPemBlock, keyData = pem.Decode(keyData) - if privateKeyPemBlock == nil { - break - } - - switch privateKeyPemBlock.Type { - case ECPrivateKeyBlockType: - // ECDSA Private Key in ASN.1 format - if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - case RSAPrivateKeyBlockType: - // RSA Private Key in PKCS#1 format - if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - case PrivateKeyBlockType: - // RSA or ECDSA Private Key in unencrypted PKCS#8 format - if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - } - - // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks - // originally, only the first PEM block was parsed and expected to be a key block - } - - // we read all the PEM blocks and didn't recognize one - return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key") -} - -// ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array. -// Reads public keys from both public and private key files. -func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) { - var block *pem.Block - keys := []interface{}{} - for { - // read the next block - block, keyData = pem.Decode(keyData) - if block == nil { - break - } - - // test block against parsing functions - if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil { - keys = append(keys, &privateKey.PublicKey) - continue - } - if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil { - keys = append(keys, publicKey) - continue - } - if privateKey, err := parseECPrivateKey(block.Bytes); err == nil { - keys = append(keys, &privateKey.PublicKey) - continue - } - if publicKey, err := parseECPublicKey(block.Bytes); err == nil { - keys = append(keys, publicKey) - continue - } - - // tolerate non-key PEM blocks for backwards compatibility - // originally, only the first PEM block was parsed and expected to be a key block - } - - if len(keys) == 0 { - return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys") - } - return keys, nil -} - -// EncodePrivateKeyPEM returns PEM-encoded private key data -func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte { - block := pem.Block{ - Type: RSAPrivateKeyBlockType, - Bytes: x509.MarshalPKCS1PrivateKey(key), - } - return pem.EncodeToMemory(&block) -} - // ParseCertsPEM returns the x509.Certificates contained in the given PEM-encoded byte array // Returns an error if a certificate could not be parsed, or if the data does not contain any certificates func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { @@ -154,93 +59,3 @@ func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { } return certs, nil } - -// parseRSAPublicKey parses a single RSA public key from the provided data -func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { - if cert, err := x509.ParseCertificate(data); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - // Test if parsed key is an RSA Public Key - var pubKey *rsa.PublicKey - var ok bool - if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid RSA Public Key") - } - - return pubKey, nil -} - -// parseRSAPrivateKey parses a single RSA private key from the provided data -func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil { - return nil, err - } - } - - // Test if parsed key is an RSA Private Key - var privKey *rsa.PrivateKey - var ok bool - if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid RSA Private Key") - } - - return privKey, nil -} - -// parseECPublicKey parses a single ECDSA public key from the provided data -func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { - if cert, err := x509.ParseCertificate(data); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - // Test if parsed key is an ECDSA Public Key - var pubKey *ecdsa.PublicKey - var ok bool - if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key") - } - - return pubKey, nil -} - -// parseECPrivateKey parses a single ECDSA private key from the provided data -func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParseECPrivateKey(data); err != nil { - return nil, err - } - - // Test if parsed key is an ECDSA Private Key - var privKey *ecdsa.PrivateKey - var ok bool - if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key") - } - - return privKey, nil -} diff --git a/staging/src/k8s.io/client-go/util/certificate/BUILD b/staging/src/k8s.io/client-go/util/certificate/BUILD index 3d16014c00..44cde57dbe 100644 --- a/staging/src/k8s.io/client-go/util/certificate/BUILD +++ b/staging/src/k8s.io/client-go/util/certificate/BUILD @@ -42,6 +42,7 @@ go_library( "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/certificate/csr:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go b/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go index 2610fac4a8..5aa232a42a 100644 --- a/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go +++ b/staging/src/k8s.io/client-go/util/certificate/certificate_manager.go @@ -38,6 +38,7 @@ import ( certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" "k8s.io/client-go/util/cert" "k8s.io/client-go/util/certificate/csr" + "k8s.io/client-go/util/keyutil" ) // certificateWaitTimeout controls the amount of time we wait for certificate @@ -547,7 +548,7 @@ func (m *manager) generateCSR() (template *x509.CertificateRequest, csrPEM []byt return nil, nil, nil, nil, fmt.Errorf("unable to marshal the new key to DER: %v", err) } - keyPEM = pem.EncodeToMemory(&pem.Block{Type: cert.ECPrivateKeyBlockType, Bytes: der}) + keyPEM = pem.EncodeToMemory(&pem.Block{Type: keyutil.ECPrivateKeyBlockType, Bytes: der}) template = m.getTemplate() if template == nil { diff --git a/staging/src/k8s.io/client-go/util/keyutil/BUILD b/staging/src/k8s.io/client-go/util/keyutil/BUILD new file mode 100644 index 0000000000..52793c68f9 --- /dev/null +++ b/staging/src/k8s.io/client-go/util/keyutil/BUILD @@ -0,0 +1,33 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["key_test.go"], + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["key.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/util/keyutil", + importpath = "k8s.io/client-go/util/keyutil", +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/staging/src/k8s.io/client-go/util/keyutil/OWNERS b/staging/src/k8s.io/client-go/util/keyutil/OWNERS new file mode 100644 index 0000000000..470b7a1c92 --- /dev/null +++ b/staging/src/k8s.io/client-go/util/keyutil/OWNERS @@ -0,0 +1,7 @@ +approvers: +- sig-auth-certificates-approvers +reviewers: +- sig-auth-certificates-reviewers +labels: +- sig/auth + diff --git a/staging/src/k8s.io/client-go/util/keyutil/key.go b/staging/src/k8s.io/client-go/util/keyutil/key.go new file mode 100644 index 0000000000..83c2c6254e --- /dev/null +++ b/staging/src/k8s.io/client-go/util/keyutil/key.go @@ -0,0 +1,323 @@ +/* +Copyright 2018 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 keyutil contains utilities for managing public/private key pairs. +package keyutil + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + cryptorand "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "io/ioutil" + "os" + "path/filepath" +) + +const ( + // ECPrivateKeyBlockType is a possible value for pem.Block.Type. + ECPrivateKeyBlockType = "EC PRIVATE KEY" + // RSAPrivateKeyBlockType is a possible value for pem.Block.Type. + RSAPrivateKeyBlockType = "RSA PRIVATE KEY" + // PrivateKeyBlockType is a possible value for pem.Block.Type. + PrivateKeyBlockType = "PRIVATE KEY" + // PublicKeyBlockType is a possible value for pem.Block.Type. + PublicKeyBlockType = "PUBLIC KEY" +) + +// MakeEllipticPrivateKeyPEM creates an ECDSA private key +func MakeEllipticPrivateKeyPEM() ([]byte, error) { + privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader) + if err != nil { + return nil, err + } + + derBytes, err := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return nil, err + } + + privateKeyPemBlock := &pem.Block{ + Type: ECPrivateKeyBlockType, + Bytes: derBytes, + } + return pem.EncodeToMemory(privateKeyPemBlock), nil +} + +// WriteKey writes the pem-encoded key data to keyPath. +// The key file will be created with file mode 0600. +// If the key file already exists, it will be overwritten. +// The parent directory of the keyPath will be created as needed with file mode 0755. +func WriteKey(keyPath string, data []byte) error { + if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil { + return err + } + return ioutil.WriteFile(keyPath, data, os.FileMode(0600)) +} + +// LoadOrGenerateKeyFile looks for a key in the file at the given path. If it +// can't find one, it will generate a new key and store it there. +func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { + loadedData, err := ioutil.ReadFile(keyPath) + // Call verifyKeyData to ensure the file wasn't empty/corrupt. + if err == nil && verifyKeyData(loadedData) { + return loadedData, false, err + } + if !os.IsNotExist(err) { + return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err) + } + + generatedData, err := MakeEllipticPrivateKeyPEM() + if err != nil { + return nil, false, fmt.Errorf("error generating key: %v", err) + } + if err := WriteKey(keyPath, generatedData); err != nil { + return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err) + } + return generatedData, true, nil +} + +// MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to +// a PEM encoded block or returns an error. +func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) { + switch t := privateKey.(type) { + case *ecdsa.PrivateKey: + derBytes, err := x509.MarshalECPrivateKey(t) + if err != nil { + return nil, err + } + block := &pem.Block{ + Type: ECPrivateKeyBlockType, + Bytes: derBytes, + } + return pem.EncodeToMemory(block), nil + case *rsa.PrivateKey: + block := &pem.Block{ + Type: RSAPrivateKeyBlockType, + Bytes: x509.MarshalPKCS1PrivateKey(t), + } + return pem.EncodeToMemory(block), nil + default: + return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey) + } +} + +// PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file. +// Returns an error if the file could not be read or if the private key could not be parsed. +func PrivateKeyFromFile(file string) (interface{}, error) { + data, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + key, err := ParsePrivateKeyPEM(data) + if err != nil { + return nil, fmt.Errorf("error reading private key file %s: %v", file, err) + } + return key, nil +} + +// PublicKeysFromFile returns the public keys in rsa.PublicKey or ecdsa.PublicKey format from a given PEM-encoded file. +// Reads public keys from both public and private key files. +func PublicKeysFromFile(file string) ([]interface{}, error) { + data, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + keys, err := ParsePublicKeysPEM(data) + if err != nil { + return nil, fmt.Errorf("error reading public key file %s: %v", file, err) + } + return keys, nil +} + +// verifyKeyData returns true if the provided data appears to be a valid private key. +func verifyKeyData(data []byte) bool { + if len(data) == 0 { + return false + } + _, err := ParsePrivateKeyPEM(data) + return err == nil +} + +// ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data. +// Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY" +func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) { + var privateKeyPemBlock *pem.Block + for { + privateKeyPemBlock, keyData = pem.Decode(keyData) + if privateKeyPemBlock == nil { + break + } + + switch privateKeyPemBlock.Type { + case ECPrivateKeyBlockType: + // ECDSA Private Key in ASN.1 format + if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil { + return key, nil + } + case RSAPrivateKeyBlockType: + // RSA Private Key in PKCS#1 format + if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil { + return key, nil + } + case PrivateKeyBlockType: + // RSA or ECDSA Private Key in unencrypted PKCS#8 format + if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil { + return key, nil + } + } + + // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks + // originally, only the first PEM block was parsed and expected to be a key block + } + + // we read all the PEM blocks and didn't recognize one + return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key") +} + +// ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array. +// Reads public keys from both public and private key files. +func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) { + var block *pem.Block + keys := []interface{}{} + for { + // read the next block + block, keyData = pem.Decode(keyData) + if block == nil { + break + } + + // test block against parsing functions + if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil { + keys = append(keys, &privateKey.PublicKey) + continue + } + if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil { + keys = append(keys, publicKey) + continue + } + if privateKey, err := parseECPrivateKey(block.Bytes); err == nil { + keys = append(keys, &privateKey.PublicKey) + continue + } + if publicKey, err := parseECPublicKey(block.Bytes); err == nil { + keys = append(keys, publicKey) + continue + } + + // tolerate non-key PEM blocks for backwards compatibility + // originally, only the first PEM block was parsed and expected to be a key block + } + + if len(keys) == 0 { + return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys") + } + return keys, nil +} + +// parseRSAPublicKey parses a single RSA public key from the provided data +func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) { + var err error + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { + if cert, err := x509.ParseCertificate(data); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + // Test if parsed key is an RSA Public Key + var pubKey *rsa.PublicKey + var ok bool + if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok { + return nil, fmt.Errorf("data doesn't contain valid RSA Public Key") + } + + return pubKey, nil +} + +// parseRSAPrivateKey parses a single RSA private key from the provided data +func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) { + var err error + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil { + return nil, err + } + } + + // Test if parsed key is an RSA Private Key + var privKey *rsa.PrivateKey + var ok bool + if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok { + return nil, fmt.Errorf("data doesn't contain valid RSA Private Key") + } + + return privKey, nil +} + +// parseECPublicKey parses a single ECDSA public key from the provided data +func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) { + var err error + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { + if cert, err := x509.ParseCertificate(data); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + // Test if parsed key is an ECDSA Public Key + var pubKey *ecdsa.PublicKey + var ok bool + if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok { + return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key") + } + + return pubKey, nil +} + +// parseECPrivateKey parses a single ECDSA private key from the provided data +func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) { + var err error + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParseECPrivateKey(data); err != nil { + return nil, err + } + + // Test if parsed key is an ECDSA Private Key + var privKey *ecdsa.PrivateKey + var ok bool + if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { + return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key") + } + + return privKey, nil +} diff --git a/staging/src/k8s.io/client-go/util/cert/pem_test.go b/staging/src/k8s.io/client-go/util/keyutil/key_test.go similarity index 99% rename from staging/src/k8s.io/client-go/util/cert/pem_test.go rename to staging/src/k8s.io/client-go/util/keyutil/key_test.go index de3ce52537..f3974de044 100644 --- a/staging/src/k8s.io/client-go/util/cert/pem_test.go +++ b/staging/src/k8s.io/client-go/util/keyutil/key_test.go @@ -1,5 +1,5 @@ /* -Copyright 2014 The Kubernetes Authors. +Copyright 2018 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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cert +package keyutil import ( "io/ioutil" diff --git a/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json b/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json index 6d87d53f44..5f226345a4 100644 --- a/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json +++ b/staging/src/k8s.io/cloud-provider/Godeps/Godeps.json @@ -950,6 +950,10 @@ "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/csi-api/Godeps/Godeps.json b/staging/src/k8s.io/csi-api/Godeps/Godeps.json index 57a482d1e5..717264ef12 100644 --- a/staging/src/k8s.io/csi-api/Godeps/Godeps.json +++ b/staging/src/k8s.io/csi-api/Godeps/Godeps.json @@ -518,6 +518,10 @@ "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 26819c2fab..24f1f50a6b 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -1758,6 +1758,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/metrics/Godeps/Godeps.json b/staging/src/k8s.io/metrics/Godeps/Godeps.json index cc62d77952..4ffe2e46a7 100644 --- a/staging/src/k8s.io/metrics/Godeps/Godeps.json +++ b/staging/src/k8s.io/metrics/Godeps/Godeps.json @@ -498,6 +498,10 @@ "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/klog", "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" diff --git a/staging/src/k8s.io/node-api/Godeps/Godeps.json b/staging/src/k8s.io/node-api/Godeps/Godeps.json index 4d0c38d895..f59bf34eca 100644 --- a/staging/src/k8s.io/node-api/Godeps/Godeps.json +++ b/staging/src/k8s.io/node-api/Godeps/Godeps.json @@ -518,6 +518,10 @@ "ImportPath": "k8s.io/client-go/util/flowcontrol", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index 81021ee679..35a5367e88 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -1718,6 +1718,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json b/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json index 26d6136cdb..7f2c60789c 100644 --- a/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-cli-plugin/Godeps/Godeps.json @@ -574,6 +574,10 @@ "ImportPath": "k8s.io/client-go/util/jsonpath", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/klog", "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" diff --git a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json index f8a7671170..d675255389 100644 --- a/staging/src/k8s.io/sample-controller/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-controller/Godeps/Godeps.json @@ -1122,6 +1122,10 @@ "ImportPath": "k8s.io/client-go/util/homedir", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, + { + "ImportPath": "k8s.io/client-go/util/keyutil", + "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, { "ImportPath": "k8s.io/client-go/util/retry", "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" diff --git a/test/e2e/apimachinery/BUILD b/test/e2e/apimachinery/BUILD index 2727fa6010..247a6696bc 100644 --- a/test/e2e/apimachinery/BUILD +++ b/test/e2e/apimachinery/BUILD @@ -67,6 +67,7 @@ go_library( "//staging/src/k8s.io/client-go/dynamic:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset:go_default_library", diff --git a/test/e2e/apimachinery/certs.go b/test/e2e/apimachinery/certs.go index 056e3db15f..3c4f0f8c00 100644 --- a/test/e2e/apimachinery/certs.go +++ b/test/e2e/apimachinery/certs.go @@ -21,7 +21,8 @@ import ( "io/ioutil" "os" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/test/e2e/framework" ) @@ -44,7 +45,7 @@ func setupServerCert(namespaceName, serviceName string) *certContext { if err != nil { framework.Failf("Failed to create CA private key %v", err) } - signingCert, err := certutil.NewSelfSignedCACert(certutil.Config{CommonName: "e2e-server-cert-ca"}, signingKey) + signingCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "e2e-server-cert-ca"}, signingKey) if err != nil { framework.Failf("Failed to create CA cert for apiserver %v", err) } @@ -60,7 +61,7 @@ func setupServerCert(namespaceName, serviceName string) *certContext { framework.Failf("Failed to create private key for %v", err) } signedCert, err := pkiutil.NewSignedCert( - &certutil.Config{ + &cert.Config{ CommonName: serviceName + "." + namespaceName + ".svc", Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, }, @@ -80,12 +81,16 @@ func setupServerCert(namespaceName, serviceName string) *certContext { if err = ioutil.WriteFile(certFile.Name(), pkiutil.EncodeCertPEM(signedCert), 0600); err != nil { framework.Failf("Failed to write cert file %v", err) } - if err = ioutil.WriteFile(keyFile.Name(), certutil.EncodePrivateKeyPEM(key), 0644); err != nil { + privateKeyPEM, err := keyutil.MarshalPrivateKeyToPEM(key) + if err != nil { + framework.Failf("Failed to marshal key %v", err) + } + if err = ioutil.WriteFile(keyFile.Name(), privateKeyPEM, 0644); err != nil { framework.Failf("Failed to write key file %v", err) } return &certContext{ cert: pkiutil.EncodeCertPEM(signedCert), - key: certutil.EncodePrivateKeyPEM(key), + key: privateKeyPEM, signingCert: pkiutil.EncodeCertPEM(signingCert), } } diff --git a/test/e2e/auth/certificates.go b/test/e2e/auth/certificates.go index ccbce67214..1dd6d74832 100644 --- a/test/e2e/auth/certificates.go +++ b/test/e2e/auth/certificates.go @@ -22,14 +22,15 @@ import ( "encoding/pem" "time" - . "github.com/onsi/ginkgo" "k8s.io/api/certificates/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" v1beta1client "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" "k8s.io/client-go/util/cert" - pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" + "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" ) var _ = SIGDescribe("Certificates API", func() { diff --git a/test/integration/auth/BUILD b/test/integration/auth/BUILD index cd8db061f9..0c99d7fd9e 100644 --- a/test/integration/auth/BUILD +++ b/test/integration/auth/BUILD @@ -85,7 +85,7 @@ go_test( "//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/watch:go_default_library", "//staging/src/k8s.io/client-go/transport:go_default_library", - "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library", "//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library", "//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library", diff --git a/test/integration/auth/svcaccttoken_test.go b/test/integration/auth/svcaccttoken_test.go index 0963ffeea4..d22e74bbef 100644 --- a/test/integration/auth/svcaccttoken_test.go +++ b/test/integration/auth/svcaccttoken_test.go @@ -41,7 +41,7 @@ import ( clientset "k8s.io/client-go/kubernetes" v1listers "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" "k8s.io/kubernetes/pkg/apis/core" serviceaccountgetter "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/features" @@ -59,7 +59,7 @@ func TestServiceAccountTokenCreate(t *testing.T) { defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TokenRequest, true)() // Build client config, clientset, and informers - sk, err := certutil.ParsePrivateKeyPEM([]byte(ecdsaPrivateKey)) + sk, err := keyutil.ParsePrivateKeyPEM([]byte(ecdsaPrivateKey)) if err != nil { t.Fatalf("err: %v", err) } diff --git a/test/integration/examples/BUILD b/test/integration/examples/BUILD index 51cbdb7483..eb0f8adb2e 100644 --- a/test/integration/examples/BUILD +++ b/test/integration/examples/BUILD @@ -36,6 +36,7 @@ go_test( "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library", "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", + "//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/cmd/server:go_default_library", diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index e8b5d43b63..3359c4c22f 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -42,13 +42,14 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - certutil "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/cert" + "k8s.io/client-go/util/keyutil" apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1" aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" kubeaggregatorserver "k8s.io/kube-aggregator/pkg/cmd/server" "k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" - pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" + "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/test/integration/framework" wardlev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" wardlev1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" @@ -66,7 +67,7 @@ func TestAggregatedAPIServer(t *testing.T) { if err != nil { t.Fatal(err) } - proxySigningCert, err := certutil.NewSelfSignedCACert(certutil.Config{CommonName: "front-proxy-ca"}, proxySigningKey) + proxySigningCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "front-proxy-ca"}, proxySigningKey) if err != nil { t.Fatal(err) } @@ -78,7 +79,7 @@ func TestAggregatedAPIServer(t *testing.T) { if err != nil { t.Fatal(err) } - clientSigningCert, err := certutil.NewSelfSignedCACert(certutil.Config{CommonName: "client-ca"}, clientSigningKey) + clientSigningCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "client-ca"}, clientSigningKey) if err != nil { t.Fatal(err) } @@ -240,7 +241,7 @@ func TestAggregatedAPIServer(t *testing.T) { t.Fatal(err) } proxyClientCert, err := pkiutil.NewSignedCert( - &certutil.Config{ + &cert.Config{ CommonName: "kube-aggregator", Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, }, @@ -251,7 +252,11 @@ func TestAggregatedAPIServer(t *testing.T) { if err := ioutil.WriteFile(proxyClientCertFile.Name(), pkiutil.EncodeCertPEM(proxyClientCert), 0600); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(proxyClientKeyFile.Name(), certutil.EncodePrivateKeyPEM(proxyClientKey), 0644); err != nil { + proxyClientKeyPEM, err := keyutil.MarshalPrivateKeyToPEM(proxyClientKey) + if err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(proxyClientKeyFile.Name(), proxyClientKeyPEM, 0644); err != nil { t.Fatal(err) } aggregatorPort := new(int32) diff --git a/test/integration/framework/test_server.go b/test/integration/framework/test_server.go index c4a58828f7..1b223a1579 100644 --- a/test/integration/framework/test_server.go +++ b/test/integration/framework/test_server.go @@ -32,11 +32,10 @@ import ( genericapiserveroptions "k8s.io/apiserver/pkg/server/options" client "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - certutil "k8s.io/client-go/util/cert" - + "k8s.io/client-go/util/cert" "k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" - pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" + "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/pkg/master" ) @@ -58,7 +57,7 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup if err != nil { t.Fatal(err) } - proxySigningCert, err := certutil.NewSelfSignedCACert(certutil.Config{CommonName: "front-proxy-ca"}, proxySigningKey) + proxySigningCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "front-proxy-ca"}, proxySigningKey) if err != nil { t.Fatal(err) } @@ -70,7 +69,7 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup if err != nil { t.Fatal(err) } - clientSigningCert, err := certutil.NewSelfSignedCACert(certutil.Config{CommonName: "client-ca"}, clientSigningKey) + clientSigningCert, err := cert.NewSelfSignedCACert(cert.Config{CommonName: "client-ca"}, clientSigningKey) if err != nil { t.Fatal(err) }