kubeadm: allow creating a cluster with ECDSA keys

The selected key type is defined by kubeadm's --feature-gates option:
if it contains PublicKeysECDSA=true then ECDSA keys will be generated
and used.

By default RSA keys are used still.

Signed-off-by: Dmitry Rozhkov <dmitry.rozhkov@linux.intel.com>
This commit is contained in:
Dmitry Rozhkov 2020-02-21 16:43:37 +02:00
parent ac25069a05
commit 109f5db5a3
22 changed files with 241 additions and 133 deletions

View File

@ -19,6 +19,7 @@ go_library(
], ],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm", importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm",
deps = [ deps = [
"//cmd/kubeadm/app/features:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -17,8 +17,11 @@ limitations under the License.
package kubeadm package kubeadm
import ( import (
"crypto/x509"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -400,6 +403,15 @@ func (cfg *ClusterConfiguration) GetControlPlaneImageRepository() string {
return cfg.ImageRepository return cfg.ImageRepository
} }
// PublicKeyAlgorithm returns the type of encryption keys used in the cluster.
func (cfg *ClusterConfiguration) PublicKeyAlgorithm() x509.PublicKeyAlgorithm {
if features.Enabled(cfg.FeatureGates, features.PublicKeysECDSA) {
return x509.ECDSA
}
return x509.RSA
}
// HostPathMount contains elements describing volumes that are mounted from the // HostPathMount contains elements describing volumes that are mounted from the
// host. // host.
type HostPathMount struct { type HostPathMount struct {

View File

@ -200,7 +200,7 @@ func runCertsSa(c workflow.RunData) error {
} }
// create the new service account key (or use existing) // create the new service account key (or use existing)
return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(data.CertificateWriteDir()) return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(data.CertificateWriteDir(), data.Cfg().ClusterConfiguration.PublicKeyAlgorithm())
} }
func runCerts(c workflow.RunData) error { func runCerts(c workflow.RunData) error {

View File

@ -35,7 +35,7 @@ go_test(
srcs = ["features_test.go"], srcs = ["features_test.go"],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//cmd/kubeadm/app/constants:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//staging/src/k8s.io/component-base/featuregate:go_default_library", "//staging/src/k8s.io/component-base/featuregate:go_default_library",
], ],
) )

View File

@ -30,11 +30,14 @@ import (
const ( const (
// IPv6DualStack is expected to be alpha in v1.16 // IPv6DualStack is expected to be alpha in v1.16
IPv6DualStack = "IPv6DualStack" IPv6DualStack = "IPv6DualStack"
// PublicKeysECDSA is expected to be alpha in v1.19
PublicKeysECDSA = "PublicKeysECDSA"
) )
// InitFeatureGates are the default feature gates for the init command // InitFeatureGates are the default feature gates for the init command
var InitFeatureGates = FeatureList{ var InitFeatureGates = FeatureList{
IPv6DualStack: {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Alpha}}, IPv6DualStack: {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Alpha}},
PublicKeysECDSA: {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Alpha}},
} }
// Feature represents a feature being gated // Feature represents a feature being gated

View File

@ -20,8 +20,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/component-base/featuregate" "k8s.io/component-base/featuregate"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
) )
func TestKnownFeatures(t *testing.T) { func TestKnownFeatures(t *testing.T) {
@ -129,7 +129,7 @@ func TestNewFeatureGate(t *testing.T) {
func TestValidateVersion(t *testing.T) { func TestValidateVersion(t *testing.T) {
var someFeatures = FeatureList{ var someFeatures = FeatureList{
"feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}}, "feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
"feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}, MinimumVersion: constants.MinimumControlPlaneVersion.WithPreRelease("alpha.1")}, "feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}, MinimumVersion: version.MustParseSemantic("v1.17.0").WithPreRelease("alpha.1")},
} }
var tests = []struct { var tests = []struct {
@ -146,7 +146,7 @@ func TestValidateVersion(t *testing.T) {
{ {
name: "min version but correct value given", name: "min version but correct value given",
requestedFeatures: map[string]bool{"feature2": true}, requestedFeatures: map[string]bool{"feature2": true},
requestedVersion: constants.MinimumControlPlaneVersion.String(), requestedVersion: "v1.17.0",
expectedError: false, expectedError: false,
}, },
{ {

View File

@ -28,7 +28,7 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
) )
type configMutatorsFunc func(*kubeadmapi.InitConfiguration, *certutil.Config) error type configMutatorsFunc func(*kubeadmapi.InitConfiguration, *pkiutil.CertConfig) error
// KubeadmCert represents a certificate that Kubeadm will create to function properly. // KubeadmCert represents a certificate that Kubeadm will create to function properly.
type KubeadmCert struct { type KubeadmCert struct {
@ -39,17 +39,18 @@ type KubeadmCert struct {
// Some attributes will depend on the InitConfiguration, only known at runtime. // Some attributes will depend on the InitConfiguration, only known at runtime.
// These functions will be run in series, passed both the InitConfiguration and a cert Config. // These functions will be run in series, passed both the InitConfiguration and a cert Config.
configMutators []configMutatorsFunc configMutators []configMutatorsFunc
config certutil.Config config pkiutil.CertConfig
} }
// GetConfig returns the definition for the given cert given the provided InitConfiguration // GetConfig returns the definition for the given cert given the provided InitConfiguration
func (k *KubeadmCert) GetConfig(ic *kubeadmapi.InitConfiguration) (*certutil.Config, error) { func (k *KubeadmCert) GetConfig(ic *kubeadmapi.InitConfiguration) (*pkiutil.CertConfig, error) {
for _, f := range k.configMutators { for _, f := range k.configMutators {
if err := f(ic, &k.config); err != nil { if err := f(ic, &k.config); err != nil {
return nil, err return nil, err
} }
} }
k.config.PublicKeyAlgorithm = ic.ClusterConfiguration.PublicKeyAlgorithm()
return &k.config, nil return &k.config, nil
} }
@ -239,8 +240,10 @@ var (
Name: "ca", Name: "ca",
LongName: "self-signed Kubernetes CA to provision identities for other Kubernetes components", LongName: "self-signed Kubernetes CA to provision identities for other Kubernetes components",
BaseName: kubeadmconstants.CACertAndKeyBaseName, BaseName: kubeadmconstants.CACertAndKeyBaseName,
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: "kubernetes", Config: certutil.Config{
CommonName: "kubernetes",
},
}, },
} }
// KubeadmCertAPIServer is the definition of the cert used to serve the Kubernetes API. // KubeadmCertAPIServer is the definition of the cert used to serve the Kubernetes API.
@ -249,9 +252,11 @@ var (
LongName: "certificate for serving the Kubernetes API", LongName: "certificate for serving the Kubernetes API",
BaseName: kubeadmconstants.APIServerCertAndKeyBaseName, BaseName: kubeadmconstants.APIServerCertAndKeyBaseName,
CAName: "ca", CAName: "ca",
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: kubeadmconstants.APIServerCertCommonName, Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, CommonName: kubeadmconstants.APIServerCertCommonName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
},
}, },
configMutators: []configMutatorsFunc{ configMutators: []configMutatorsFunc{
makeAltNamesMutator(pkiutil.GetAPIServerAltNames), makeAltNamesMutator(pkiutil.GetAPIServerAltNames),
@ -263,10 +268,12 @@ var (
LongName: "certificate for the API server to connect to kubelet", LongName: "certificate for the API server to connect to kubelet",
BaseName: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName, BaseName: kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
CAName: "ca", CAName: "ca",
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: kubeadmconstants.APIServerKubeletClientCertCommonName, Config: certutil.Config{
Organization: []string{kubeadmconstants.SystemPrivilegedGroup}, CommonName: kubeadmconstants.APIServerKubeletClientCertCommonName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: []string{kubeadmconstants.SystemPrivilegedGroup},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
}, },
} }
@ -275,8 +282,10 @@ var (
Name: "front-proxy-ca", Name: "front-proxy-ca",
LongName: "self-signed CA to provision identities for front proxy", LongName: "self-signed CA to provision identities for front proxy",
BaseName: kubeadmconstants.FrontProxyCACertAndKeyBaseName, BaseName: kubeadmconstants.FrontProxyCACertAndKeyBaseName,
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: "front-proxy-ca", Config: certutil.Config{
CommonName: "front-proxy-ca",
},
}, },
} }
@ -286,9 +295,11 @@ var (
BaseName: kubeadmconstants.FrontProxyClientCertAndKeyBaseName, BaseName: kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
LongName: "certificate for the front proxy client", LongName: "certificate for the front proxy client",
CAName: "front-proxy-ca", CAName: "front-proxy-ca",
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: kubeadmconstants.FrontProxyClientCertCommonName, Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, CommonName: kubeadmconstants.FrontProxyClientCertCommonName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
}, },
} }
@ -297,8 +308,10 @@ var (
Name: "etcd-ca", Name: "etcd-ca",
LongName: "self-signed CA to provision identities for etcd", LongName: "self-signed CA to provision identities for etcd",
BaseName: kubeadmconstants.EtcdCACertAndKeyBaseName, BaseName: kubeadmconstants.EtcdCACertAndKeyBaseName,
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: "etcd-ca", Config: certutil.Config{
CommonName: "etcd-ca",
},
}, },
} }
// KubeadmCertEtcdServer is the definition of the cert used to serve etcd to clients. // KubeadmCertEtcdServer is the definition of the cert used to serve etcd to clients.
@ -307,12 +320,14 @@ var (
LongName: "certificate for serving etcd", LongName: "certificate for serving etcd",
BaseName: kubeadmconstants.EtcdServerCertAndKeyBaseName, BaseName: kubeadmconstants.EtcdServerCertAndKeyBaseName,
CAName: "etcd-ca", CAName: "etcd-ca",
config: certutil.Config{ config: pkiutil.CertConfig{
// TODO: etcd 3.2 introduced an undocumented requirement for ClientAuth usage on the Config: certutil.Config{
// server cert: https://github.com/coreos/etcd/issues/9785#issuecomment-396715692 // TODO: etcd 3.2 introduced an undocumented requirement for ClientAuth usage on the
// Once the upstream issue is resolved, this should be returned to only allowing // server cert: https://github.com/coreos/etcd/issues/9785#issuecomment-396715692
// ServerAuth usage. // Once the upstream issue is resolved, this should be returned to only allowing
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, // ServerAuth usage.
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
},
}, },
configMutators: []configMutatorsFunc{ configMutators: []configMutatorsFunc{
makeAltNamesMutator(pkiutil.GetEtcdAltNames), makeAltNamesMutator(pkiutil.GetEtcdAltNames),
@ -325,8 +340,10 @@ var (
LongName: "certificate for etcd nodes to communicate with each other", LongName: "certificate for etcd nodes to communicate with each other",
BaseName: kubeadmconstants.EtcdPeerCertAndKeyBaseName, BaseName: kubeadmconstants.EtcdPeerCertAndKeyBaseName,
CAName: "etcd-ca", CAName: "etcd-ca",
config: certutil.Config{ config: pkiutil.CertConfig{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
},
}, },
configMutators: []configMutatorsFunc{ configMutators: []configMutatorsFunc{
makeAltNamesMutator(pkiutil.GetEtcdPeerAltNames), makeAltNamesMutator(pkiutil.GetEtcdPeerAltNames),
@ -339,10 +356,12 @@ var (
LongName: "certificate for liveness probes to healthcheck etcd", LongName: "certificate for liveness probes to healthcheck etcd",
BaseName: kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName, BaseName: kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
CAName: "etcd-ca", CAName: "etcd-ca",
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: kubeadmconstants.EtcdHealthcheckClientCertCommonName, Config: certutil.Config{
Organization: []string{kubeadmconstants.SystemPrivilegedGroup}, CommonName: kubeadmconstants.EtcdHealthcheckClientCertCommonName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: []string{kubeadmconstants.SystemPrivilegedGroup},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
}, },
} }
// KubeadmCertEtcdAPIClient is the definition of the cert used by the API server to access etcd. // KubeadmCertEtcdAPIClient is the definition of the cert used by the API server to access etcd.
@ -351,16 +370,18 @@ var (
LongName: "certificate the apiserver uses to access etcd", LongName: "certificate the apiserver uses to access etcd",
BaseName: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName, BaseName: kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
CAName: "etcd-ca", CAName: "etcd-ca",
config: certutil.Config{ config: pkiutil.CertConfig{
CommonName: kubeadmconstants.APIServerEtcdClientCertCommonName, Config: certutil.Config{
Organization: []string{kubeadmconstants.SystemPrivilegedGroup}, CommonName: kubeadmconstants.APIServerEtcdClientCertCommonName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: []string{kubeadmconstants.SystemPrivilegedGroup},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
}, },
} }
) )
func makeAltNamesMutator(f func(*kubeadmapi.InitConfiguration) (*certutil.AltNames, error)) configMutatorsFunc { func makeAltNamesMutator(f func(*kubeadmapi.InitConfiguration) (*certutil.AltNames, error)) configMutatorsFunc {
return func(mc *kubeadmapi.InitConfiguration, cc *certutil.Config) error { return func(mc *kubeadmapi.InitConfiguration, cc *pkiutil.CertConfig) error {
altNames, err := f(mc) altNames, err := f(mc)
if err != nil { if err != nil {
return err return err
@ -371,7 +392,7 @@ func makeAltNamesMutator(f func(*kubeadmapi.InitConfiguration) (*certutil.AltNam
} }
func setCommonNameToNodeName() configMutatorsFunc { func setCommonNameToNodeName() configMutatorsFunc {
return func(mc *kubeadmapi.InitConfiguration, cc *certutil.Config) error { return func(mc *kubeadmapi.InitConfiguration, cc *pkiutil.CertConfig) error {
cc.CommonName = mc.NodeRegistration.Name cc.CommonName = mc.NodeRegistration.Name
return nil return nil
} }

View File

@ -27,6 +27,7 @@ import (
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
) )
func TestCertListOrder(t *testing.T) { func TestCertListOrder(t *testing.T) {
@ -160,16 +161,18 @@ func TestCreateCertificateChain(t *testing.T) {
caCfg := Certificates{ caCfg := Certificates{
{ {
config: certutil.Config{}, config: pkiutil.CertConfig{},
Name: "test-ca", Name: "test-ca",
BaseName: "test-ca", BaseName: "test-ca",
}, },
{ {
config: certutil.Config{ config: pkiutil.CertConfig{
AltNames: certutil.AltNames{ Config: certutil.Config{
DNSNames: []string{"test-domain.space"}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"},
},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
configMutators: []configMutatorsFunc{ configMutators: []configMutatorsFunc{
setCommonNameToNodeName(), setCommonNameToNodeName(),

View File

@ -24,7 +24,6 @@ import (
"path/filepath" "path/filepath"
"github.com/pkg/errors" "github.com/pkg/errors"
certutil "k8s.io/client-go/util/cert"
"k8s.io/client-go/util/keyutil" "k8s.io/client-go/util/keyutil"
"k8s.io/klog" "k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
@ -61,12 +60,12 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error {
fmt.Printf("[certs] Valid certificates and keys now exist in %q\n", cfg.CertificatesDir) fmt.Printf("[certs] Valid certificates and keys now exist in %q\n", cfg.CertificatesDir)
// Service accounts are not x509 certs, so handled separately // Service accounts are not x509 certs, so handled separately
return CreateServiceAccountKeyAndPublicKeyFiles(cfg.CertificatesDir) return CreateServiceAccountKeyAndPublicKeyFiles(cfg.CertificatesDir, cfg.ClusterConfiguration.PublicKeyAlgorithm())
} }
// CreateServiceAccountKeyAndPublicKeyFiles creates new public/private key files for signing service account users. // CreateServiceAccountKeyAndPublicKeyFiles creates new public/private key files for signing service account users.
// If the sa public/private key files already exist in the target folder, they are used only if evaluated equals; otherwise an error is returned. // If the sa public/private key files already exist in the target folder, they are used only if evaluated equals; otherwise an error is returned.
func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string) error { func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string, keyType x509.PublicKeyAlgorithm) error {
klog.V(1).Infoln("creating new public/private key files for signing service account users") klog.V(1).Infoln("creating new public/private key files for signing service account users")
_, err := keyutil.PrivateKeyFromFile(filepath.Join(certsDir, kubeadmconstants.ServiceAccountPrivateKeyName)) _, err := keyutil.PrivateKeyFromFile(filepath.Join(certsDir, kubeadmconstants.ServiceAccountPrivateKeyName))
if err == nil { if err == nil {
@ -80,7 +79,7 @@ func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string) error {
} }
// The key does NOT exist, let's generate it now // The key does NOT exist, let's generate it now
key, err := pkiutil.NewPrivateKey() key, err := pkiutil.NewPrivateKey(keyType)
if err != nil { if err != nil {
return err return err
} }
@ -215,7 +214,7 @@ func writeCertificateAuthorityFilesIfNotExist(pkiDir string, baseName string, ca
// If there already is a certificate file at the given path; kubeadm tries to load it and check if the values in the // If there already is a certificate file at the given path; kubeadm tries to load it and check if the values in the
// existing and the expected certificate equals. If they do; kubeadm will just skip writing the file as it's up-to-date, // existing and the expected certificate equals. If they do; kubeadm will just skip writing the file as it's up-to-date,
// otherwise this function returns an error. // otherwise this function returns an error.
func writeCertificateFilesIfNotExist(pkiDir string, baseName string, signingCert *x509.Certificate, cert *x509.Certificate, key crypto.Signer, cfg *certutil.Config) error { func writeCertificateFilesIfNotExist(pkiDir string, baseName string, signingCert *x509.Certificate, cert *x509.Certificate, key crypto.Signer, cfg *pkiutil.CertConfig) error {
// Checks if the signed certificate exists in the PKI directory // Checks if the signed certificate exists in the PKI directory
if pkiutil.CertOrKeyExist(pkiDir, baseName) { if pkiutil.CertOrKeyExist(pkiDir, baseName) {
@ -426,7 +425,7 @@ func validatePrivatePublicKey(l certKeyLocation) error {
// validateCertificateWithConfig makes sure that a given certificate is valid at // validateCertificateWithConfig makes sure that a given certificate is valid at
// least for the SANs defined in the configuration. // least for the SANs defined in the configuration.
func validateCertificateWithConfig(cert *x509.Certificate, baseName string, cfg *certutil.Config) error { func validateCertificateWithConfig(cert *x509.Certificate, baseName string, cfg *pkiutil.CertConfig) error {
for _, dnsName := range cfg.AltNames.DNSNames { for _, dnsName := range cfg.AltNames.DNSNames {
if err := cert.VerifyHostname(dnsName); err != nil { if err := cert.VerifyHostname(dnsName); err != nil {
return errors.Wrapf(err, "certificate %s is invalid", baseName) return errors.Wrapf(err, "certificate %s is invalid", baseName)

View File

@ -42,8 +42,10 @@ import (
func createTestCSR(t *testing.T) (*x509.CertificateRequest, crypto.Signer) { func createTestCSR(t *testing.T) (*x509.CertificateRequest, crypto.Signer) {
csr, key, err := pkiutil.NewCSRAndKey( csr, key, err := pkiutil.NewCSRAndKey(
&certutil.Config{ &pkiutil.CertConfig{
CommonName: "testCert", Config: certutil.Config{
CommonName: "testCert",
},
}) })
if err != nil { if err != nil {
t.Fatalf("couldn't create test cert: %v", err) t.Fatalf("couldn't create test cert: %v", err)
@ -344,7 +346,7 @@ func TestCreateServiceAccountKeyAndPublicKeyFiles(t *testing.T) {
} }
} }
err := CreateServiceAccountKeyAndPublicKeyFiles(dir) err := CreateServiceAccountKeyAndPublicKeyFiles(dir, x509.RSA)
if (err != nil) != tt.expectedErr { if (err != nil) != tt.expectedErr {
t.Fatalf("expected error: %v, got: %v, error: %v", tt.expectedErr, err != nil, err) t.Fatalf("expected error: %v, got: %v, error: %v", tt.expectedErr, err != nil, err)
} else if tt.expectedErr { } else if tt.expectedErr {

View File

@ -52,7 +52,7 @@ func NewAPIRenewer(client clientset.Interface) *APIRenewer {
} }
// Renew a certificate using the K8s certificate API // Renew a certificate using the K8s certificate API
func (r *APIRenewer) Renew(cfg *certutil.Config) (*x509.Certificate, crypto.Signer, error) { func (r *APIRenewer) Renew(cfg *pkiutil.CertConfig) (*x509.Certificate, crypto.Signer, error) {
reqTmp := &x509.CertificateRequest{ reqTmp := &x509.CertificateRequest{
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: cfg.CommonName, CommonName: cfg.CommonName,
@ -62,7 +62,7 @@ func (r *APIRenewer) Renew(cfg *certutil.Config) (*x509.Certificate, crypto.Sign
IPAddresses: cfg.AltNames.IPs, IPAddresses: cfg.AltNames.IPs,
} }
key, err := pkiutil.NewPrivateKey() key, err := pkiutil.NewPrivateKey(cfg.PublicKeyAlgorithm)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "couldn't create new private key") return nil, nil, errors.Wrap(err, "couldn't create new private key")
} }

View File

@ -33,7 +33,9 @@ import (
) )
func TestAPIRenewer(t *testing.T) { func TestAPIRenewer(t *testing.T) {
caCertCfg := &certutil.Config{CommonName: "kubernetes"} caCertCfg := &pkiutil.CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
}
caCert, caKey, err := pkiutil.NewCertificateAuthority(caCertCfg) caCert, caKey, err := pkiutil.NewCertificateAuthority(caCertCfg)
if err != nil { if err != nil {
t.Fatalf("couldn't create CA: %v", err) t.Fatalf("couldn't create CA: %v", err)
@ -55,12 +57,14 @@ func TestAPIRenewer(t *testing.T) {
// override the timeout so tests are faster // override the timeout so tests are faster
watchTimeout = time.Second watchTimeout = time.Second
certCfg := &certutil.Config{ certCfg := &pkiutil.CertConfig{
CommonName: "test-certs", Config: certutil.Config{
AltNames: certutil.AltNames{ CommonName: "test-certs",
DNSNames: []string{"test-domain.space"}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"},
},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
} }
renewer := &APIRenewer{ renewer := &APIRenewer{
@ -92,12 +96,14 @@ func defaultReactionFunc(obj runtime.Object) k8stesting.ReactionFunc {
} }
func getCertReq(t *testing.T, caCert *x509.Certificate, caKey crypto.Signer) *certsapi.CertificateSigningRequest { func getCertReq(t *testing.T, caCert *x509.Certificate, caKey crypto.Signer) *certsapi.CertificateSigningRequest {
cert, _, err := pkiutil.NewCertAndKey(caCert, caKey, &certutil.Config{ cert, _, err := pkiutil.NewCertAndKey(caCert, caKey, &pkiutil.CertConfig{
CommonName: "testcert", Config: certutil.Config{
AltNames: certutil.AltNames{ CommonName: "testcert",
DNSNames: []string{"test-domain.space"}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"},
},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}) })
if err != nil { if err != nil {
t.Fatalf("couldn't generate cert: %v", err) t.Fatalf("couldn't generate cert: %v", err)

View File

@ -20,7 +20,6 @@ import (
"crypto" "crypto"
"crypto/x509" "crypto/x509"
certutil "k8s.io/client-go/util/cert"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
) )
@ -39,6 +38,6 @@ func NewFileRenewer(caCert *x509.Certificate, caKey crypto.Signer) *FileRenewer
} }
// Renew a certificate using a given CA cert and key // Renew a certificate using a given CA cert and key
func (r *FileRenewer) Renew(cfg *certutil.Config) (*x509.Certificate, crypto.Signer, error) { func (r *FileRenewer) Renew(cfg *pkiutil.CertConfig) (*x509.Certificate, crypto.Signer, error) {
return pkiutil.NewCertAndKey(r.caCert, r.caKey, cfg) return pkiutil.NewCertAndKey(r.caCert, r.caKey, cfg)
} }

View File

@ -21,6 +21,7 @@ import (
"testing" "testing"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
) )
func TestFileRenewer(t *testing.T) { func TestFileRenewer(t *testing.T) {
@ -28,12 +29,14 @@ func TestFileRenewer(t *testing.T) {
fr := NewFileRenewer(testCACert, testCAKey) fr := NewFileRenewer(testCACert, testCAKey)
// renews a certificate // renews a certificate
certCfg := &certutil.Config{ certCfg := &pkiutil.CertConfig{
CommonName: "test-certs", Config: certutil.Config{
AltNames: certutil.AltNames{ CommonName: "test-certs",
DNSNames: []string{"test-domain.space"}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"},
},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
} }
cert, _, err := fr.Renew(certCfg) cert, _, err := fr.Renew(certCfg)

View File

@ -224,7 +224,10 @@ func (rm *Manager) RenewUsingLocalCA(name string) (bool, error) {
} }
// extract the certificate config // extract the certificate config
cfg := certToConfig(cert) cfg := &pkiutil.CertConfig{
Config: certToConfig(cert),
PublicKeyAlgorithm: rm.cfg.PublicKeyAlgorithm(),
}
// reads the CA // reads the CA
caCert, caKey, err := certsphase.LoadCertificateAuthority(rm.cfg.CertificatesDir, handler.CABaseName) caCert, caKey, err := certsphase.LoadCertificateAuthority(rm.cfg.CertificatesDir, handler.CABaseName)
@ -264,7 +267,10 @@ func (rm *Manager) RenewUsingCSRAPI(name string, client clientset.Interface) err
} }
// extract the certificate config // extract the certificate config
cfg := certToConfig(cert) cfg := &pkiutil.CertConfig{
Config: certToConfig(cert),
PublicKeyAlgorithm: rm.cfg.PublicKeyAlgorithm(),
}
// create a new certificate with the same config // create a new certificate with the same config
newCert, newKey, err := NewAPIRenewer(client).Renew(cfg) newCert, newKey, err := NewAPIRenewer(client).Renew(cfg)
@ -298,7 +304,10 @@ func (rm *Manager) CreateRenewCSR(name, outdir string) error {
} }
// extracts the certificate config // extracts the certificate config
cfg := certToConfig(cert) cfg := &pkiutil.CertConfig{
Config: certToConfig(cert),
PublicKeyAlgorithm: rm.cfg.PublicKeyAlgorithm(),
}
// generates the CSR request and save it // generates the CSR request and save it
csr, key, err := pkiutil.NewCSRAndKey(cfg) csr, key, err := pkiutil.NewCSRAndKey(cfg)
@ -407,8 +416,8 @@ func (rm *Manager) IsExternallyManaged(caBaseName string) (bool, error) {
} }
} }
func certToConfig(cert *x509.Certificate) *certutil.Config { func certToConfig(cert *x509.Certificate) certutil.Config {
return &certutil.Config{ return certutil.Config{
CommonName: cert.Subject.CommonName, CommonName: cert.Subject.CommonName,
Organization: cert.Subject.Organization, Organization: cert.Subject.Organization,
AltNames: certutil.AltNames{ AltNames: certutil.AltNames{

View File

@ -34,18 +34,22 @@ import (
) )
var ( var (
testCACertCfg = &certutil.Config{CommonName: "kubernetes"} testCACertCfg = &pkiutil.CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
}
testCACert, testCAKey, _ = pkiutil.NewCertificateAuthority(testCACertCfg) testCACert, testCAKey, _ = pkiutil.NewCertificateAuthority(testCACertCfg)
testCertCfg = &certutil.Config{ testCertCfg = &pkiutil.CertConfig{
CommonName: "test-common-name", Config: certutil.Config{
Organization: []string{"sig-cluster-lifecycle"}, CommonName: "test-common-name",
AltNames: certutil.AltNames{ Organization: []string{"sig-cluster-lifecycle"},
IPs: []net.IP{net.ParseIP("10.100.0.1")}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"}, IPs: []net.IP{net.ParseIP("10.100.0.1")},
DNSNames: []string{"test-domain.space"},
},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}, },
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
} }
) )

View File

@ -154,13 +154,15 @@ func writeTestCertificate(t *testing.T, dir, name string, caCert *x509.Certifica
// writeTestKubeconfig is a utility for creating a test kubeconfig with an embedded certificate // writeTestKubeconfig is a utility for creating a test kubeconfig with an embedded certificate
func writeTestKubeconfig(t *testing.T, dir, name string, caCert *x509.Certificate, caKey crypto.Signer) *x509.Certificate { func writeTestKubeconfig(t *testing.T, dir, name string, caCert *x509.Certificate, caKey crypto.Signer) *x509.Certificate {
cfg := &certutil.Config{ cfg := &pkiutil.CertConfig{
CommonName: "test-common-name", Config: certutil.Config{
Organization: []string{"sig-cluster-lifecycle"}, CommonName: "test-common-name",
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: []string{"sig-cluster-lifecycle"},
AltNames: certutil.AltNames{ Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
IPs: []net.IP{net.ParseIP("10.100.0.1")}, AltNames: certutil.AltNames{
DNSNames: []string{"test-domain.space"}, IPs: []net.IP{net.ParseIP("10.100.0.1")},
DNSNames: []string{"test-domain.space"},
},
}, },
} }
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, cfg) cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, cfg)

View File

@ -182,10 +182,12 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientc
} }
// otherwise, create a client certs // otherwise, create a client certs
clientCertConfig := certutil.Config{ clientCertConfig := pkiutil.CertConfig{
CommonName: spec.ClientName, Config: certutil.Config{
Organization: spec.ClientCertAuth.Organizations, CommonName: spec.ClientName,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: spec.ClientCertAuth.Organizations,
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
} }
clientCert, clientKey, err := pkiutil.NewCertAndKey(spec.CACert, spec.ClientCertAuth.CAKey, &clientCertConfig) clientCert, clientKey, err := pkiutil.NewCertAndKey(spec.CACert, spec.ClientCertAuth.CAKey, &clientCertConfig)
if err != nil { if err != nil {

View File

@ -32,7 +32,9 @@ import (
// SetupCertificateAuthority is a utility function for kubeadm testing that creates a // SetupCertificateAuthority is a utility function for kubeadm testing that creates a
// CertificateAuthority cert/key pair // CertificateAuthority cert/key pair
func SetupCertificateAuthority(t *testing.T) (*x509.Certificate, crypto.Signer) { func SetupCertificateAuthority(t *testing.T) (*x509.Certificate, crypto.Signer) {
caCert, caKey, err := pkiutil.NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) caCert, caKey, err := pkiutil.NewCertificateAuthority(&pkiutil.CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
})
if err != nil { if err != nil {
t.Fatalf("failure while generating CA certificate and key: %v", err) t.Fatalf("failure while generating CA certificate and key: %v", err)
} }
@ -132,7 +134,7 @@ func AssertCertificateHasIPAddresses(t *testing.T, cert *x509.Certificate, IPAdd
// CreateCACert creates a generic CA cert. // CreateCACert creates a generic CA cert.
func CreateCACert(t *testing.T) (*x509.Certificate, crypto.Signer) { func CreateCACert(t *testing.T) (*x509.Certificate, crypto.Signer) {
certCfg := &certutil.Config{CommonName: "kubernetes"} certCfg := &pkiutil.CertConfig{Config: certutil.Config{CommonName: "kubernetes"}}
cert, key, err := pkiutil.NewCertificateAuthority(certCfg) cert, key, err := pkiutil.NewCertificateAuthority(certCfg)
if err != nil { if err != nil {
t.Fatalf("couldn't create CA: %v", err) t.Fatalf("couldn't create CA: %v", err)
@ -141,11 +143,13 @@ func CreateCACert(t *testing.T) (*x509.Certificate, crypto.Signer) {
} }
// CreateTestCert makes a generic certificate with the given CA and alternative names. // CreateTestCert makes a generic certificate with the given CA and alternative names.
func CreateTestCert(t *testing.T, caCert *x509.Certificate, caKey crypto.Signer, altNames certutil.AltNames) (*x509.Certificate, crypto.Signer, *certutil.Config) { func CreateTestCert(t *testing.T, caCert *x509.Certificate, caKey crypto.Signer, altNames certutil.AltNames) (*x509.Certificate, crypto.Signer, *pkiutil.CertConfig) {
config := &certutil.Config{ config := &pkiutil.CertConfig{
CommonName: "testCert", Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, CommonName: "testCert",
AltNames: altNames, Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
AltNames: altNames,
},
} }
cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, config) cert, key, err := pkiutil.NewCertAndKey(caCert, caKey, config)
if err != nil { if err != nil {

View File

@ -19,6 +19,7 @@ package pkiutil
import ( import (
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic"
cryptorand "crypto/rand" cryptorand "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
@ -56,14 +57,20 @@ const (
rsaKeySize = 2048 rsaKeySize = 2048
) )
// CertConfig is a wrapper around certutil.Config extending it with PublicKeyAlgorithm.
type CertConfig struct {
certutil.Config
PublicKeyAlgorithm x509.PublicKeyAlgorithm
}
// NewCertificateAuthority creates new certificate and private key for the certificate authority // NewCertificateAuthority creates new certificate and private key for the certificate authority
func NewCertificateAuthority(config *certutil.Config) (*x509.Certificate, crypto.Signer, error) { func NewCertificateAuthority(config *CertConfig) (*x509.Certificate, crypto.Signer, error) {
key, err := NewPrivateKey() key, err := NewPrivateKey(config.PublicKeyAlgorithm)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "unable to create private key while generating CA certificate") return nil, nil, errors.Wrap(err, "unable to create private key while generating CA certificate")
} }
cert, err := certutil.NewSelfSignedCACert(*config, key) cert, err := certutil.NewSelfSignedCACert(config.Config, key)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "unable to create self-signed CA certificate") return nil, nil, errors.Wrap(err, "unable to create self-signed CA certificate")
} }
@ -72,8 +79,8 @@ func NewCertificateAuthority(config *certutil.Config) (*x509.Certificate, crypto
} }
// NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key // NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key
func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *certutil.Config) (*x509.Certificate, crypto.Signer, error) { func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *CertConfig) (*x509.Certificate, crypto.Signer, error) {
key, err := NewPrivateKey() key, err := NewPrivateKey(config.PublicKeyAlgorithm)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "unable to create private key") return nil, nil, errors.Wrap(err, "unable to create private key")
} }
@ -87,8 +94,8 @@ func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *certut
} }
// NewCSRAndKey generates a new key and CSR and that could be signed to create the given certificate // NewCSRAndKey generates a new key and CSR and that could be signed to create the given certificate
func NewCSRAndKey(config *certutil.Config) (*x509.CertificateRequest, crypto.Signer, error) { func NewCSRAndKey(config *CertConfig) (*x509.CertificateRequest, crypto.Signer, error) {
key, err := NewPrivateKey() key, err := NewPrivateKey(config.PublicKeyAlgorithm)
if err != nil { if err != nil {
return nil, nil, errors.Wrap(err, "unable to create private key") return nil, nil, errors.Wrap(err, "unable to create private key")
} }
@ -496,7 +503,7 @@ func CertificateRequestFromFile(file string) (*x509.CertificateRequest, error) {
} }
// NewCSR creates a new CSR // NewCSR creates a new CSR
func NewCSR(cfg certutil.Config, key crypto.Signer) (*x509.CertificateRequest, error) { func NewCSR(cfg CertConfig, key crypto.Signer) (*x509.CertificateRequest, error) {
template := &x509.CertificateRequest{ template := &x509.CertificateRequest{
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: cfg.CommonName, CommonName: cfg.CommonName,
@ -538,12 +545,16 @@ func EncodePublicKeyPEM(key crypto.PublicKey) ([]byte, error) {
} }
// NewPrivateKey creates an RSA private key // NewPrivateKey creates an RSA private key
func NewPrivateKey() (crypto.Signer, error) { func NewPrivateKey(keyType x509.PublicKeyAlgorithm) (crypto.Signer, error) {
if keyType == x509.ECDSA {
return ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
}
return rsa.GenerateKey(cryptorand.Reader, rsaKeySize) return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
} }
// NewSignedCert creates a signed certificate using the given CA certificate and key // NewSignedCert creates a signed certificate using the given CA certificate and key
func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) { func NewSignedCert(cfg *CertConfig, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64)) serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -33,7 +33,9 @@ import (
) )
func TestNewCertificateAuthority(t *testing.T) { func TestNewCertificateAuthority(t *testing.T) {
cert, key, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) cert, key, err := NewCertificateAuthority(&CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
})
if cert == nil { if cert == nil {
t.Error("failed NewCertificateAuthority, cert == nil") t.Error("failed NewCertificateAuthority, cert == nil")
@ -86,10 +88,12 @@ func TestNewCertAndKey(t *testing.T) {
t.Fatalf("Couldn't create Private Key") t.Fatalf("Couldn't create Private Key")
} }
caCert := &x509.Certificate{} caCert := &x509.Certificate{}
config := &certutil.Config{ config := &CertConfig{
CommonName: "test", Config: certutil.Config{
Organization: []string{"test"}, CommonName: "test",
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, Organization: []string{"test"},
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
} }
_, _, actual := NewCertAndKey(caCert, caKey, config) _, _, actual := NewCertAndKey(caCert, caKey, config)
if (actual == nil) != rt.expected { if (actual == nil) != rt.expected {
@ -104,26 +108,41 @@ func TestNewCertAndKey(t *testing.T) {
} }
func TestHasServerAuth(t *testing.T) { func TestHasServerAuth(t *testing.T) {
caCert, caKey, _ := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) caCert, caKey, _ := NewCertificateAuthority(&CertConfig{Config: certutil.Config{CommonName: "kubernetes"}})
var tests = []struct { var tests = []struct {
name string name string
config certutil.Config config CertConfig
expected bool expected bool
}{ }{
{ {
name: "has ServerAuth", name: "has ServerAuth",
config: certutil.Config{ config: CertConfig{
CommonName: "test", Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, CommonName: "test",
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
},
},
expected: true,
},
{
name: "has ServerAuth ECDSA",
config: CertConfig{
Config: certutil.Config{
CommonName: "test",
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
},
PublicKeyAlgorithm: x509.ECDSA,
}, },
expected: true, expected: true,
}, },
{ {
name: "doesn't have ServerAuth", name: "doesn't have ServerAuth",
config: certutil.Config{ config: CertConfig{
CommonName: "test", Config: certutil.Config{
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, CommonName: "test",
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
},
}, },
expected: false, expected: false,
}, },
@ -285,7 +304,9 @@ func TestTryLoadCertAndKeyFromDisk(t *testing.T) {
} }
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
caCert, caKey, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) caCert, caKey, err := NewCertificateAuthority(&CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
})
if err != nil { if err != nil {
t.Errorf( t.Errorf(
"failed to create cert and key with an error: %v", "failed to create cert and key with an error: %v",
@ -340,7 +361,9 @@ func TestTryLoadCertFromDisk(t *testing.T) {
} }
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
caCert, _, err := NewCertificateAuthority(&certutil.Config{CommonName: "kubernetes"}) caCert, _, err := NewCertificateAuthority(&CertConfig{
Config: certutil.Config{CommonName: "kubernetes"},
})
if err != nil { if err != nil {
t.Errorf( t.Errorf(
"failed to create cert and key with an error: %v", "failed to create cert and key with an error: %v",

View File

@ -356,6 +356,10 @@ func TestCmdInitFeatureGates(t *testing.T) {
name: "feature gate IPv6DualStack=true", name: "feature gate IPv6DualStack=true",
args: "--feature-gates=IPv6DualStack=true", args: "--feature-gates=IPv6DualStack=true",
}, },
{
name: "feature gate PublicKeysECDSA=true",
args: "--feature-gates=PublicKeysECDSA=true",
},
} }
for _, rt := range initTest { for _, rt := range initTest {