diff --git a/src/k8s/pkg/k8sd/app/hooks_start.go b/src/k8s/pkg/k8sd/app/hooks_start.go index 610052180..89df0db1f 100644 --- a/src/k8s/pkg/k8sd/app/hooks_start.go +++ b/src/k8s/pkg/k8sd/app/hooks_start.go @@ -8,9 +8,9 @@ import ( "github.com/canonical/k8s/pkg/k8sd/database" databaseutil "github.com/canonical/k8s/pkg/k8sd/database/util" - "github.com/canonical/k8s/pkg/k8sd/pki" "github.com/canonical/k8s/pkg/k8sd/types" "github.com/canonical/k8s/pkg/utils" + pkiutil "github.com/canonical/k8s/pkg/utils/pki" "github.com/canonical/microcluster/state" ) @@ -26,7 +26,7 @@ func (a *App) onStart(s *state.State) error { return nil, fmt.Errorf("failed to load RSA key from configuration: %w", err) } keyPEM := cfg.Certificates.GetK8sdPublicKey() - key, err := pki.LoadRSAPublicKey(cfg.Certificates.GetK8sdPublicKey()) + key, err := pkiutil.LoadRSAPublicKey(cfg.Certificates.GetK8sdPublicKey()) if err != nil && keyPEM != "" { return nil, fmt.Errorf("failed to load RSA key: %w", err) } diff --git a/src/k8s/pkg/k8sd/controllers/update_node_configuration.go b/src/k8s/pkg/k8sd/controllers/update_node_configuration.go index 12b3eee05..5f1b51a32 100644 --- a/src/k8s/pkg/k8sd/controllers/update_node_configuration.go +++ b/src/k8s/pkg/k8sd/controllers/update_node_configuration.go @@ -7,10 +7,10 @@ import ( "time" "github.com/canonical/k8s/pkg/client/kubernetes" - "github.com/canonical/k8s/pkg/k8sd/pki" "github.com/canonical/k8s/pkg/k8sd/types" "github.com/canonical/k8s/pkg/snap" snaputil "github.com/canonical/k8s/pkg/snap/util" + pkiutil "github.com/canonical/k8s/pkg/utils/pki" ) // UpdateNodeConfigurationController asynchronously performs updates of the cluster config. @@ -98,7 +98,7 @@ func (c *UpdateNodeConfigurationController) Run(ctx context.Context, getClusterC func (c *UpdateNodeConfigurationController) reconcile(ctx context.Context, client *kubernetes.Client, config types.ClusterConfig) error { keyPEM := config.Certificates.GetK8sdPrivateKey() - key, err := pki.LoadRSAPrivateKey(keyPEM) + key, err := pkiutil.LoadRSAPrivateKey(keyPEM) if err != nil && keyPEM != "" { return fmt.Errorf("failed to load cluster RSA key: %w", err) } diff --git a/src/k8s/pkg/k8sd/pki/control_plane.go b/src/k8s/pkg/k8sd/pki/control_plane.go index c842ffa7c..e7444cca2 100644 --- a/src/k8s/pkg/k8sd/pki/control_plane.go +++ b/src/k8s/pkg/k8sd/pki/control_plane.go @@ -4,6 +4,8 @@ import ( "crypto/x509/pkix" "fmt" "net" + + pkiutil "github.com/canonical/k8s/pkg/utils/pki" ) // ControlPlanePKI is a list of all certificates we require for a control plane node. @@ -105,7 +107,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { if !c.allowSelfSignedCA { return fmt.Errorf("kubernetes CA not specified and generating self-signed CA not allowed") } - cert, key, err := generateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca"}, c.years, 2048) + cert, key, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca"}, c.years, 2048) if err != nil { return fmt.Errorf("failed to generate kubernetes CA: %w", err) } @@ -118,7 +120,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { if !c.allowSelfSignedCA { return fmt.Errorf("kubernetes client CA not specified and generating self-signed CA not allowed") } - cert, key, err := generateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca-client"}, c.years, 2048) + cert, key, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca-client"}, c.years, 2048) if err != nil { return fmt.Errorf("failed to generate kubernetes client CA: %w", err) } @@ -126,12 +128,12 @@ func (c *ControlPlanePKI) CompleteCertificates() error { c.ClientCAKey = key } - serverCACert, serverCAKey, err := loadCertificate(c.CACert, c.CAKey) + serverCACert, serverCAKey, err := pkiutil.LoadCertificate(c.CACert, c.CAKey) if err != nil { return fmt.Errorf("failed to parse kubernetes CA: %w", err) } - clientCACert, clientCAKey, err := loadCertificate(c.ClientCACert, c.ClientCAKey) + clientCACert, clientCAKey, err := pkiutil.LoadCertificate(c.ClientCACert, c.ClientCAKey) if err != nil { return fmt.Errorf("failed to parse kubernetes CA: %w", err) } @@ -141,7 +143,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { if !c.allowSelfSignedCA { return fmt.Errorf("front-proxy CA not specified and generating self-signed CA not allowed") } - cert, key, err := generateSelfSignedCA(pkix.Name{CommonName: "front-proxy-ca"}, c.years, 2048) + cert, key, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "front-proxy-ca"}, c.years, 2048) if err != nil { return fmt.Errorf("failed to generate front-proxy CA: %w", err) } @@ -151,7 +153,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { // Generate front proxy client certificate (ok to override) if c.FrontProxyClientCert == "" || c.FrontProxyClientKey == "" { - frontProxyCACert, frontProxyCAKey, err := loadCertificate(c.FrontProxyCACert, c.FrontProxyCAKey) + frontProxyCACert, frontProxyCAKey, err := pkiutil.LoadCertificate(c.FrontProxyCACert, c.FrontProxyCAKey) switch { case err != nil: return fmt.Errorf("failed to parse front proxy CA: %w", err) @@ -159,11 +161,11 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("using an external front proxy CA without providing the front-proxy-client certificate is not possible") } - template, err := generateCertificate(pkix.Name{CommonName: "front-proxy-client"}, c.years, false, nil, nil) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: "front-proxy-client"}, c.years, false, nil, nil) if err != nil { return fmt.Errorf("failed to generate front-proxy-client certificate: %w", err) } - cert, key, err := signCertificate(template, 2048, frontProxyCACert, &frontProxyCAKey.PublicKey, frontProxyCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, frontProxyCACert, &frontProxyCAKey.PublicKey, frontProxyCAKey) if err != nil { return fmt.Errorf("failed to sign front-proxy-client certificate: %w", err) } @@ -178,7 +180,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("service account signing key not specified and generating new key is not allowed") } - key, _, err := generateRSAKey(2048) + key, _, err := pkiutil.GenerateRSAKey(2048) if err != nil { return fmt.Errorf("failed to generate service account key: %w", err) } @@ -192,14 +194,14 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("using an external kubernetes CA without providing the kubelet certificate is not possible") } - template, err := generateCertificate( + template, err := pkiutil.GenerateCertificate( pkix.Name{CommonName: fmt.Sprintf("system:node:%s", c.hostname), Organization: []string{"system:nodes"}}, c.years, false, append(c.dnsSANs, c.hostname), append(c.ipSANs, machineIPs...), ) if err != nil { return fmt.Errorf("failed to generate kubelet certificate: %w", err) } - cert, key, err := signCertificate(template, 2048, serverCACert, &serverCAKey.PublicKey, serverCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, serverCACert, &serverCAKey.PublicKey, serverCAKey) if err != nil { return fmt.Errorf("failed to sign kubelet certificate: %w", err) } @@ -214,11 +216,11 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("using an external kubernetes CA without providing the apiserver-kubelet-client certificate is not possible") } - template, err := generateCertificate(pkix.Name{CommonName: "apiserver-kubelet-client", Organization: []string{"system:masters"}}, c.years, false, nil, nil) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: "apiserver-kubelet-client", Organization: []string{"system:masters"}}, c.years, false, nil, nil) if err != nil { return fmt.Errorf("failed to generate apiserver-kubelet-client certificate: %w", err) } - cert, key, err := signCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) if err != nil { return fmt.Errorf("failed to sign apiserver-kubelet-client certificate: %w", err) } @@ -233,7 +235,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("using an external kubernetes CA without providing the apiserver certificate is not possible") } - template, err := generateCertificate( + template, err := pkiutil.GenerateCertificate( pkix.Name{CommonName: "kube-apiserver"}, c.years, false, @@ -241,7 +243,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { if err != nil { return fmt.Errorf("failed to generate apiserver certificate: %w", err) } - cert, key, err := signCertificate(template, 2048, serverCACert, &serverCAKey.PublicKey, serverCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, serverCACert, &serverCAKey.PublicKey, serverCAKey) if err != nil { return fmt.Errorf("failed to sign apiserver certificate: %w", err) } @@ -268,12 +270,12 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("using an external kubernetes CA client without providing the %s certificate is not possible", i.name) } - template, err := generateCertificate(pkix.Name{CommonName: i.cn, Organization: i.o}, c.years, false, nil, nil) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: i.cn, Organization: i.o}, c.years, false, nil, nil) if err != nil { return fmt.Errorf("failed to generate %s client certificate: %w", i.name, err) } - cert, key, err := signCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) if err != nil { return fmt.Errorf("failed to sign %s client certificate: %w", i.name, err) } @@ -289,7 +291,7 @@ func (c *ControlPlanePKI) CompleteCertificates() error { return fmt.Errorf("cluster keypair not specified and generating new key is not allowed") } - priv, pub, err := generateRSAKey(2048) + priv, pub, err := pkiutil.GenerateRSAKey(2048) if err != nil { return fmt.Errorf("failed to generate cluster keypair: %w", err) } diff --git a/src/k8s/pkg/k8sd/pki/control_plane_test.go b/src/k8s/pkg/k8sd/pki/control_plane_test.go index 6f0416cdb..ec4c8afa3 100644 --- a/src/k8s/pkg/k8sd/pki/control_plane_test.go +++ b/src/k8s/pkg/k8sd/pki/control_plane_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/canonical/k8s/pkg/k8sd/pki" + pkiutil "github.com/canonical/k8s/pkg/utils/pki" . "github.com/onsi/gomega" ) @@ -38,9 +39,9 @@ func TestControlPlaneCertificates(t *testing.T) { t.Run("K8sdKey", func(t *testing.T) { g := NewWithT(t) - priv, err := pki.LoadRSAPrivateKey(c.K8sdPrivateKey) + priv, err := pkiutil.LoadRSAPrivateKey(c.K8sdPrivateKey) g.Expect(err).ToNot(HaveOccurred()) - pub, err := pki.LoadRSAPublicKey(c.K8sdPublicKey) + pub, err := pkiutil.LoadRSAPublicKey(c.K8sdPublicKey) g.Expect(err).ToNot(HaveOccurred()) // generate a hash to sign diff --git a/src/k8s/pkg/k8sd/pki/k8sdqlite.go b/src/k8s/pkg/k8sd/pki/k8sdqlite.go index 80892f250..8a7506411 100644 --- a/src/k8s/pkg/k8sd/pki/k8sdqlite.go +++ b/src/k8s/pkg/k8sd/pki/k8sdqlite.go @@ -4,6 +4,8 @@ import ( "crypto/x509/pkix" "fmt" "net" + + pkiutil "github.com/canonical/k8s/pkg/utils/pki" ) // K8sDqlitePKI is a list of certificates required by the k8s-dqlite datastore. @@ -57,11 +59,11 @@ func (c *K8sDqlitePKI) CompleteCertificates() error { return fmt.Errorf("k8s-dqlite certificate not specified and generating self-signed certificates is not allowed") } - template, err := generateCertificate(pkix.Name{CommonName: "k8s"}, c.years, false, append(c.dnsSANs, c.hostname), append(c.ipSANs, net.IP{127, 0, 0, 1})) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: "k8s"}, c.years, false, append(c.dnsSANs, c.hostname), append(c.ipSANs, net.IP{127, 0, 0, 1})) if err != nil { return fmt.Errorf("failed to generate k8s-dqlite certificate: %w", err) } - cert, key, err := signCertificate(template, 2048, template, nil, nil) + cert, key, err := pkiutil.SignCertificate(template, 2048, template, nil, nil) if err != nil { return fmt.Errorf("failed to self-sign k8s-dqlite certificate: %w", err) } diff --git a/src/k8s/pkg/k8sd/pki/worker.go b/src/k8s/pkg/k8sd/pki/worker.go index 05db0d4f6..bb6e9f40e 100644 --- a/src/k8s/pkg/k8sd/pki/worker.go +++ b/src/k8s/pkg/k8sd/pki/worker.go @@ -4,6 +4,8 @@ import ( "crypto/x509/pkix" "fmt" "net" + + pkiutil "github.com/canonical/k8s/pkg/utils/pki" ) type WorkerNodePKI struct { @@ -23,12 +25,12 @@ type WorkerNodePKI struct { // CompleteWorkerNodePKI generates the PKI needed for a worker node. func (c *ControlPlanePKI) CompleteWorkerNodePKI(hostname string, nodeIP net.IP, bits int) (*WorkerNodePKI, error) { - serverCACert, serverCAKey, err := loadCertificate(c.CACert, c.CAKey) + serverCACert, serverCAKey, err := pkiutil.LoadCertificate(c.CACert, c.CAKey) if err != nil { return nil, fmt.Errorf("failed to load kubernetes CA: %w", err) } - clientCACert, clientCAKey, err := loadCertificate(c.ClientCACert, c.ClientCAKey) + clientCACert, clientCAKey, err := pkiutil.LoadCertificate(c.ClientCACert, c.ClientCAKey) if err != nil { return nil, fmt.Errorf("failed to load kubernetes client CA: %w", err) } @@ -37,11 +39,11 @@ func (c *ControlPlanePKI) CompleteWorkerNodePKI(hostname string, nodeIP net.IP, // we have a cluster CA key, sign the kubelet server certificate if serverCAKey != nil { - template, err := generateCertificate(pkix.Name{CommonName: fmt.Sprintf("system:node:%s", hostname), Organization: []string{"system:nodes"}}, c.years, false, []string{hostname}, []net.IP{{127, 0, 0, 1}, nodeIP}) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: fmt.Sprintf("system:node:%s", hostname), Organization: []string{"system:nodes"}}, c.years, false, []string{hostname}, []net.IP{{127, 0, 0, 1}, nodeIP}) if err != nil { return nil, fmt.Errorf("failed to generate kubelet certificate for hostname=%s address=%s: %w", hostname, nodeIP.String(), err) } - cert, key, err := signCertificate(template, bits, serverCACert, &serverCAKey.PublicKey, serverCAKey) + cert, key, err := pkiutil.SignCertificate(template, bits, serverCACert, &serverCAKey.PublicKey, serverCAKey) if err != nil { return nil, fmt.Errorf("failed to sign kubelet certificate for hostname=%s address=%s: %w", hostname, nodeIP.String(), err) } @@ -62,12 +64,12 @@ func (c *ControlPlanePKI) CompleteWorkerNodePKI(hostname string, nodeIP net.IP, {name: "kubelet", cn: fmt.Sprintf("system:node:%s", hostname), o: []string{"system:nodes"}, cert: &pki.KubeletClientCert, key: &pki.KubeletClientKey}, } { if *i.cert == "" || *i.key == "" { - template, err := generateCertificate(pkix.Name{CommonName: i.cn, Organization: i.o}, c.years, false, nil, nil) + template, err := pkiutil.GenerateCertificate(pkix.Name{CommonName: i.cn, Organization: i.o}, c.years, false, nil, nil) if err != nil { return nil, fmt.Errorf("failed to generate %s client certificate: %w", i.name, err) } - cert, key, err := signCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) + cert, key, err := pkiutil.SignCertificate(template, 2048, clientCACert, &clientCAKey.PublicKey, clientCAKey) if err != nil { return nil, fmt.Errorf("failed to sign %s client certificate: %w", i.name, err) } diff --git a/src/k8s/pkg/k8sd/pki/worker_test.go b/src/k8s/pkg/k8sd/pki/worker_test.go index bbee1efc9..299093435 100644 --- a/src/k8s/pkg/k8sd/pki/worker_test.go +++ b/src/k8s/pkg/k8sd/pki/worker_test.go @@ -1,10 +1,12 @@ -package pki +package pki_test import ( "crypto/x509/pkix" "net" "testing" + "github.com/canonical/k8s/pkg/k8sd/pki" + pkiutil "github.com/canonical/k8s/pkg/utils/pki" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" ) @@ -12,20 +14,20 @@ import ( func TestControlPlanePKI_CompleteWorkerNodePKI(t *testing.T) { g := NewWithT(t) - serverCACert, serverCAKey, err := generateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca"}, 1, 2048) + serverCACert, serverCAKey, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca"}, 1, 2048) g.Expect(err).ToNot(HaveOccurred()) - clientCACert, clientCAKey, err := generateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca-client"}, 1, 2048) + clientCACert, clientCAKey, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "kubernetes-ca-client"}, 1, 2048) g.Expect(err).ToNot(HaveOccurred()) for _, tc := range []struct { name string - withCerts func(*ControlPlanePKI) + withCerts func(*pki.ControlPlanePKI) expectErr bool expectPKITo types.GomegaMatcher }{ { name: "WithCACertAndKeys", - withCerts: func(pki *ControlPlanePKI) { + withCerts: func(pki *pki.ControlPlanePKI) { pki.CACert = serverCACert pki.CAKey = serverCAKey pki.ClientCACert = clientCACert @@ -44,26 +46,26 @@ func TestControlPlanePKI_CompleteWorkerNodePKI(t *testing.T) { }, { name: "WithoutCerts", - withCerts: func(pki *ControlPlanePKI) {}, + withCerts: func(pki *pki.ControlPlanePKI) {}, expectErr: true, }, { name: "WithoutCACert", - withCerts: func(pki *ControlPlanePKI) { + withCerts: func(pki *pki.ControlPlanePKI) { pki.ClientCACert = clientCACert }, expectErr: true, }, { name: "WithoutClientCACert", - withCerts: func(pki *ControlPlanePKI) { + withCerts: func(pki *pki.ControlPlanePKI) { pki.CACert = serverCACert }, expectErr: true, }, { name: "OnlyServerCAKey", - withCerts: func(pki *ControlPlanePKI) { + withCerts: func(pki *pki.ControlPlanePKI) { pki.CACert = serverCACert pki.CAKey = serverCAKey pki.ClientCACert = clientCACert @@ -81,7 +83,7 @@ func TestControlPlanePKI_CompleteWorkerNodePKI(t *testing.T) { }, { name: "OnlyClientCAKey", - withCerts: func(pki *ControlPlanePKI) { + withCerts: func(pki *pki.ControlPlanePKI) { pki.CACert = serverCACert pki.ClientCACert = clientCACert pki.ClientCAKey = clientCAKey @@ -100,7 +102,7 @@ func TestControlPlanePKI_CompleteWorkerNodePKI(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { g := NewWithT(t) - cp := NewControlPlanePKI(ControlPlanePKIOpts{Years: 10}) + cp := pki.NewControlPlanePKI(pki.ControlPlanePKIOpts{Years: 10}) tc.withCerts(cp) pki, err := cp.CompleteWorkerNodePKI("worker", net.IP{10, 0, 0, 1}, 2048) diff --git a/src/k8s/pkg/k8sd/pki/generate.go b/src/k8s/pkg/utils/pki/generate.go similarity index 88% rename from src/k8s/pkg/k8sd/pki/generate.go rename to src/k8s/pkg/utils/pki/generate.go index 674d3d1e0..3fa46c972 100644 --- a/src/k8s/pkg/k8sd/pki/generate.go +++ b/src/k8s/pkg/utils/pki/generate.go @@ -1,4 +1,4 @@ -package pki +package pkiutil import ( "crypto/rand" @@ -12,8 +12,8 @@ import ( "time" ) -// generateSerialNumber returns a random number that can be used for the SerialNumber field in an x509 certificate. -func generateSerialNumber() (*big.Int, error) { +// GenerateSerialNumber returns a random number that can be used for the SerialNumber field in an x509 certificate. +func GenerateSerialNumber() (*big.Int, error) { serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { @@ -22,8 +22,8 @@ func generateSerialNumber() (*big.Int, error) { return serialNumber, nil } -func generateCertificate(subject pkix.Name, years int, ca bool, dnsSANs []string, ipSANs []net.IP) (*x509.Certificate, error) { - serialNumber, err := generateSerialNumber() +func GenerateCertificate(subject pkix.Name, years int, ca bool, dnsSANs []string, ipSANs []net.IP) (*x509.Certificate, error) { + serialNumber, err := GenerateSerialNumber() if err != nil { return nil, fmt.Errorf("failed to generate serial number for certificate template: %w", err) } @@ -49,8 +49,8 @@ func generateCertificate(subject pkix.Name, years int, ca bool, dnsSANs []string return cert, nil } -func generateSelfSignedCA(subject pkix.Name, years int, bits int) (string, string, error) { - cert, err := generateCertificate(subject, years, true, nil, nil) +func GenerateSelfSignedCA(subject pkix.Name, years int, bits int) (string, string, error) { + cert, err := GenerateCertificate(subject, years, true, nil, nil) if err != nil { return "", "", fmt.Errorf("failed to generate certificate: %w", err) } @@ -75,7 +75,7 @@ func generateSelfSignedCA(subject pkix.Name, years int, bits int) (string, strin return string(crtPEM), string(keyPEM), nil } -func signCertificate(certificate *x509.Certificate, bits int, parent *x509.Certificate, pub any, priv any) (string, string, error) { +func SignCertificate(certificate *x509.Certificate, bits int, parent *x509.Certificate, pub any, priv any) (string, string, error) { key, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return "", "", fmt.Errorf("failed to generate RSA private key: %w", err) @@ -102,7 +102,7 @@ func signCertificate(certificate *x509.Certificate, bits int, parent *x509.Certi return string(crtPEM), string(keyPEM), nil } -func generateRSAKey(bits int) (string, string, error) { +func GenerateRSAKey(bits int) (string, string, error) { priv, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return "", "", fmt.Errorf("failed to generate RSA private key: %w", err) diff --git a/src/k8s/pkg/k8sd/pki/generate_test.go b/src/k8s/pkg/utils/pki/generate_test.go similarity index 58% rename from src/k8s/pkg/k8sd/pki/generate_test.go rename to src/k8s/pkg/utils/pki/generate_test.go index 0f8ea17c3..c5ac37361 100644 --- a/src/k8s/pkg/k8sd/pki/generate_test.go +++ b/src/k8s/pkg/utils/pki/generate_test.go @@ -1,14 +1,15 @@ -package pki +package pkiutil_test import ( "crypto/x509/pkix" "testing" + pkiutil "github.com/canonical/k8s/pkg/utils/pki" . "github.com/onsi/gomega" ) -func Test_generateSelfSignedCA(t *testing.T) { - cert, key, err := generateSelfSignedCA(pkix.Name{CommonName: "test-cert"}, 10, 2048) +func TestGenerateSelfSignedCA(t *testing.T) { + cert, key, err := pkiutil.GenerateSelfSignedCA(pkix.Name{CommonName: "test-cert"}, 10, 2048) g := NewWithT(t) g.Expect(err).To(BeNil()) @@ -16,14 +17,14 @@ func Test_generateSelfSignedCA(t *testing.T) { g.Expect(key).ToNot(BeEmpty()) t.Run("Load", func(t *testing.T) { - c, k, err := loadCertificate(cert, key) + c, k, err := pkiutil.LoadCertificate(cert, key) g.Expect(err).To(BeNil()) g.Expect(c).ToNot(BeNil()) g.Expect(k).ToNot(BeNil()) }) t.Run("LoadCertOnly", func(t *testing.T) { - cert, key, err := loadCertificate(cert, "") + cert, key, err := pkiutil.LoadCertificate(cert, "") g.Expect(err).To(BeNil()) g.Expect(cert).ToNot(BeNil()) g.Expect(key).To(BeNil()) diff --git a/src/k8s/pkg/k8sd/pki/load.go b/src/k8s/pkg/utils/pki/load.go similarity index 88% rename from src/k8s/pkg/k8sd/pki/load.go rename to src/k8s/pkg/utils/pki/load.go index 19928e04e..e4bb8fadb 100644 --- a/src/k8s/pkg/k8sd/pki/load.go +++ b/src/k8s/pkg/utils/pki/load.go @@ -1,4 +1,4 @@ -package pki +package pkiutil import ( "crypto/rsa" @@ -7,10 +7,10 @@ import ( "fmt" ) -// loadCertificate parses the PEM blocks and returns the certificate and private key. -// loadCertificate will fail if certPEM is not a valid certificate. -// loadCertificate will return a nil private key if keyPEM is empty, but will fail if it is not valid. -func loadCertificate(certPEM string, keyPEM string) (*x509.Certificate, *rsa.PrivateKey, error) { +// LoadCertificate parses the PEM blocks and returns the certificate and private key. +// LoadCertificate will fail if certPEM is not a valid certificate. +// LoadCertificate will return a nil private key if keyPEM is empty, but will fail if it is not valid. +func LoadCertificate(certPEM string, keyPEM string) (*x509.Certificate, *rsa.PrivateKey, error) { decodedCert, _ := pem.Decode([]byte(certPEM)) if decodedCert == nil { return nil, nil, fmt.Errorf("failed to parse certificate PEM")