diff --git a/pkg/karmadactl/cmdinit/cert/cert.go b/pkg/karmadactl/cmdinit/cert/cert.go index 41c66dab9a64..50b38e48f8d8 100644 --- a/pkg/karmadactl/cmdinit/cert/cert.go +++ b/pkg/karmadactl/cmdinit/cert/cert.go @@ -22,6 +22,7 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/rsa" + "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/pem" @@ -261,11 +262,12 @@ func NewCertConfig(cn string, org []string, altNames certutil.AltNames, notAfter } // GenCerts Create CA certificate and sign etcd karmada certificate. -func GenCerts(pkiPath string, etcdServerCertCfg, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg *CertsConfig) error { - caCert, caKey, err := NewCACertAndKey("karmada") +func GenCerts(pkiPath, caCertPath, caKeyPath string, etcdServerCertCfg, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg *CertsConfig) error { + caCert, caKey, err := getCertAndKey(caCertPath, caKeyPath) if err != nil { return err } + if err = WriteCertAndKey(pkiPath, globaloptions.CaCertAndKeyName, caCert, caKey); err != nil { return err } @@ -309,6 +311,27 @@ func GenCerts(pkiPath string, etcdServerCertCfg, etcdClientCertCfg, karmadaCertC return genEtcdCerts(pkiPath, etcdServerCertCfg, etcdClientCertCfg) } +func getCertAndKey(caCertPath, caKeyPath string) (caCert *x509.Certificate, caKey *crypto.Signer, err error) { + if caKeyPath != "" && caCertPath != "" { + certificate, err := tls.LoadX509KeyPair(caCertPath, caKeyPath) + if err != nil { + return nil, nil, err + } + caCert, err = x509.ParseCertificate(certificate.Certificate[0]) + if err != nil { + return nil, nil, err + } + key := certificate.PrivateKey.(crypto.Signer) + caKey = &key + } else { + caCert, caKey, err = NewCACertAndKey("karmada") + if err != nil { + return nil, nil, err + } + } + return caCert, caKey, nil +} + func genEtcdCerts(pkiPath string, etcdServerCertCfg, etcdClientCertCfg *CertsConfig) error { etcdCaCert, etcdCaKey, err := NewCACertAndKey("etcd-ca") if err != nil { diff --git a/pkg/karmadactl/cmdinit/cert/cert_test.go b/pkg/karmadactl/cmdinit/cert/cert_test.go index 750573b92770..e069630dabee 100644 --- a/pkg/karmadactl/cmdinit/cert/cert_test.go +++ b/pkg/karmadactl/cmdinit/cert/cert_test.go @@ -20,6 +20,7 @@ import ( "fmt" "net" "os" + "path/filepath" "testing" "time" @@ -29,11 +30,33 @@ import ( ) const ( - TestCertsTmp = "./test-certs-tmp" + TestCertsTmp = "./test-certs-tmp" + TestCaCertPath = "./test-ca.crt" + TestCaKeyPath = "./test-ca.key" ) +func writeMockCert() { + certData := []byte("-----BEGIN CERTIFICATE-----\nMIIB6TCCAY6gAwIBAgIUQlTeCuvulLnDo9JWIAIJmMQB0jUwCgYIKoZIzj0EAwIw\nQDELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAkdEMQ8wDQYDVQQHEwZGb1NoYW4xEzAR\nBgNVBAMTCkt1YmVybmV0ZXMwHhcNMjQwNTA4MDg1MTAwWhcNMjkwNTA3MDg1MTAw\nWjBAMQswCQYDVQQGEwJDTjELMAkGA1UECBMCR0QxDzANBgNVBAcTBkZvU2hhbjET\nMBEGA1UEAxMKS3ViZXJuZXRlczBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLz2\n4B6I1ymHkD8VYNbYm7J1PkPRKlwIPx1GzFm92EyK5nkNY4mMmIDwTocKM08IBNBB\nnesvfH6ipBqVU95IohCjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgECMB0GA1UdDgQWBBQTkWmoVW9/Cb/bl4rHsCGKJiHbSzAfBgNVHSMEGDAW\ngBQTkWmoVW9/Cb/bl4rHsCGKJiHbSzAKBggqhkjOPQQDAgNJADBGAiEA16jlnBod\nF9Ba4VZ/CGdaROZTaF988AYjYKdgOsun2+0CIQCRkpzQ0+XeSk6qZJ+fwYBdoXUL\nSmz0jaVWUjrO2GsIrw==\n-----END CERTIFICATE-----") + if err := os.MkdirAll(filepath.Dir(TestCaCertPath), os.FileMode(0755)); err != nil { + fmt.Println(err) + } + if err := os.WriteFile(TestCaCertPath, certData, os.FileMode(0644)); err != nil { + fmt.Println(err) + } + keyData := []byte("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIIPimXOHhF5n74QbTprxcvLE/WURZL3w4IuhY6B/LfufoAoGCCqGSM49\nAwEHoUQDQgAEvPbgHojXKYeQPxVg1tibsnU+Q9EqXAg/HUbMWb3YTIrmeQ1jiYyY\ngPBOhwozTwgE0EGd6y98fqKkGpVT3kiiEA==\n-----END EC PRIVATE KEY-----") + if err := os.MkdirAll(filepath.Dir(TestCaKeyPath), os.FileMode(0755)); err != nil { + fmt.Println(err) + } + if err := os.WriteFile(TestCaKeyPath, keyData, os.FileMode(0644)); err != nil { + fmt.Println(err) + } +} + func TestGenCerts(_ *testing.T) { defer os.RemoveAll(TestCertsTmp) + defer os.RemoveAll(TestCaCertPath) + defer os.RemoveAll(TestCaKeyPath) + writeMockCert() notAfter := time.Now().Add(Duration365d * 10).UTC() namespace := "kube-karmada" @@ -101,7 +124,7 @@ func TestGenCerts(_ *testing.T) { apiserverCertCfg := NewCertConfig("karmada-apiserver", []string{""}, karmadaAltNames, ¬After) frontProxyClientCertCfg := NewCertConfig("front-proxy-client", []string{}, certutil.AltNames{}, ¬After) - if err := GenCerts(TestCertsTmp, etcdServerCertConfig, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg); err != nil { + if err := GenCerts(TestCertsTmp, TestCaCertPath, TestCaKeyPath, etcdServerCertConfig, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg); err != nil { fmt.Println(err) } } diff --git a/pkg/karmadactl/cmdinit/cmdinit.go b/pkg/karmadactl/cmdinit/cmdinit.go index ab946f4ec365..9ace6431a74d 100644 --- a/pkg/karmadactl/cmdinit/cmdinit.go +++ b/pkg/karmadactl/cmdinit/cmdinit.go @@ -125,6 +125,8 @@ func NewCmdInit(parentCommand string) *cobra.Command { flags.StringVar(&opts.ExternalIP, "cert-external-ip", "", "the external IP of Karmada certificate (e.g 192.168.1.2,172.16.1.2)") flags.StringVar(&opts.ExternalDNS, "cert-external-dns", "", "the external DNS of Karmada certificate (e.g localhost,localhost.com)") flags.DurationVar(&opts.CertValidity, "cert-validity-period", cert.Duration365d, "the validity period of Karmada certificate (e.g 8760h0m0s, that is 365 days)") + flags.StringVarP(&opts.CaCertPath, "ca-cert-path", "", "", "The path of CA cert, if not set, will gen new, the option must be specified together with ca-key-path") + flags.StringVarP(&opts.CaKeyPath, "ca-key-path", "", "", "The path of CA key, if not set, will gen new, the option must be specified together with ca-cert-path") // Kubernetes flags.StringVarP(&opts.Namespace, "namespace", "n", "karmada-system", "Kubernetes namespace") flags.StringVar(&opts.StorageClassesName, "storage-classes-name", "", "Kubernetes StorageClasses Name") diff --git a/pkg/karmadactl/cmdinit/kubernetes/deploy.go b/pkg/karmadactl/cmdinit/kubernetes/deploy.go index 28d7262ee8d4..a5b437f638aa 100644 --- a/pkg/karmadactl/cmdinit/kubernetes/deploy.go +++ b/pkg/karmadactl/cmdinit/kubernetes/deploy.go @@ -171,6 +171,8 @@ type CommandInitOption struct { KarmadaAPIServerIP []net.IP HostClusterDomain string WaitComponentReadyTimeout int + CaCertPath string + CaKeyPath string } func (i *CommandInitOption) validateLocalEtcd(parentCommand string) error { @@ -353,7 +355,7 @@ func (i *CommandInitOption) genCerts() error { apiserverCertCfg := cert.NewCertConfig("karmada-apiserver", []string{""}, karmadaAltNames, ¬After) frontProxyClientCertCfg := cert.NewCertConfig("front-proxy-client", []string{}, certutil.AltNames{}, ¬After) - if err = cert.GenCerts(i.KarmadaPkiPath, etcdServerCertConfig, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg); err != nil { + if err = cert.GenCerts(i.KarmadaPkiPath, i.CaCertPath, i.CaKeyPath, etcdServerCertConfig, etcdClientCertCfg, karmadaCertCfg, apiserverCertCfg, frontProxyClientCertCfg); err != nil { return err } return nil