From 528a3d9da8b448a6640149c2b71e452929fe909c Mon Sep 17 00:00:00 2001 From: Roy <62500486+aazf@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:56:36 +0800 Subject: [PATCH 1/5] support create secret, add cert annotations. --- internal/deployer/k8s_secret.go | 56 ++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 3729114f..4ae3e81c 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + corev1 "k8s.io/api/core/v1" k8sMetaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" @@ -43,7 +44,7 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { return err } - d.infos = append(d.infos, toStr("kubeClient 创建成功", nil)) + d.infos = append(d.infos, toStr("kubeClient create success.", nil)) namespace := getDeployString(d.option.DeployConfig, "namespace") if namespace == "" { @@ -65,38 +66,57 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { namespace = "tls.key" } - // 获取 Secret 实例 - secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, k8sMetaV1.GetOptions{}) - if err != nil { - return fmt.Errorf("failed to get k8s secret: %w", err) + secretPayload := corev1.Secret{ + TypeMeta: k8sMetaV1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: k8sMetaV1.ObjectMeta{ + Name: secretName, + Annotations: map[string]string{ + "cert-manager.io/alt-names": d.option.Domain, + "cert-manager.io/common-name": d.option.Domain, + "cert-manager.io/issuer-name": d.option.DeployConfig.Id, + }, + }, + Type: corev1.SecretType("kubernetes.io/tls"), } - // 更新 Secret Data - secret.Data[secretDataKeyForCrt] = []byte(d.option.Certificate.Certificate) - secret.Data[secretDataKeyForKey] = []byte(d.option.Certificate.PrivateKey) - _, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secret, k8sMetaV1.UpdateOptions{}) + secretPayload.Data = make(map[string][]byte) + secretPayload.Data[secretDataKeyForCrt] = []byte(d.option.Certificate.Certificate) + secretPayload.Data[secretDataKeyForKey] = []byte(d.option.Certificate.PrivateKey) + + // 获取 Secret 实例 + _, err = client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, k8sMetaV1.GetOptions{}) + if err != nil { + _, err = client.CoreV1().Secrets(namespace).Create(context.TODO(), &secretPayload, k8sMetaV1.CreateOptions{}) + if err != nil { + return fmt.Errorf("failed to create k8s secret: %w", err) + } else { + d.infos = append(d.infos, toStr("Certificate has been created in K8s Secret", nil)) + return nil + } + } + + // 更新 Secret 实例 + _, err = client.CoreV1().Secrets(namespace).Update(ctx, &secretPayload, k8sMetaV1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update k8s secret: %w", err) } - d.infos = append(d.infos, toStr("证书已更新到 K8s Secret", nil)) + d.infos = append(d.infos, toStr("Certificate has been updated to K8s Secret", nil)) return nil } func (d *K8sSecretDeployer) createClient(access *domain.KubernetesAccess) (*kubernetes.Clientset, error) { - kubeConfig, err := clientcmd.Load([]byte(access.KubeConfig)) + kubeConfig, err := clientcmd.NewClientConfigFromBytes([]byte(access.KubeConfig)) if err != nil { return nil, err } - - clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: ""}, - &clientcmd.ConfigOverrides{CurrentContext: kubeConfig.CurrentContext}, - ) - config, err := clientConfig.ClientConfig() + config, err := kubeConfig.ClientConfig() if err != nil { - return nil, err + panic(err.Error()) } client, err := kubernetes.NewForConfig(config) From 9f6ea410af085fef9a89d5515117deef0c47a69a Mon Sep 17 00:00:00 2001 From: Roy <62500486+aazf@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:05:05 +0700 Subject: [PATCH 2/5] Update k8s_secret.go --- internal/deployer/k8s_secret.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 4ae3e81c..37110992 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -116,7 +116,7 @@ func (d *K8sSecretDeployer) createClient(access *domain.KubernetesAccess) (*kube } config, err := kubeConfig.ClientConfig() if err != nil { - panic(err.Error()) + return nil, err } client, err := kubernetes.NewForConfig(config) From 5411b9cb92e571c4828d93c0e6d6fd3ec661ad83 Mon Sep 17 00:00:00 2001 From: Roy <62500486+aazf@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:06:57 +0700 Subject: [PATCH 3/5] change annotations to certimage. --- internal/deployer/k8s_secret.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 37110992..9009204e 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -74,9 +74,9 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { ObjectMeta: k8sMetaV1.ObjectMeta{ Name: secretName, Annotations: map[string]string{ - "cert-manager.io/alt-names": d.option.Domain, - "cert-manager.io/common-name": d.option.Domain, - "cert-manager.io/issuer-name": d.option.DeployConfig.Id, + "certimage/alt-names": d.option.Domain, + "certimage/common-name": d.option.Domain, + "certimage/issuer-name": d.option.DeployConfig.Id, }, }, Type: corev1.SecretType("kubernetes.io/tls"), From 46dccb176ec27d258e4dcec6afba1e3dbd61d4be Mon Sep 17 00:00:00 2001 From: Roy <62500486+aazf@users.noreply.github.com> Date: Thu, 24 Oct 2024 18:39:18 +0800 Subject: [PATCH 4/5] fix typo, get annotations from cert. --- internal/deployer/k8s_secret.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 9009204e..37063ef6 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -2,9 +2,13 @@ package deployer import ( "context" + "crypto/x509" "encoding/json" + "encoding/pem" "fmt" + "strings" + corev1 "k8s.io/api/core/v1" k8sMetaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -65,6 +69,14 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { if secretDataKeyForKey == "" { namespace = "tls.key" } + block, _ := pem.Decode([]byte(d.option.Certificate.Certificate)) + if block == nil { + return fmt.Errorf("failed to parse certificate PEM") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return fmt.Errorf("failed to parse certificate: " + err.Error()) + } secretPayload := corev1.Secret{ TypeMeta: k8sMetaV1.TypeMeta{ @@ -74,9 +86,10 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { ObjectMeta: k8sMetaV1.ObjectMeta{ Name: secretName, Annotations: map[string]string{ - "certimage/alt-names": d.option.Domain, - "certimage/common-name": d.option.Domain, - "certimage/issuer-name": d.option.DeployConfig.Id, + "certimate/domains": d.option.Domain, + "certimate/alt-names": strings.Join(cert.DNSNames, ","), + "certimate/common-name": cert.Subject.CommonName, + "certimate/issuer-organization": strings.Join(cert.Issuer.Organization, ","), }, }, Type: corev1.SecretType("kubernetes.io/tls"), From e2254faf154d286f33d3a56cbf7319fd934d623e Mon Sep 17 00:00:00 2001 From: yoan <536464346@qq.com> Date: Thu, 24 Oct 2024 20:44:41 +0800 Subject: [PATCH 5/5] Reuse the x509 package --- internal/deployer/k8s_secret.go | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/internal/deployer/k8s_secret.go b/internal/deployer/k8s_secret.go index 37063ef6..89789269 100644 --- a/internal/deployer/k8s_secret.go +++ b/internal/deployer/k8s_secret.go @@ -2,11 +2,8 @@ package deployer import ( "context" - "crypto/x509" "encoding/json" - "encoding/pem" "fmt" - "strings" corev1 "k8s.io/api/core/v1" @@ -15,6 +12,7 @@ import ( "k8s.io/client-go/tools/clientcmd" "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/utils/x509" ) type K8sSecretDeployer struct { @@ -69,13 +67,10 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { if secretDataKeyForKey == "" { namespace = "tls.key" } - block, _ := pem.Decode([]byte(d.option.Certificate.Certificate)) - if block == nil { - return fmt.Errorf("failed to parse certificate PEM") - } - cert, err := x509.ParseCertificate(block.Bytes) + + certificate, err := x509.ParseCertificateFromPEM(d.option.Certificate.Certificate) if err != nil { - return fmt.Errorf("failed to parse certificate: " + err.Error()) + return fmt.Errorf("failed to parse certificate: %w", err) } secretPayload := corev1.Secret{ @@ -87,9 +82,9 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context) error { Name: secretName, Annotations: map[string]string{ "certimate/domains": d.option.Domain, - "certimate/alt-names": strings.Join(cert.DNSNames, ","), - "certimate/common-name": cert.Subject.CommonName, - "certimate/issuer-organization": strings.Join(cert.Issuer.Organization, ","), + "certimate/alt-names": strings.Join(certificate.DNSNames, ","), + "certimate/common-name": certificate.Subject.CommonName, + "certimate/issuer-organization": strings.Join(certificate.Issuer.Organization, ","), }, }, Type: corev1.SecretType("kubernetes.io/tls"),