mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-08 21:49:52 +00:00
137 lines
3.9 KiB
Go
137 lines
3.9 KiB
Go
package deployer
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
xerrors "github.com/pkg/errors"
|
|
k8sCore "k8s.io/api/core/v1"
|
|
k8sMeta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/rest"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
|
|
"github.com/usual2970/certimate/internal/domain"
|
|
"github.com/usual2970/certimate/internal/pkg/utils/x509"
|
|
)
|
|
|
|
type K8sSecretDeployer struct {
|
|
option *DeployerOption
|
|
infos []string
|
|
|
|
k8sClient *kubernetes.Clientset
|
|
}
|
|
|
|
func NewK8sSecretDeployer(option *DeployerOption) (Deployer, error) {
|
|
access := &domain.KubernetesAccess{}
|
|
if err := json.Unmarshal([]byte(option.Access), access); err != nil {
|
|
return nil, xerrors.Wrap(err, "failed to get access")
|
|
}
|
|
|
|
client, err := (&K8sSecretDeployer{}).createK8sClient(access)
|
|
if err != nil {
|
|
return nil, xerrors.Wrap(err, "failed to create k8s client")
|
|
}
|
|
|
|
return &K8sSecretDeployer{
|
|
option: option,
|
|
infos: make([]string, 0),
|
|
k8sClient: client,
|
|
}, nil
|
|
}
|
|
|
|
func (d *K8sSecretDeployer) GetID() string {
|
|
return fmt.Sprintf("%s-%s", d.option.AccessRecord.GetString("name"), d.option.AccessRecord.Id)
|
|
}
|
|
|
|
func (d *K8sSecretDeployer) GetInfos() []string {
|
|
return d.infos
|
|
}
|
|
|
|
func (d *K8sSecretDeployer) Deploy(ctx context.Context) error {
|
|
namespace := d.option.DeployConfig.GetConfigAsString("namespace")
|
|
secretName := d.option.DeployConfig.GetConfigAsString("secretName")
|
|
secretDataKeyForCrt := d.option.DeployConfig.GetConfigOrDefaultAsString("secretDataKeyForCrt", "tls.crt")
|
|
secretDataKeyForKey := d.option.DeployConfig.GetConfigOrDefaultAsString("secretDataKeyForKey", "tls.key")
|
|
if namespace == "" {
|
|
namespace = "default"
|
|
}
|
|
if secretName == "" {
|
|
return errors.New("`secretName` is required")
|
|
}
|
|
|
|
certX509, err := x509.ParseCertificateFromPEM(d.option.Certificate.Certificate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
secretPayload := k8sCore.Secret{
|
|
TypeMeta: k8sMeta.TypeMeta{
|
|
Kind: "Secret",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: k8sMeta.ObjectMeta{
|
|
Name: secretName,
|
|
Annotations: map[string]string{
|
|
"certimate/domains": d.option.Domain,
|
|
"certimate/alt-names": strings.Join(certX509.DNSNames, ","),
|
|
"certimate/common-name": certX509.Subject.CommonName,
|
|
"certimate/issuer-organization": strings.Join(certX509.Issuer.Organization, ","),
|
|
},
|
|
},
|
|
Type: k8sCore.SecretType("kubernetes.io/tls"),
|
|
}
|
|
secretPayload.Data = make(map[string][]byte)
|
|
secretPayload.Data[secretDataKeyForCrt] = []byte(d.option.Certificate.Certificate)
|
|
secretPayload.Data[secretDataKeyForKey] = []byte(d.option.Certificate.PrivateKey)
|
|
|
|
// 获取 Secret 实例
|
|
_, err = d.k8sClient.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, k8sMeta.GetOptions{})
|
|
if err != nil {
|
|
_, err = d.k8sClient.CoreV1().Secrets(namespace).Create(context.TODO(), &secretPayload, k8sMeta.CreateOptions{})
|
|
if err != nil {
|
|
return xerrors.Wrap(err, "failed to create k8s secret")
|
|
} else {
|
|
d.infos = append(d.infos, toStr("Certificate has been created in K8s Secret", nil))
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// 更新 Secret 实例
|
|
_, err = d.k8sClient.CoreV1().Secrets(namespace).Update(context.TODO(), &secretPayload, k8sMeta.UpdateOptions{})
|
|
if err != nil {
|
|
return xerrors.Wrap(err, "failed to update k8s secret")
|
|
}
|
|
|
|
d.infos = append(d.infos, toStr("Certificate has been updated to K8s Secret", nil))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *K8sSecretDeployer) createK8sClient(access *domain.KubernetesAccess) (*kubernetes.Clientset, error) {
|
|
var config *rest.Config
|
|
var err error
|
|
if access.KubeConfig == "" {
|
|
config, err = rest.InClusterConfig()
|
|
} else {
|
|
kubeConfig, err := clientcmd.NewClientConfigFromBytes([]byte(access.KubeConfig))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
config, err = kubeConfig.ClientConfig()
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err := kubernetes.NewForConfig(config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return client, nil
|
|
}
|