mirror of
https://github.com/rancher/rke.git
synced 2025-04-27 03:11:03 +00:00
178 lines
6.4 KiB
Go
178 lines
6.4 KiB
Go
package pki
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"net"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/rancher/rke/docker"
|
|
"github.com/rancher/rke/hosts"
|
|
"github.com/rancher/rke/log"
|
|
v3 "github.com/rancher/rke/types"
|
|
)
|
|
|
|
type CertificatePKI struct {
|
|
Certificate *x509.Certificate `json:"-"`
|
|
Key *rsa.PrivateKey `json:"-"`
|
|
CSR *x509.CertificateRequest `json:"-"`
|
|
CertificatePEM string `json:"certificatePEM"`
|
|
KeyPEM string `json:"keyPEM"`
|
|
CSRPEM string `json:"-"`
|
|
Config string `json:"config"`
|
|
Name string `json:"name"`
|
|
CommonName string `json:"commonName"`
|
|
OUName string `json:"ouName"`
|
|
EnvName string `json:"envName"`
|
|
Path string `json:"path"`
|
|
KeyEnvName string `json:"keyEnvName"`
|
|
KeyPath string `json:"keyPath"`
|
|
ConfigEnvName string `json:"configEnvName"`
|
|
ConfigPath string `json:"configPath"`
|
|
}
|
|
|
|
type GenFunc func(context.Context, map[string]CertificatePKI, v3.RancherKubernetesEngineConfig, string, string, bool) error
|
|
type CSRFunc func(context.Context, map[string]CertificatePKI, v3.RancherKubernetesEngineConfig) error
|
|
|
|
const (
|
|
etcdRole = "etcd"
|
|
controlRole = "controlplane"
|
|
workerRole = "worker"
|
|
BundleCertContainer = "rke-bundle-cert"
|
|
)
|
|
|
|
func GenerateRKECerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineConfig, configPath, configDir string) (map[string]CertificatePKI, error) {
|
|
certs := make(map[string]CertificatePKI)
|
|
// generate RKE CA certificates
|
|
if err := GenerateRKECACerts(ctx, certs, configPath, configDir); err != nil {
|
|
return certs, err
|
|
}
|
|
// Generating certificates for kubernetes components
|
|
if err := GenerateRKEServicesCerts(ctx, certs, rkeConfig, configPath, configDir, false); err != nil {
|
|
return certs, err
|
|
}
|
|
return certs, nil
|
|
}
|
|
|
|
func GenerateRKENodeCerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineConfig, nodeAddress string, certBundle map[string]CertificatePKI) map[string]CertificatePKI {
|
|
crtMap := make(map[string]CertificatePKI)
|
|
crtKeys := []string{}
|
|
for _, node := range rkeConfig.Nodes {
|
|
if node.Address == nodeAddress {
|
|
for _, role := range node.Role {
|
|
keys := getCertKeys(rkeConfig.Nodes, role, &rkeConfig)
|
|
crtKeys = append(crtKeys, keys...)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
for _, key := range crtKeys {
|
|
crtMap[key] = certBundle[key]
|
|
}
|
|
return crtMap
|
|
}
|
|
|
|
func RegenerateEtcdCertificate(
|
|
ctx context.Context,
|
|
crtMap map[string]CertificatePKI,
|
|
etcdHost *hosts.Host,
|
|
etcdHosts []*hosts.Host,
|
|
clusterDomain string,
|
|
KubernetesServiceIP []net.IP) (map[string]CertificatePKI, error) {
|
|
|
|
etcdName := GetCrtNameForHost(etcdHost, EtcdCertName)
|
|
log.Infof(ctx, "[certificates] Regenerating new %s certificate and key", etcdName)
|
|
caCrt := crtMap[CACertName].Certificate
|
|
caKey := crtMap[CACertName].Key
|
|
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, KubernetesServiceIP, []string{})
|
|
|
|
etcdCrt, etcdKey, err := GenerateSignedCertAndKey(caCrt, caKey, true, EtcdCertName, etcdAltNames, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
crtMap[etcdName] = ToCertObject(etcdName, "", "", etcdCrt, etcdKey, nil)
|
|
log.Infof(ctx, "[certificates] Successfully generated new %s certificate and key", etcdName)
|
|
return crtMap, nil
|
|
}
|
|
|
|
func SaveBackupBundleOnHost(ctx context.Context, host *hosts.Host, alpineSystemImage, etcdSnapshotPath string, prsMap map[string]v3.PrivateRegistry) error {
|
|
imageCfg := &container.Config{
|
|
Cmd: []string{
|
|
"sh",
|
|
"-c",
|
|
fmt.Sprintf("if [ -d %s ] && [ \"$(ls -A %s)\" ]; then tar czvf %s %s;fi", TempCertPath, TempCertPath, BundleCertPath, TempCertPath),
|
|
},
|
|
Image: alpineSystemImage,
|
|
}
|
|
hostCfg := &container.HostConfig{
|
|
|
|
Binds: []string{
|
|
fmt.Sprintf("%s:/etc/kubernetes:z", path.Join(host.PrefixPath, "/etc/kubernetes")),
|
|
fmt.Sprintf("%s:/backup:z", etcdSnapshotPath),
|
|
},
|
|
Privileged: true,
|
|
}
|
|
if err := docker.DoRunContainer(ctx, host.DClient, imageCfg, hostCfg, BundleCertContainer, host.Address, "certificates", prsMap); err != nil {
|
|
return err
|
|
}
|
|
status, err := docker.WaitForContainer(ctx, host.DClient, host.Address, BundleCertContainer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if status != 0 {
|
|
return fmt.Errorf("Failed to run certificate bundle compress, exit status is: %d", status)
|
|
}
|
|
log.Infof(ctx, "[certificates] successfully saved certificate bundle [%s/pki.bundle.tar.gz] on host [%s]", etcdSnapshotPath, host.Address)
|
|
return docker.RemoveContainer(ctx, host.DClient, host.Address, BundleCertContainer)
|
|
}
|
|
|
|
func ExtractBackupBundleOnHost(ctx context.Context, host *hosts.Host, alpineSystemImage, etcdSnapshotPath string, prsMap map[string]v3.PrivateRegistry) error {
|
|
imageCfg := &container.Config{
|
|
Cmd: []string{
|
|
"sh",
|
|
"-c",
|
|
fmt.Sprintf(
|
|
"mkdir -p %s; tar xzvf %s -C %s --strip-components %d --exclude %s",
|
|
TempCertPath,
|
|
BundleCertPath,
|
|
TempCertPath,
|
|
len(strings.Split(filepath.Clean(TempCertPath), "/"))-1,
|
|
ClusterStateFile),
|
|
},
|
|
Image: alpineSystemImage,
|
|
}
|
|
hostCfg := &container.HostConfig{
|
|
|
|
Binds: []string{
|
|
fmt.Sprintf("%s:/etc/kubernetes:z", path.Join(host.PrefixPath, "/etc/kubernetes")),
|
|
fmt.Sprintf("%s:/backup:z", etcdSnapshotPath),
|
|
},
|
|
Privileged: true,
|
|
}
|
|
if err := docker.DoRunContainer(ctx, host.DClient, imageCfg, hostCfg, BundleCertContainer, host.Address, "certificates", prsMap); err != nil {
|
|
return err
|
|
}
|
|
status, err := docker.WaitForContainer(ctx, host.DClient, host.Address, BundleCertContainer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if status != 0 {
|
|
containerErrLog, _, err := docker.GetContainerLogsStdoutStderr(ctx, host.DClient, BundleCertContainer, "5", false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// removing the container in case of an error too
|
|
if err := docker.RemoveContainer(ctx, host.DClient, host.Address, BundleCertContainer); err != nil {
|
|
return err
|
|
}
|
|
return fmt.Errorf("Failed to run certificate bundle extract, exit status is: %d, container logs: %s", status, containerErrLog)
|
|
}
|
|
log.Infof(ctx, "[certificates] successfully extracted certificate bundle on host [%s] to backup path [%s]", host.Address, TempCertPath)
|
|
return docker.RemoveContainer(ctx, host.DClient, host.Address, BundleCertContainer)
|
|
}
|