diff --git a/.gitignore b/.gitignore index 81d1b990..36d5f731 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /dist *.swp /.trash-cache +admin.config diff --git a/pki/constants.go b/pki/constants.go index c7f7b784..301ffd1b 100644 --- a/pki/constants.go +++ b/pki/constants.go @@ -52,4 +52,8 @@ const ( KubeNodeCertPath = "/etc/kubernetes/ssl/kube-node.pem" KubeNodeKeyPath = "/etc/kubernetes/ssl/kube-node-key.pem" KubeNodeConfigPath = "/etc/kubernetes/ssl/kubecfg-kube-node.yaml" + + KubeAdminCommonName = "kube-admin" + KubeAdminOrganizationName = "system:masters" + KubeAdminConfigPath = "admin.config" ) diff --git a/pki/deploy.go b/pki/deploy.go index 97f2f218..78e9e3e8 100644 --- a/pki/deploy.go +++ b/pki/deploy.go @@ -5,6 +5,8 @@ import ( "crypto/rsa" "crypto/x509" "fmt" + "io/ioutil" + "os" "time" "github.com/Sirupsen/logrus" @@ -127,3 +129,14 @@ func doRunDeployer(host *hosts.Host, containerEnv []string) error { return nil } } + +func deployAdminConfig(kubeConfig string, forceDeploy bool) error { + logrus.Debugf("Deploying admin Kubeconfig locally: %s", kubeConfig) + if _, err := os.Stat(KubeAdminConfigPath); os.IsNotExist(err) || forceDeploy { + err := ioutil.WriteFile(KubeAdminConfigPath, []byte(kubeConfig), 0644) + if err != nil { + return fmt.Errorf("Failed to create local admin kubeconfig file: %v", err) + } + } + return nil +} diff --git a/pki/kubeconfig.go b/pki/kubeconfig.go index 708c1fba..8140d21e 100644 --- a/pki/kubeconfig.go +++ b/pki/kubeconfig.go @@ -1,5 +1,7 @@ package pki +import "encoding/base64" + func getKubeConfigX509(kubernetesURL string, componentName string, caPath string, crtPath string, keyPath string) string { return `apiVersion: v1 kind: Config @@ -21,3 +23,25 @@ users: client-certificate: ` + crtPath + ` client-key: ` + keyPath + `` } + +func getKubeConfigX509WithData(kubernetesURL string, componentName string, cacrt string, crt string, key string) string { + return `apiVersion: v1 +kind: Config +clusters: +- cluster: + api-version: v1 + certificate-authority-data: ` + base64.StdEncoding.EncodeToString([]byte(cacrt)) + ` + server: "` + kubernetesURL + `" + name: "local" +contexts: +- context: + cluster: "local" + user: "` + componentName + `" + name: "Default" +current-context: "Default" +users: +- name: "` + componentName + `" + user: + client-certificate-data: ` + base64.StdEncoding.EncodeToString([]byte(crt)) + ` + client-key-data: ` + base64.StdEncoding.EncodeToString([]byte(key)) + `` +} diff --git a/pki/pki.go b/pki/pki.go index c0ee07ee..746ad6c0 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -26,6 +26,11 @@ func StartCertificatesGeneration(ctx *cli.Context, cpHosts []hosts.Host, workerH if err != nil { return err } + logrus.Infof("[certificates] Generating admin certificates and kubeconfig") + err = generateAdminCerts(certs, clusterDomain, cpHosts, forceDeploy) + if err != nil { + return err + } err = deployCertificatesOnMasters(cpHosts, certs, forceDeploy) if err != nil { return err @@ -103,6 +108,7 @@ func generateCerts(cpHosts []hosts.Host, clusterDomain string, KubernetesService config: getKubeConfigX509("https://"+cpHosts[0].ControlPlaneIP+":6443", KubeProxyName, CACertPath, KubeProxyCertPath, KubeProxyKeyPath), } + // generate Kubelet certificate and key logrus.Infof("[certificates] Generating Node certificate") nodeCrt, nodeKey, err := generateClientCertAndKey(caCrt, caKey, KubeNodeCommonName, []string{KubeNodeOrganizationName}) if err != nil { @@ -117,6 +123,25 @@ func generateCerts(cpHosts []hosts.Host, clusterDomain string, KubernetesService return certs, nil } +func generateAdminCerts(certs map[string]CertificatePKI, clusterDomain string, cpHosts []hosts.Host, forceDeploy bool) error { + // generate API certificate and key + caCrt, caKey := certs[CACertName].certificate, certs[CACertName].key + kubeAdminCrt, kubeAdminKey, err := generateClientCertAndKey(caCrt, caKey, KubeAdminCommonName, []string{KubeAdminOrganizationName}) + if err != nil { + return err + } + logrus.Debugf("[certificates] Kube Admin Certificate: %s", string(cert.EncodeCertPEM(kubeAdminCrt))) + kubeAdminConfig := getKubeConfigX509WithData( + "https://"+cpHosts[0].IP+":6443", + KubeAdminCommonName, + string(cert.EncodeCertPEM(caCrt)), + string(cert.EncodeCertPEM(kubeAdminCrt)), + string(cert.EncodePrivateKeyPEM(kubeAdminKey))) + + err = deployAdminConfig(kubeAdminConfig, forceDeploy) + return err +} + func generateClientCertAndKey(caCrt *x509.Certificate, caKey *rsa.PrivateKey, commonName string, orgs []string) (*x509.Certificate, *rsa.PrivateKey, error) { rootKey, err := cert.NewPrivateKey() if err != nil {