diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index 38b7358d48a..60e1f44032d 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -91,6 +91,7 @@ func fuzzClusterConfiguration(obj *kubeadm.ClusterConfiguration, c fuzz.Continue obj.APIServer.ExtraEnvs = []kubeadm.EnvVar{} obj.Scheduler.ExtraEnvs = []kubeadm.EnvVar{} obj.Etcd.Local.ExtraEnvs = []kubeadm.EnvVar{} + obj.EncryptionAlgorithm = kubeadm.EncryptionAlgorithmRSA } func fuzzDNS(obj *kubeadm.DNS, c fuzz.Continue) { diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index 8b845239173..9a157b79f2c 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -17,8 +17,6 @@ limitations under the License. package kubeadm import ( - "crypto/x509" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -141,6 +139,10 @@ type ClusterConfiguration struct { // The cluster name ClusterName string + + // EncryptionAlgorithm holds the type of asymmetric encryption algorithm used for keys and certificates. + // Can be "RSA" (default algorithm, key size is 2048) or "ECDSA" (uses the P-256 eliptic curve). + EncryptionAlgorithm EncryptionAlgorithmType } // ControlPlaneComponent holds settings common to control plane component of the cluster @@ -403,13 +405,18 @@ func (cfg *ClusterConfiguration) GetControlPlaneImageRepository() string { 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 +// EncryptionAlgorithmType returns the type of encryption keys used in the cluster. +func (cfg *ClusterConfiguration) EncryptionAlgorithmType() EncryptionAlgorithmType { + // If the feature gate is set to true, or false respect it. + // If the feature gate is not set, use the EncryptionAlgorithm field (v1beta4). + // TODO: remove this function when the feature gate is removed. + if enabled, ok := cfg.FeatureGates[features.PublicKeysECDSA]; ok { + if enabled { + return EncryptionAlgorithmECDSA + } + return EncryptionAlgorithmRSA } - - return x509.RSA + return cfg.EncryptionAlgorithm } // HostPathMount contains elements describing volumes that are mounted from the @@ -518,3 +525,13 @@ type Arg struct { type EnvVar struct { v1.EnvVar } + +// EncryptionAlgorithmType can define an asymmetric encryption algorithm type. +type EncryptionAlgorithmType string + +const ( + // EncryptionAlgorithmECDSA defines the ECDSA encryption algorithm type. + EncryptionAlgorithmECDSA EncryptionAlgorithmType = "ECDSA" + // EncryptionAlgorithmRSA defines the RSA encryption algorithm type. + EncryptionAlgorithmRSA EncryptionAlgorithmType = "RSA" +) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go index 7114c938778..840ea16ab28 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go @@ -38,9 +38,26 @@ func Convert_v1beta3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConf return err } err = Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(&ClusterConfiguration{}, &out.ClusterConfiguration, s) + // Required to pass fuzzer tests. This ClusterConfiguration is empty and is never defaulted. + // If we call Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration() it will receive + // a default value, thus here we need to reset it back to "". + out.EncryptionAlgorithm = "" return err } +// Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration is required due to missing EncryptionAlgorithm in v1beta3. +func Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error { + return autoConvert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in, out, s) +} + +// Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration is required due to missing EncryptionAlgorithm in v1beta3. +func Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error { + // Required to pass validation and fuzzer tests. The field is missing in v1beta3, thus we have to + // default it to a sane (default) value in the internal type. + out.EncryptionAlgorithm = kubeadm.EncryptionAlgorithmRSA + return autoConvert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s) +} + // Convert_v1beta3_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent is required due to the missing ControlPlaneComponent.ExtraEnvs in v1beta3. func Convert_v1beta3_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error { out.ExtraEnvs = []kubeadm.EnvVar{} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go index 7eb0fdf209b..95abd68c4a2 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go @@ -69,16 +69,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*DNS)(nil), (*kubeadm.DNS)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta3_DNS_To_kubeadm_DNS(a.(*DNS), b.(*kubeadm.DNS), scope) }); err != nil { @@ -184,6 +174,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*kubeadm.ControlPlaneComponent)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_kubeadm_ControlPlaneComponent_To_v1beta3_ControlPlaneComponent(a.(*kubeadm.ControlPlaneComponent), b.(*ControlPlaneComponent), scope) }); err != nil { @@ -209,6 +204,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*kubeadm.ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta3_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(a.(*ControlPlaneComponent), b.(*kubeadm.ControlPlaneComponent), scope) }); err != nil { @@ -336,11 +336,6 @@ func autoConvert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in return nil } -// Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration is an autogenerated conversion function. -func Convert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error { - return autoConvert_v1beta3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s) -} - func autoConvert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error { // INFO: in.ComponentConfigs opted out of conversion generation if err := Convert_kubeadm_Etcd_To_v1beta3_Etcd(&in.Etcd, &out.Etcd, s); err != nil { @@ -369,14 +364,10 @@ func autoConvert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in // INFO: in.CIImageRepository opted out of conversion generation out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) out.ClusterName = in.ClusterName + // WARNING: in.EncryptionAlgorithm requires manual conversion: does not exist in peer-type return nil } -// Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration is an autogenerated conversion function. -func Convert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error { - return autoConvert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in, out, s) -} - func autoConvert_v1beta3_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error { // WARNING: in.ExtraArgs requires manual conversion: inconvertible types (map[string]string vs []k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm.Arg) out.ExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/defaults.go index 53433863cdf..69484f526d1 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/defaults.go @@ -60,6 +60,9 @@ const ( // DefaultImagePullPolicy is the default image pull policy in kubeadm DefaultImagePullPolicy = corev1.PullIfNotPresent + + // DefaultEncryptionAlgorithm is the default encryption algorithm. + DefaultEncryptionAlgorithm = EncryptionAlgorithmRSA ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -99,6 +102,10 @@ func SetDefaults_ClusterConfiguration(obj *ClusterConfiguration) { obj.ClusterName = DefaultClusterName } + if obj.EncryptionAlgorithm == "" { + obj.EncryptionAlgorithm = DefaultEncryptionAlgorithm + } + SetDefaults_Etcd(obj) SetDefaults_APIServer(&obj.APIServer) } diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go index 511d946e72c..602a72e57c5 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go @@ -32,6 +32,9 @@ limitations under the License. // - Replace the existing string/string extra argument maps with structured extra arguments that support duplicates. // The change applies to `ClusterConfiguration` - `APIServer.ExtraArgs, `ControllerManager.ExtraArgs`, // `Scheduler.ExtraArgs`, `Etcd.Local.ExtraArgs`. Also to `NodeRegistrationOptions.KubeletExtraArgs`. +// - Add `ClusterConfiguration.EncryptionAlgorithm` that can be used to set the asymmetric encryption algorithm +// used for this cluster's keys and certificates. Can be "RSA" (default algorithm, key size is 2048) or +// "ECDSA" (uses the P-256 eliptic curve). // // Migration from old kubeadm config versions // diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go index 8008d3b54d6..269912c012b 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go @@ -140,6 +140,11 @@ type ClusterConfiguration struct { // The cluster name // +optional ClusterName string `json:"clusterName,omitempty"` + + // EncryptionAlgorithm holds the type of asymmetric encryption algorithm used for keys and certificates. + // Can be "RSA" (default algorithm, key size is 2048) or "ECDSA" (uses the P-256 eliptic curve). + // +optional + EncryptionAlgorithm EncryptionAlgorithmType `json:"encryptionAlgorithm,omitempty"` } // ControlPlaneComponent holds settings common to control plane component of the cluster @@ -513,3 +518,13 @@ type Arg struct { type EnvVar struct { corev1.EnvVar `json:",inline"` } + +// EncryptionAlgorithmType can define an asymmetric encryption algorithm type. +type EncryptionAlgorithmType string + +const ( + // EncryptionAlgorithmECDSA defines the ECDSA encryption algorithm type. + EncryptionAlgorithmECDSA EncryptionAlgorithmType = "ECDSA" + // EncryptionAlgorithmRSA defines the RSA encryption algorithm type. + EncryptionAlgorithmRSA EncryptionAlgorithmType = "RSA" +) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go index 67bebb9bd95..ed01f88d9f6 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go @@ -385,6 +385,7 @@ func autoConvert_v1beta4_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in out.ImageRepository = in.ImageRepository out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) out.ClusterName = in.ClusterName + out.EncryptionAlgorithm = kubeadm.EncryptionAlgorithmType(in.EncryptionAlgorithm) return nil } @@ -421,6 +422,7 @@ func autoConvert_kubeadm_ClusterConfiguration_To_v1beta4_ClusterConfiguration(in // INFO: in.CIImageRepository opted out of conversion generation out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) out.ClusterName = in.ClusterName + out.EncryptionAlgorithm = EncryptionAlgorithmType(in.EncryptionAlgorithm) return nil } diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index 23c0590d7c3..a8e1c625f83 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -72,6 +72,7 @@ func ValidateClusterConfiguration(c *kubeadm.ClusterConfiguration) field.ErrorLi allErrs = append(allErrs, ValidateHostPort(c.ControlPlaneEndpoint, field.NewPath("controlPlaneEndpoint"))...) allErrs = append(allErrs, ValidateImageRepository(c.ImageRepository, field.NewPath("imageRepository"))...) allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...) + allErrs = append(allErrs, ValidateEncryptionAlgorithm(string(c.EncryptionAlgorithm), field.NewPath("encryptionAlgorithm"))...) allErrs = append(allErrs, componentconfigs.Validate(c)...) return allErrs } @@ -337,6 +338,17 @@ func ValidateEtcd(e *kubeadm.Etcd, fldPath *field.Path) field.ErrorList { return allErrs } +// ValidateEncryptionAlgorithm validates the public key algorithm +func ValidateEncryptionAlgorithm(algo string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + if algo != string(kubeadm.EncryptionAlgorithmRSA) && algo != string(kubeadm.EncryptionAlgorithmECDSA) { + msg := fmt.Sprintf("Invalid encryption algorithm. Must be %q or %q", + kubeadm.EncryptionAlgorithmRSA, kubeadm.EncryptionAlgorithmECDSA) + allErrs = append(allErrs, field.Invalid(fldPath, algo, msg)) + } + return allErrs +} + // ValidateCertSANs validates alternative names func ValidateCertSANs(altnames []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index c6ddf38e72b..32ffe5a2320 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -513,7 +513,8 @@ func TestValidateInitConfiguration(t *testing.T) { ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", + CertificatesDir: "/some/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }, NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodename, CRISocket: criPath}, }, false}, @@ -528,7 +529,8 @@ func TestValidateInitConfiguration(t *testing.T) { ServiceSubnet: "2001:db8::1/98", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/cert/dir", + CertificatesDir: "/some/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }, NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodename, CRISocket: criPath}, }, false}, @@ -543,7 +545,8 @@ func TestValidateInitConfiguration(t *testing.T) { ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/other/cert/dir", + CertificatesDir: "/some/other/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }, }, false}, {"valid InitConfiguration with incorrect IPv4 pod subnet", @@ -558,7 +561,8 @@ func TestValidateInitConfiguration(t *testing.T) { DNSDomain: "cluster.local", PodSubnet: "10.0.1.15", }, - CertificatesDir: "/some/other/cert/dir", + CertificatesDir: "/some/other/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }, NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodename, CRISocket: criPath}, }, false}, @@ -580,7 +584,8 @@ func TestValidateInitConfiguration(t *testing.T) { DNSDomain: "cluster.local", PodSubnet: "10.0.1.15/16", }, - CertificatesDir: "/some/other/cert/dir", + CertificatesDir: "/some/other/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }, NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodename, CRISocket: criPath}, }, true}, @@ -601,7 +606,8 @@ func TestValidateInitConfiguration(t *testing.T) { ServiceSubnet: "2001:db8::1/112", DNSDomain: "cluster.local", }, - CertificatesDir: "/some/other/cert/dir", + CertificatesDir: "/some/other/cert/dir", + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmECDSA, }, NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: nodename, CRISocket: criPath}, }, true}, @@ -1187,6 +1193,26 @@ func TestValidateEtcd(t *testing.T) { } } +func TestValidateEncryptionAlgorithm(t *testing.T) { + var tests = []struct { + name string + algo string + expectedErrors bool + }{ + {name: "valid RSA", algo: string(kubeadmapi.EncryptionAlgorithmRSA), expectedErrors: false}, + {name: "valid ECDSA", algo: string(kubeadmapi.EncryptionAlgorithmECDSA), expectedErrors: false}, + {name: "invalid algorithm", algo: "foo", expectedErrors: true}, + {name: "empty algorithm returns an error", algo: "", expectedErrors: true}, + } + for _, tc := range tests { + actual := ValidateEncryptionAlgorithm(tc.algo, field.NewPath("encryptionAlgorithm")) + actualErrors := len(actual) > 0 + if actualErrors != tc.expectedErrors { + t.Errorf("error: validate public key algorithm: %q\n\texpected: %t\n\t actual: %t", tc.algo, tc.expectedErrors, actualErrors) + } + } +} + func TestGetClusterNodeMask(t *testing.T) { tests := []struct { name string diff --git a/cmd/kubeadm/app/cmd/phases/init/certs.go b/cmd/kubeadm/app/cmd/phases/init/certs.go index 5d2ef1cc100..b499819dcf9 100644 --- a/cmd/kubeadm/app/cmd/phases/init/certs.go +++ b/cmd/kubeadm/app/cmd/phases/init/certs.go @@ -188,7 +188,7 @@ func runCertsSa(c workflow.RunData) error { } // create the new service account key (or use existing) - return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(data.CertificateWriteDir(), data.Cfg().ClusterConfiguration.PublicKeyAlgorithm()) + return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(data.CertificateWriteDir(), data.Cfg().ClusterConfiguration.EncryptionAlgorithmType()) } func runCerts(c workflow.RunData) error { diff --git a/cmd/kubeadm/app/features/features.go b/cmd/kubeadm/app/features/features.go index 5c007a708d4..5aa63424774 100644 --- a/cmd/kubeadm/app/features/features.go +++ b/cmd/kubeadm/app/features/features.go @@ -42,7 +42,10 @@ const ( // InitFeatureGates are the default feature gates for the init command var InitFeatureGates = FeatureList{ - PublicKeysECDSA: {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Alpha}}, + PublicKeysECDSA: { + FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Deprecated}, + DeprecationMessage: "The PublicKeysECDSA feature gate is deprecated and will be removed after the feature 'ClusterConfiguration.EncryptionAlgorithm' is added.", + }, RootlessControlPlane: {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Alpha}}, EtcdLearnerMode: {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Beta}}, UpgradeAddonsBeforeControlPlane: { diff --git a/cmd/kubeadm/app/phases/certs/certlist.go b/cmd/kubeadm/app/phases/certs/certlist.go index 177d8224123..8c5d04665e3 100644 --- a/cmd/kubeadm/app/phases/certs/certlist.go +++ b/cmd/kubeadm/app/phases/certs/certlist.go @@ -60,7 +60,7 @@ func (k *KubeadmCert) GetConfig(ic *kubeadmapi.InitConfiguration) (*pkiutil.Cert } } - k.config.PublicKeyAlgorithm = ic.ClusterConfiguration.PublicKeyAlgorithm() + k.config.EncryptionAlgorithm = ic.ClusterConfiguration.EncryptionAlgorithmType() return &k.config, nil } diff --git a/cmd/kubeadm/app/phases/certs/certs.go b/cmd/kubeadm/app/phases/certs/certs.go index 7c823960fe5..ea4d34528c0 100644 --- a/cmd/kubeadm/app/phases/certs/certs.go +++ b/cmd/kubeadm/app/phases/certs/certs.go @@ -69,12 +69,12 @@ func CreatePKIAssets(cfg *kubeadmapi.InitConfiguration) error { fmt.Printf("[certs] Valid certificates and keys now exist in %q\n", cfg.CertificatesDir) // Service accounts are not x509 certs, so handled separately - return CreateServiceAccountKeyAndPublicKeyFiles(cfg.CertificatesDir, cfg.ClusterConfiguration.PublicKeyAlgorithm()) + return CreateServiceAccountKeyAndPublicKeyFiles(cfg.CertificatesDir, cfg.ClusterConfiguration.EncryptionAlgorithmType()) } // 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. -func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string, keyType x509.PublicKeyAlgorithm) error { +func CreateServiceAccountKeyAndPublicKeyFiles(certsDir string, keyType kubeadmapi.EncryptionAlgorithmType) error { klog.V(1).Infoln("creating new public/private key files for signing service account users") _, err := keyutil.PrivateKeyFromFile(filepath.Join(certsDir, kubeadmconstants.ServiceAccountPrivateKeyName)) if err == nil { diff --git a/cmd/kubeadm/app/phases/certs/certs_test.go b/cmd/kubeadm/app/phases/certs/certs_test.go index a399551432b..755ff124ac8 100644 --- a/cmd/kubeadm/app/phases/certs/certs_test.go +++ b/cmd/kubeadm/app/phases/certs/certs_test.go @@ -347,7 +347,7 @@ func TestCreateServiceAccountKeyAndPublicKeyFiles(t *testing.T) { } } - err := CreateServiceAccountKeyAndPublicKeyFiles(dir, x509.RSA) + err := CreateServiceAccountKeyAndPublicKeyFiles(dir, kubeadmapi.EncryptionAlgorithmRSA) if (err != nil) != tt.expectedErr { t.Fatalf("expected error: %v, got: %v, error: %v", tt.expectedErr, err != nil, err) } else if tt.expectedErr { diff --git a/cmd/kubeadm/app/phases/certs/renewal/manager.go b/cmd/kubeadm/app/phases/certs/renewal/manager.go index 764bcb01a80..d7c420c45fd 100644 --- a/cmd/kubeadm/app/phases/certs/renewal/manager.go +++ b/cmd/kubeadm/app/phases/certs/renewal/manager.go @@ -227,8 +227,8 @@ func (rm *Manager) RenewUsingLocalCA(name string) (bool, error) { // extract the certificate config cfg := &pkiutil.CertConfig{ - Config: certToConfig(cert), - PublicKeyAlgorithm: rm.cfg.PublicKeyAlgorithm(), + Config: certToConfig(cert), + EncryptionAlgorithm: rm.cfg.EncryptionAlgorithmType(), } // reads the CA @@ -270,8 +270,8 @@ func (rm *Manager) CreateRenewCSR(name, outdir string) error { // extracts the certificate config cfg := &pkiutil.CertConfig{ - Config: certToConfig(cert), - PublicKeyAlgorithm: rm.cfg.PublicKeyAlgorithm(), + Config: certToConfig(cert), + EncryptionAlgorithm: rm.cfg.EncryptionAlgorithmType(), } // generates the CSR request and save it diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go index eeac15bb958..af25d7cac3f 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go @@ -482,7 +482,7 @@ func createKubeConfigAndCSR(kubeConfigDir string, kubeadmConfig *kubeadmapi.Init clientCertConfig := newClientCertConfigFromKubeConfigSpec(spec, nil) - clientKey, err := pkiutil.NewPrivateKey(clientCertConfig.PublicKeyAlgorithm) + clientKey, err := pkiutil.NewPrivateKey(clientCertConfig.EncryptionAlgorithm) if err != nil { return err } diff --git a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go index dc78d1b3f6b..cba7a41c7b9 100644 --- a/cmd/kubeadm/app/util/pkiutil/pki_helpers.go +++ b/cmd/kubeadm/app/util/pkiutil/pki_helpers.go @@ -60,16 +60,16 @@ const ( rsaKeySize = 2048 ) -// CertConfig is a wrapper around certutil.Config extending it with PublicKeyAlgorithm. +// CertConfig is a wrapper around certutil.Config extending it with EncryptionAlgorithm. type CertConfig struct { certutil.Config - NotAfter *time.Time - PublicKeyAlgorithm x509.PublicKeyAlgorithm + NotAfter *time.Time + EncryptionAlgorithm kubeadmapi.EncryptionAlgorithmType } // NewCertificateAuthority creates new certificate and private key for the certificate authority func NewCertificateAuthority(config *CertConfig) (*x509.Certificate, crypto.Signer, error) { - key, err := NewPrivateKey(config.PublicKeyAlgorithm) + key, err := NewPrivateKey(config.EncryptionAlgorithm) if err != nil { return nil, nil, errors.Wrap(err, "unable to create private key while generating CA certificate") } @@ -86,7 +86,7 @@ func NewCertificateAuthority(config *CertConfig) (*x509.Certificate, crypto.Sign // NewIntermediateCertificateAuthority creates new certificate and private key for an intermediate certificate authority func NewIntermediateCertificateAuthority(parentCert *x509.Certificate, parentKey crypto.Signer, config *CertConfig) (*x509.Certificate, crypto.Signer, error) { - key, err := NewPrivateKey(config.PublicKeyAlgorithm) + key, err := NewPrivateKey(config.EncryptionAlgorithm) if err != nil { return nil, nil, errors.Wrap(err, "unable to create private key while generating intermediate CA certificate") } @@ -105,7 +105,7 @@ func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *CertCo return nil, nil, errors.New("must specify at least one ExtKeyUsage") } - key, err := NewPrivateKey(config.PublicKeyAlgorithm) + key, err := NewPrivateKey(config.EncryptionAlgorithm) if err != nil { return nil, nil, errors.Wrap(err, "unable to create private key") } @@ -120,7 +120,7 @@ func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *CertCo // NewCSRAndKey generates a new key and CSR and that could be signed to create the given certificate func NewCSRAndKey(config *CertConfig) (*x509.CertificateRequest, crypto.Signer, error) { - key, err := NewPrivateKey(config.PublicKeyAlgorithm) + key, err := NewPrivateKey(config.EncryptionAlgorithm) if err != nil { return nil, nil, errors.Wrap(err, "unable to create private key") } @@ -623,8 +623,8 @@ func EncodePublicKeyPEM(key crypto.PublicKey) ([]byte, error) { // NewPrivateKey returns a new private key. var NewPrivateKey = GeneratePrivateKey -func GeneratePrivateKey(keyType x509.PublicKeyAlgorithm) (crypto.Signer, error) { - if keyType == x509.ECDSA { +func GeneratePrivateKey(keyType kubeadmapi.EncryptionAlgorithmType) (crypto.Signer, error) { + if keyType == kubeadmapi.EncryptionAlgorithmECDSA { return ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader) } diff --git a/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go b/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go index 9a4590814be..4b17b336104 100644 --- a/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go +++ b/cmd/kubeadm/app/util/pkiutil/pki_helpers_test.go @@ -52,7 +52,7 @@ func TestMain(m *testing.M) { Config: certutil.Config{ CommonName: "Root CA 1", }, - PublicKeyAlgorithm: x509.RSA, + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmRSA, }) if err != nil { panic(fmt.Sprintf("Failed generating Root CA: %v", err)) @@ -112,7 +112,7 @@ func TestHasServerAuth(t *testing.T) { // Override NewPrivateKey to reuse the same key for all certs // since this test is only checking cert.ExtKeyUsage privateKeyFunc := NewPrivateKey - NewPrivateKey = func(x509.PublicKeyAlgorithm) (crypto.Signer, error) { + NewPrivateKey = func(kubeadmapi.EncryptionAlgorithmType) (crypto.Signer, error) { return rootCAKey, nil } defer func() { @@ -141,7 +141,7 @@ func TestHasServerAuth(t *testing.T) { CommonName: "test", Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, }, - PublicKeyAlgorithm: x509.ECDSA, + EncryptionAlgorithm: kubeadmapi.EncryptionAlgorithmECDSA, }, expected: true, }, diff --git a/cmd/kubeadm/app/util/pkiutil/testing/testing.go b/cmd/kubeadm/app/util/pkiutil/testing/testing.go index 6ddd9434323..588aaacaef9 100644 --- a/cmd/kubeadm/app/util/pkiutil/testing/testing.go +++ b/cmd/kubeadm/app/util/pkiutil/testing/testing.go @@ -18,7 +18,6 @@ package testing import ( "crypto" - "crypto/x509" "fmt" "os" "path/filepath" @@ -29,6 +28,7 @@ import ( "sync" "testing" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil" ) @@ -75,7 +75,7 @@ func install() (cleanup func()) { } } -func newPrivateKey(keyType x509.PublicKeyAlgorithm) (crypto.Signer, error) { +func newPrivateKey(keyType kubeadmapi.EncryptionAlgorithmType) (crypto.Signer, error) { lock.Lock() defer lock.Unlock() @@ -108,7 +108,7 @@ func newPrivateKey(keyType x509.PublicKeyAlgorithm) (crypto.Signer, error) { keyName := "" switch keyType { - case x509.ECDSA: + case kubeadmapi.EncryptionAlgorithmECDSA: ecdsa++ keyName = fmt.Sprintf("%d.ecdsa", ecdsa) default: