2017-10-31 13:55:35 +00:00
|
|
|
package pki
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/x509"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/rancher/rke/hosts"
|
2017-11-13 21:28:38 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2017-10-31 13:55:35 +00:00
|
|
|
"k8s.io/client-go/util/cert"
|
|
|
|
)
|
|
|
|
|
|
|
|
type CertificatePKI struct {
|
2017-11-10 02:39:10 +00:00
|
|
|
Certificate *x509.Certificate
|
|
|
|
Key *rsa.PrivateKey
|
|
|
|
Config string
|
|
|
|
Name string
|
|
|
|
CommonName string
|
|
|
|
OUName string
|
|
|
|
EnvName string
|
|
|
|
Path string
|
|
|
|
KeyEnvName string
|
|
|
|
KeyPath string
|
|
|
|
ConfigEnvName string
|
|
|
|
ConfigPath string
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// StartCertificatesGeneration ...
|
2017-11-15 01:12:33 +00:00
|
|
|
func StartCertificatesGeneration(cpHosts []hosts.Host, workerHosts []hosts.Host, clusterDomain, localConfigPath string, KubernetesServiceIP net.IP) (map[string]CertificatePKI, error) {
|
2017-10-31 13:55:35 +00:00
|
|
|
logrus.Infof("[certificates] Generating kubernetes certificates")
|
2017-11-15 01:12:33 +00:00
|
|
|
certs, err := generateCerts(cpHosts, clusterDomain, localConfigPath, KubernetesServiceIP)
|
2017-10-31 13:55:35 +00:00
|
|
|
if err != nil {
|
2017-11-02 10:07:10 +00:00
|
|
|
return nil, err
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
2017-11-02 10:07:10 +00:00
|
|
|
return certs, nil
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
2017-11-15 01:12:33 +00:00
|
|
|
func generateCerts(cpHosts []hosts.Host, clusterDomain, localConfigPath string, KubernetesServiceIP net.IP) (map[string]CertificatePKI, error) {
|
2017-10-31 13:55:35 +00:00
|
|
|
certs := make(map[string]CertificatePKI)
|
|
|
|
// generate CA certificate and key
|
|
|
|
logrus.Infof("[certificates] Generating CA kubernetes certificates")
|
|
|
|
caCrt, caKey, err := generateCACertAndKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] CA Certificate: %s", string(cert.EncodeCertPEM(caCrt)))
|
|
|
|
certs[CACertName] = CertificatePKI{
|
2017-11-02 10:07:10 +00:00
|
|
|
Certificate: caCrt,
|
|
|
|
Key: caKey,
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: CACertName,
|
|
|
|
EnvName: CACertENVName,
|
|
|
|
KeyEnvName: CAKeyENVName,
|
|
|
|
Path: CACertPath,
|
|
|
|
KeyPath: CAKeyPath,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// generate API certificate and key
|
|
|
|
logrus.Infof("[certificates] Generating Kubernetes API server certificates")
|
2017-11-21 19:25:08 +00:00
|
|
|
kubeAPIAltNames := GetAltNames(cpHosts, clusterDomain, KubernetesServiceIP)
|
|
|
|
kubeAPICrt, kubeAPIKey, err := GenerateKubeAPICertAndKey(caCrt, caKey, kubeAPIAltNames)
|
2017-10-31 13:55:35 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Kube API Certificate: %s", string(cert.EncodeCertPEM(kubeAPICrt)))
|
|
|
|
certs[KubeAPICertName] = CertificatePKI{
|
2017-11-02 10:07:10 +00:00
|
|
|
Certificate: kubeAPICrt,
|
|
|
|
Key: kubeAPIKey,
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: KubeAPICertName,
|
|
|
|
EnvName: KubeAPICertENVName,
|
|
|
|
KeyEnvName: KubeAPIKeyENVName,
|
|
|
|
Path: KubeAPICertPath,
|
|
|
|
KeyPath: KubeAPIKeyPath,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// generate Kube controller-manager certificate and key
|
|
|
|
logrus.Infof("[certificates] Generating Kube Controller certificates")
|
|
|
|
kubeControllerCrt, kubeControllerKey, err := generateClientCertAndKey(caCrt, caKey, KubeControllerCommonName, []string{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Kube Controller Certificate: %s", string(cert.EncodeCertPEM(kubeControllerCrt)))
|
|
|
|
certs[KubeControllerName] = CertificatePKI{
|
2017-11-10 02:39:10 +00:00
|
|
|
Certificate: kubeControllerCrt,
|
|
|
|
Key: kubeControllerKey,
|
2017-11-15 01:12:33 +00:00
|
|
|
Config: getKubeConfigX509("https://127.0.0.1:6443", KubeControllerName, CACertPath, KubeControllerCertPath, KubeControllerKeyPath),
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: KubeControllerName,
|
|
|
|
CommonName: KubeControllerCommonName,
|
|
|
|
EnvName: KubeControllerCertENVName,
|
|
|
|
KeyEnvName: KubeControllerKeyENVName,
|
|
|
|
Path: KubeControllerCertPath,
|
|
|
|
KeyPath: KubeControllerKeyPath,
|
|
|
|
ConfigEnvName: KubeControllerConfigENVName,
|
|
|
|
ConfigPath: KubeControllerConfigPath,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// generate Kube scheduler certificate and key
|
|
|
|
logrus.Infof("[certificates] Generating Kube Scheduler certificates")
|
|
|
|
kubeSchedulerCrt, kubeSchedulerKey, err := generateClientCertAndKey(caCrt, caKey, KubeSchedulerCommonName, []string{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Kube Scheduler Certificate: %s", string(cert.EncodeCertPEM(kubeSchedulerCrt)))
|
|
|
|
certs[KubeSchedulerName] = CertificatePKI{
|
2017-11-10 02:39:10 +00:00
|
|
|
Certificate: kubeSchedulerCrt,
|
|
|
|
Key: kubeSchedulerKey,
|
2017-11-15 01:12:33 +00:00
|
|
|
Config: getKubeConfigX509("https://127.0.0.1:6443", KubeSchedulerName, CACertPath, KubeSchedulerCertPath, KubeSchedulerKeyPath),
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: KubeSchedulerName,
|
|
|
|
CommonName: KubeSchedulerCommonName,
|
|
|
|
EnvName: KubeSchedulerCertENVName,
|
|
|
|
KeyEnvName: KubeSchedulerKeyENVName,
|
|
|
|
Path: KubeSchedulerCertPath,
|
|
|
|
KeyPath: KubeSchedulerKeyPath,
|
|
|
|
ConfigEnvName: KubeSchedulerConfigENVName,
|
|
|
|
ConfigPath: KubeSchedulerConfigPath,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// generate Kube Proxy certificate and key
|
|
|
|
logrus.Infof("[certificates] Generating Kube Proxy certificates")
|
|
|
|
kubeProxyCrt, kubeProxyKey, err := generateClientCertAndKey(caCrt, caKey, KubeProxyCommonName, []string{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Kube Proxy Certificate: %s", string(cert.EncodeCertPEM(kubeProxyCrt)))
|
|
|
|
certs[KubeProxyName] = CertificatePKI{
|
2017-11-10 02:39:10 +00:00
|
|
|
Certificate: kubeProxyCrt,
|
|
|
|
Key: kubeProxyKey,
|
2017-11-15 01:12:33 +00:00
|
|
|
Config: getKubeConfigX509("https://127.0.0.1:6443", KubeProxyName, CACertPath, KubeProxyCertPath, KubeProxyKeyPath),
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: KubeProxyName,
|
|
|
|
CommonName: KubeProxyCommonName,
|
|
|
|
EnvName: KubeProxyCertENVName,
|
|
|
|
Path: KubeProxyCertPath,
|
|
|
|
KeyEnvName: KubeProxyKeyENVName,
|
|
|
|
KeyPath: KubeProxyKeyPath,
|
|
|
|
ConfigEnvName: KubeProxyConfigENVName,
|
|
|
|
ConfigPath: KubeProxyConfigPath,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
|
2017-11-01 21:46:43 +00:00
|
|
|
// generate Kubelet certificate and key
|
2017-10-31 13:55:35 +00:00
|
|
|
logrus.Infof("[certificates] Generating Node certificate")
|
|
|
|
nodeCrt, nodeKey, err := generateClientCertAndKey(caCrt, caKey, KubeNodeCommonName, []string{KubeNodeOrganizationName})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Node Certificate: %s", string(cert.EncodeCertPEM(kubeProxyCrt)))
|
|
|
|
certs[KubeNodeName] = CertificatePKI{
|
2017-11-10 02:39:10 +00:00
|
|
|
Certificate: nodeCrt,
|
|
|
|
Key: nodeKey,
|
2017-11-15 01:12:33 +00:00
|
|
|
Config: getKubeConfigX509("https://127.0.0.1:6443", KubeNodeName, CACertPath, KubeNodeCertPath, KubeNodeKeyPath),
|
2017-11-10 02:39:10 +00:00
|
|
|
Name: KubeNodeName,
|
|
|
|
CommonName: KubeNodeCommonName,
|
|
|
|
OUName: KubeNodeOrganizationName,
|
|
|
|
EnvName: KubeNodeCertENVName,
|
|
|
|
KeyEnvName: KubeNodeKeyENVName,
|
|
|
|
Path: KubeNodeCertPath,
|
|
|
|
KeyPath: KubeNodeKeyPath,
|
|
|
|
ConfigEnvName: KubeNodeConfigENVName,
|
|
|
|
ConfigPath: KubeNodeCommonName,
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
2017-11-02 10:07:10 +00:00
|
|
|
logrus.Infof("[certificates] Generating admin certificates and kubeconfig")
|
2017-11-01 21:46:43 +00:00
|
|
|
kubeAdminCrt, kubeAdminKey, err := generateClientCertAndKey(caCrt, caKey, KubeAdminCommonName, []string{KubeAdminOrganizationName})
|
|
|
|
if err != nil {
|
2017-11-02 10:07:10 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
logrus.Debugf("[certificates] Admin Certificate: %s", string(cert.EncodeCertPEM(kubeAdminCrt)))
|
|
|
|
certs[KubeAdminCommonName] = CertificatePKI{
|
|
|
|
Certificate: kubeAdminCrt,
|
|
|
|
Key: kubeAdminKey,
|
2017-11-17 00:45:51 +00:00
|
|
|
Config: GetKubeConfigX509WithData(
|
2017-11-02 10:07:10 +00:00
|
|
|
"https://"+cpHosts[0].IP+":6443",
|
|
|
|
KubeAdminCommonName,
|
|
|
|
string(cert.EncodeCertPEM(caCrt)),
|
|
|
|
string(cert.EncodeCertPEM(kubeAdminCrt)),
|
|
|
|
string(cert.EncodePrivateKeyPEM(kubeAdminKey))),
|
2017-11-10 02:39:10 +00:00
|
|
|
CommonName: KubeAdminCommonName,
|
|
|
|
OUName: KubeAdminOrganizationName,
|
|
|
|
ConfigEnvName: KubeAdminConfigENVName,
|
2017-11-15 01:12:33 +00:00
|
|
|
ConfigPath: localConfigPath,
|
2017-11-02 10:07:10 +00:00
|
|
|
}
|
|
|
|
return certs, nil
|
2017-11-01 21:46:43 +00:00
|
|
|
}
|
|
|
|
|
2017-10-31 13:55:35 +00:00
|
|
|
func generateClientCertAndKey(caCrt *x509.Certificate, caKey *rsa.PrivateKey, commonName string, orgs []string) (*x509.Certificate, *rsa.PrivateKey, error) {
|
|
|
|
rootKey, err := cert.NewPrivateKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate private key for %s certificate: %v", commonName, err)
|
|
|
|
}
|
|
|
|
caConfig := cert.Config{
|
|
|
|
CommonName: commonName,
|
|
|
|
Organization: orgs,
|
|
|
|
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
|
|
}
|
|
|
|
clientCert, err := cert.NewSignedCert(caConfig, rootKey, caCrt, caKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate %s certificate: %v", commonName, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return clientCert, rootKey, nil
|
|
|
|
}
|
|
|
|
|
2017-11-21 19:25:08 +00:00
|
|
|
func GenerateKubeAPICertAndKey(caCrt *x509.Certificate, caKey *rsa.PrivateKey, altNames *cert.AltNames) (*x509.Certificate, *rsa.PrivateKey, error) {
|
2017-10-31 13:55:35 +00:00
|
|
|
rootKey, err := cert.NewPrivateKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate private key for kube-apiserver certificate: %v", err)
|
|
|
|
}
|
|
|
|
caConfig := cert.Config{
|
|
|
|
CommonName: KubeAPICertName,
|
|
|
|
Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
|
|
|
AltNames: *altNames,
|
|
|
|
}
|
|
|
|
kubeCACert, err := cert.NewSignedCert(caConfig, rootKey, caCrt, caKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate kube-apiserver certificate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return kubeCACert, rootKey, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateCACertAndKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
|
|
|
rootKey, err := cert.NewPrivateKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate private key for CA certificate: %v", err)
|
|
|
|
}
|
|
|
|
caConfig := cert.Config{
|
|
|
|
CommonName: CACertName,
|
|
|
|
}
|
|
|
|
kubeCACert, err := cert.NewSelfSignedCACert(caConfig, rootKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("Failed to generate CA certificate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return kubeCACert, rootKey, nil
|
|
|
|
}
|
|
|
|
|
2017-11-21 19:25:08 +00:00
|
|
|
func GetAltNames(cpHosts []hosts.Host, clusterDomain string, KubernetesServiceIP net.IP) *cert.AltNames {
|
2017-10-31 13:55:35 +00:00
|
|
|
ips := []net.IP{}
|
|
|
|
dnsNames := []string{}
|
|
|
|
for _, host := range cpHosts {
|
|
|
|
ips = append(ips, net.ParseIP(host.IP))
|
2017-11-02 09:27:26 +00:00
|
|
|
if host.IP != host.AdvertiseAddress {
|
|
|
|
ips = append(ips, net.ParseIP(host.AdvertiseAddress))
|
2017-10-31 11:39:21 +00:00
|
|
|
}
|
2017-11-14 18:11:21 +00:00
|
|
|
dnsNames = append(dnsNames, host.AdvertisedHostname)
|
2017-10-31 13:55:35 +00:00
|
|
|
}
|
|
|
|
ips = append(ips, net.ParseIP("127.0.0.1"))
|
|
|
|
ips = append(ips, KubernetesServiceIP)
|
|
|
|
dnsNames = append(dnsNames, []string{
|
|
|
|
"localhost",
|
|
|
|
"kubernetes",
|
|
|
|
"kubernetes.default",
|
|
|
|
"kubernetes.default.svc",
|
|
|
|
"kubernetes.default.svc." + clusterDomain,
|
|
|
|
}...)
|
|
|
|
return &cert.AltNames{
|
|
|
|
IPs: ips,
|
|
|
|
DNSNames: dnsNames,
|
|
|
|
}
|
|
|
|
}
|
2017-11-10 02:39:10 +00:00
|
|
|
|
|
|
|
func (c *CertificatePKI) ToEnv() []string {
|
|
|
|
env := []string{
|
|
|
|
c.CertToEnv(),
|
|
|
|
c.KeyToEnv(),
|
|
|
|
}
|
|
|
|
if c.Config != "" {
|
|
|
|
env = append(env, c.ConfigToEnv())
|
|
|
|
}
|
|
|
|
return env
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CertificatePKI) CertToEnv() string {
|
|
|
|
encodedCrt := cert.EncodeCertPEM(c.Certificate)
|
|
|
|
return fmt.Sprintf("%s=%s", c.EnvName, string(encodedCrt))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CertificatePKI) KeyToEnv() string {
|
|
|
|
encodedKey := cert.EncodePrivateKeyPEM(c.Key)
|
|
|
|
return fmt.Sprintf("%s=%s", c.KeyEnvName, string(encodedKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CertificatePKI) ConfigToEnv() string {
|
|
|
|
return fmt.Sprintf("%s=%s", c.ConfigEnvName, c.Config)
|
|
|
|
}
|