From 263d7ad28237fa2a649005b250fea1e3471cdfa7 Mon Sep 17 00:00:00 2001 From: Yifan Gu Date: Tue, 31 Jul 2018 15:11:52 -0700 Subject: [PATCH] service_account: Use go code to generate service account key pairs Previously, the service account key pairs are generated by terraform in the bootkube module. This PR replace the generation using go code. Also cleaned up some of the tls and ignition terraform files. --- images/tectonic-installer/Dockerfile.ci | 2 +- installer/pkg/config-generator/tls.go | 75 +++++++++++++++---------- installer/pkg/tls/utils.go | 15 +++++ modules/bootkube/manifests.tf | 4 +- modules/bootkube/outputs.tf | 2 - modules/bootkube/service-account.tf | 35 ------------ modules/bootkube/variables.tf | 8 +++ modules/ignition/variables.tf | 10 ---- steps/assets/base/ignition-bootstrap.tf | 2 - steps/assets/base/ignition-tls.tf | 27 +++++++++ steps/assets/base/inputs.tf | 62 ++++++++++---------- steps/assets/base/outputs.tf | 1 + steps/assets/base/tectonic.tf | 52 ++++++++--------- 13 files changed, 159 insertions(+), 136 deletions(-) delete mode 100644 modules/bootkube/service-account.tf diff --git a/images/tectonic-installer/Dockerfile.ci b/images/tectonic-installer/Dockerfile.ci index 0f5d21f9fcb..4f7647887dc 100644 --- a/images/tectonic-installer/Dockerfile.ci +++ b/images/tectonic-installer/Dockerfile.ci @@ -1,6 +1,6 @@ # This Dockerfile is a used as a CI job to validate Tectonic installer on CentOS -FROM openshift/origin-release:golang-1.9 as build +FROM openshift/origin-release:golang-1.10 as build WORKDIR /go/src/github.com/openshift/installer COPY . . ### Install Terraform diff --git a/installer/pkg/config-generator/tls.go b/installer/pkg/config-generator/tls.go index da0816be424..3c81ba505ab 100644 --- a/installer/pkg/config-generator/tls.go +++ b/installer/pkg/config-generator/tls.go @@ -17,35 +17,37 @@ import ( ) const ( - adminCertPath = "generated/tls/admin.crt" - adminKeyPath = "generated/tls/admin.key" - aggregatorCACertPath = "generated/tls/aggregator-ca.crt" - aggregatorCAKeyPath = "generated/tls/aggregator-ca.key" - apiServerCertPath = "generated/tls/apiserver.crt" - apiServerKeyPath = "generated/tls/apiserver.key" - apiServerProxyCertPath = "generated/tls/apiserver-proxy.crt" - apiServerProxyKeyPath = "generated/tls/apiserver-proxy.key" - etcdCACertPath = "generated/tls/etcd-ca.crt" - etcdCAKeyPath = "generated/tls/etcd-ca.key" - etcdClientCertPath = "generated/tls/etcd-client.crt" - etcdClientKeyPath = "generated/tls/etcd-client.key" - ingressCACertPath = "generated/tls/ingress-ca.crt" - ingressCertPath = "generated/tls/ingress.crt" - ingressKeyPath = "generated/tls/ingress.key" - kubeCACertPath = "generated/tls/kube-ca.crt" - kubeCAKeyPath = "generated/tls/kube-ca.key" - kubeletCertPath = "generated/tls/kubelet.crt" - kubeletKeyPath = "generated/tls/kubelet.key" - clusterAPIServerCertPath = "generated/tls/cluster-apiserver-ca.crt" - clusterAPIServerKeyPath = "generated/tls/cluster-apiserver-ca.key" - osAPIServerCertPath = "generated/tls/openshift-apiserver.crt" - osAPIServerKeyPath = "generated/tls/openshift-apiserver.key" - rootCACertPath = "generated/tls/root-ca.crt" - rootCAKeyPath = "generated/tls/root-ca.key" - serviceServingCACertPath = "generated/tls/service-serving-ca.crt" - serviceServingCAKeyPath = "generated/tls/service-serving-ca.key" - tncCertPath = "generated/tls/tnc.crt" - tncKeyPath = "generated/tls/tnc.key" + adminCertPath = "generated/tls/admin.crt" + adminKeyPath = "generated/tls/admin.key" + aggregatorCACertPath = "generated/tls/aggregator-ca.crt" + aggregatorCAKeyPath = "generated/tls/aggregator-ca.key" + apiServerCertPath = "generated/tls/apiserver.crt" + apiServerKeyPath = "generated/tls/apiserver.key" + apiServerProxyCertPath = "generated/tls/apiserver-proxy.crt" + apiServerProxyKeyPath = "generated/tls/apiserver-proxy.key" + etcdCACertPath = "generated/tls/etcd-ca.crt" + etcdCAKeyPath = "generated/tls/etcd-ca.key" + etcdClientCertPath = "generated/tls/etcd-client.crt" + etcdClientKeyPath = "generated/tls/etcd-client.key" + ingressCACertPath = "generated/tls/ingress-ca.crt" + ingressCertPath = "generated/tls/ingress.crt" + ingressKeyPath = "generated/tls/ingress.key" + kubeCACertPath = "generated/tls/kube-ca.crt" + kubeCAKeyPath = "generated/tls/kube-ca.key" + kubeletCertPath = "generated/tls/kubelet.crt" + kubeletKeyPath = "generated/tls/kubelet.key" + clusterAPIServerCertPath = "generated/tls/cluster-apiserver-ca.crt" + clusterAPIServerKeyPath = "generated/tls/cluster-apiserver-ca.key" + osAPIServerCertPath = "generated/tls/openshift-apiserver.crt" + osAPIServerKeyPath = "generated/tls/openshift-apiserver.key" + rootCACertPath = "generated/tls/root-ca.crt" + rootCAKeyPath = "generated/tls/root-ca.key" + serviceServingCACertPath = "generated/tls/service-serving-ca.crt" + serviceServingCAKeyPath = "generated/tls/service-serving-ca.key" + tncCertPath = "generated/tls/tnc.crt" + tncKeyPath = "generated/tls/tnc.key" + serviceAccountPubkeyPath = "generated/tls/service-account.pub" + serviceAccountPrivateKeyPath = "generated/tls/service-account.key" validityTenYears = time.Hour * 24 * 365 * 10 validityThirtyMinutes = time.Minute * 30 @@ -267,6 +269,21 @@ func (c *ConfigGenerator) GenerateTLSConfig(clusterDir string) error { return fmt.Errorf("failed to generate cluster-apiserver CA: %v", err) } + // Service Account private and public key. + svcAccountPrivKey, err := generatePrivateKey(clusterDir, serviceAccountPrivateKeyPath) + if err != nil { + return fmt.Errorf("failed to generate service-account private key: %v", err) + } + + pubkeyPath := filepath.Join(clusterDir, serviceAccountPubkeyPath) + pubkeyData, err := tls.PublicKeyToPem(&svcAccountPrivKey.PublicKey) + if err != nil { + return fmt.Errorf("failed to generate service-account public key: %v", err) + } + if err := ioutil.WriteFile(pubkeyPath, []byte(pubkeyData), 0600); err != nil { + return fmt.Errorf("failed to write service-account public key: %v", err) + } + return nil } diff --git a/installer/pkg/tls/utils.go b/installer/pkg/tls/utils.go index 9cb8f91682c..4c322e5e720 100644 --- a/installer/pkg/tls/utils.go +++ b/installer/pkg/tls/utils.go @@ -39,3 +39,18 @@ func CSRToPem(cert *x509.CertificateRequest) string { ) return string(certInPem) } + +// PublicKeyToPem converts an rsa.PublicKey object to pem string +func PublicKeyToPem(key *rsa.PublicKey) (string, error) { + keyInBytes, err := x509.MarshalPKIXPublicKey(key) + if err != nil { + return "", err + } + keyinPem := pem.EncodeToMemory( + &pem.Block{ + Type: "RSA PUBLIC KEY", + Bytes: keyInBytes, + }, + ) + return string(keyinPem), nil +} diff --git a/modules/bootkube/manifests.tf b/modules/bootkube/manifests.tf index 52021081649..76907be8693 100644 --- a/modules/bootkube/manifests.tf +++ b/modules/bootkube/manifests.tf @@ -47,8 +47,8 @@ data "template_file" "manifest_file_list" { clusterapi_ca_key = "${base64encode(var.clusterapi_ca_key_pem)}" oidc_ca_cert = "${base64encode(var.oidc_ca_cert)}" pull_secret = "${base64encode(file(var.pull_secret_path))}" - serviceaccount_pub = "${base64encode(tls_private_key.service_account.public_key_pem)}" - serviceaccount_key = "${base64encode(tls_private_key.service_account.private_key_pem)}" + serviceaccount_pub = "${base64encode(var.service_account_public_key_pem)}" + serviceaccount_key = "${base64encode(var.service_account_private_key_pem)}" kube_dns_service_ip = "${cidrhost(var.service_cidr, 10)}" openshift_loopback_kubeconfig = "${base64encode(data.template_file.kubeconfig.rendered)}" diff --git a/modules/bootkube/outputs.tf b/modules/bootkube/outputs.tf index 582e029f6f1..90f9412960b 100644 --- a/modules/bootkube/outputs.tf +++ b/modules/bootkube/outputs.tf @@ -24,8 +24,6 @@ output "ignition_file_id_list" { data.ignition_file.bootkube_sh.id, data.ignition_file.kubeconfig.id, data.ignition_file.kubeconfig-kubelet.id, - data.ignition_file.service_account_key.id, - data.ignition_file.service_account_crt.id, ), data.ignition_file.manifest_file_list.*.id, ))}"] diff --git a/modules/bootkube/service-account.tf b/modules/bootkube/service-account.tf deleted file mode 100644 index 0c4e57186c0..00000000000 --- a/modules/bootkube/service-account.tf +++ /dev/null @@ -1,35 +0,0 @@ -# Kubernete's Service Account (resources/generated/tls/{service-account.key,service-account.pub}) -resource "tls_private_key" "service_account" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "local_file" "service_account_key" { - content = "${tls_private_key.service_account.private_key_pem}" - filename = "./generated/tls/service-account.key" -} - -data "ignition_file" "service_account_key" { - filesystem = "root" - path = "/opt/tectonic/tls/service-account.key" - mode = "0644" - - content { - content = "${tls_private_key.service_account.private_key_pem}" - } -} - -resource "local_file" "service_account_crt" { - content = "${tls_private_key.service_account.public_key_pem}" - filename = "./generated/tls/service-account.pub" -} - -data "ignition_file" "service_account_crt" { - filesystem = "root" - path = "/opt/tectonic/tls/service-account.pub" - mode = "0644" - - content { - content = "${tls_private_key.service_account.public_key_pem}" - } -} diff --git a/modules/bootkube/variables.tf b/modules/bootkube/variables.tf index 35ad4242325..c9d8a7e68b6 100644 --- a/modules/bootkube/variables.tf +++ b/modules/bootkube/variables.tf @@ -131,6 +131,14 @@ variable "tnc_key_pem" { type = "string" } +variable "service_account_public_key_pem" { + type = "string" +} + +variable "service_account_private_key_pem" { + type = "string" +} + variable "oidc_ca_cert" { type = "string" } diff --git a/modules/ignition/variables.tf b/modules/ignition/variables.tf index 3bcca37409a..9c697fc4e3c 100644 --- a/modules/ignition/variables.tf +++ b/modules/ignition/variables.tf @@ -69,13 +69,3 @@ variable "etcd_ca_cert_pem" { type = "string" description = "The etcd kube CA certificate in PEM format." } - -variable "tnc_cert_pem" { - type = "string" - description = "The TNC certificate in PEM format." -} - -variable "tnc_key_pem" { - type = "string" - description = "The TNC key in PEM format." -} diff --git a/steps/assets/base/ignition-bootstrap.tf b/steps/assets/base/ignition-bootstrap.tf index 694400f8869..68676b76129 100644 --- a/steps/assets/base/ignition-bootstrap.tf +++ b/steps/assets/base/ignition-bootstrap.tf @@ -12,8 +12,6 @@ module "ignition_bootstrap" { kubelet_debug_config = "${var.tectonic_kubelet_debug_config}" kubelet_node_label = "node-role.kubernetes.io/master" kubelet_node_taints = "node-role.kubernetes.io/master=:NoSchedule" - tnc_cert_pem = "${local.tnc_cert_pem}" - tnc_key_pem = "${local.tnc_key_pem}" } # The cluster configs written by the install binary external to Terraform. diff --git a/steps/assets/base/ignition-tls.tf b/steps/assets/base/ignition-tls.tf index c6105216c80..7cbac4b1e9e 100644 --- a/steps/assets/base/ignition-tls.tf +++ b/steps/assets/base/ignition-tls.tf @@ -275,6 +275,28 @@ data "ignition_file" "tnc_cert" { path = "/opt/tectonic/tls/tnc.crt" } +data "ignition_file" "service_account_private_key" { + filesystem = "root" + mode = "0644" + + content { + content = "${local.service_account_private_key_pem}" + } + + path = "/opt/tectonic/tls/service-account.key" +} + +data "ignition_file" "service_account_public_key" { + filesystem = "root" + mode = "0644" + + content { + content = "${local.service_account_public_key_pem}" + } + + path = "/opt/tectonic/tls/service-account.pub" +} + locals { ca_certs_ignition_file_id_list = [ "${data.ignition_file.root_ca_cert.id}", @@ -312,4 +334,9 @@ locals { "${data.ignition_file.tnc_key.id}", "${data.ignition_file.tnc_cert.id}", ] + + service_account_keys_ignition_file_id_list = [ + "${data.ignition_file.service_account_private_key.id}", + "${data.ignition_file.service_account_public_key.id}", + ] } diff --git a/steps/assets/base/inputs.tf b/steps/assets/base/inputs.tf index 6c41e6a8d7e..440173bcd52 100644 --- a/steps/assets/base/inputs.tf +++ b/steps/assets/base/inputs.tf @@ -1,32 +1,34 @@ locals { - admin_cert_pem = "${file("${local.tls_path}/admin.crt")}" - admin_key_pem = "${file("${local.tls_path}/admin.key")}" - aggregator_ca_cert_pem = "${file("${local.tls_path}/aggregator-ca.crt")}" - aggregator_ca_key_pem = "${file("${local.tls_path}/aggregator-ca.key")}" - apiserver_cert_pem = "${file("${local.tls_path}/apiserver.crt")}" - apiserver_key_pem = "${file("${local.tls_path}/apiserver.key")}" - apiserver_proxy_cert_pem = "${file("${local.tls_path}/apiserver-proxy.crt")}" - apiserver_proxy_key_pem = "${file("${local.tls_path}/apiserver-proxy.key")}" - clusterapi_ca_cert_pem = "${file("${local.tls_path}/cluster-apiserver-ca.crt")}" - clusterapi_ca_key_pem = "${file("${local.tls_path}/cluster-apiserver-ca.key")}" - etcd_ca_cert_pem = "${file("${local.tls_path}/etcd-client-ca.crt")}" - etcd_ca_key_pem = "${file("${local.tls_path}/etcd-client-ca.key")}" - etcd_client_cert_pem = "${file("${local.tls_path}/etcd-client.crt")}" - etcd_client_key_pem = "${file("${local.tls_path}/etcd-client.key")}" - ingress_ca_cert_pem = "${file("${local.tls_path}/ingress-ca.crt")}" - ingress_cert_pem = "${file("${local.tls_path}/ingress.crt")}" - ingress_key_pem = "${file("${local.tls_path}/ingress.key")}" - kube_ca_cert_pem = "${file("${local.tls_path}/kube-ca.crt")}" - kube_ca_key_pem = "${file("${local.tls_path}/kube-ca.key")}" - kubelet_cert_pem = "${file("${local.tls_path}/kubelet.crt")}" - kubelet_key_pem = "${file("${local.tls_path}/kubelet.key")}" - oidc_ca_cert = "${file("${local.tls_path}/ingress-ca.crt")}" - openshift_apiserver_cert_pem = "${file("${local.tls_path}/openshift-apiserver.crt")}" - openshift_apiserver_key_pem = "${file("${local.tls_path}/openshift-apiserver.key")}" - root_ca_cert_pem = "${file("${local.tls_path}/root-ca.crt")}" - service_serving_ca_cert_pem = "${file("${local.tls_path}/service-serving-ca.crt")}" - service_serving_ca_key_pem = "${file("${local.tls_path}/service-serving-ca.key")}" - tls_path = "${path.cwd}/generated/tls" - tnc_cert_pem = "${file("${local.tls_path}/tnc.crt")}" - tnc_key_pem = "${file("${local.tls_path}/tnc.key")}" + admin_cert_pem = "${file("${local.tls_path}/admin.crt")}" + admin_key_pem = "${file("${local.tls_path}/admin.key")}" + aggregator_ca_cert_pem = "${file("${local.tls_path}/aggregator-ca.crt")}" + aggregator_ca_key_pem = "${file("${local.tls_path}/aggregator-ca.key")}" + apiserver_cert_pem = "${file("${local.tls_path}/apiserver.crt")}" + apiserver_key_pem = "${file("${local.tls_path}/apiserver.key")}" + apiserver_proxy_cert_pem = "${file("${local.tls_path}/apiserver-proxy.crt")}" + apiserver_proxy_key_pem = "${file("${local.tls_path}/apiserver-proxy.key")}" + clusterapi_ca_cert_pem = "${file("${local.tls_path}/cluster-apiserver-ca.crt")}" + clusterapi_ca_key_pem = "${file("${local.tls_path}/cluster-apiserver-ca.key")}" + etcd_ca_cert_pem = "${file("${local.tls_path}/etcd-client-ca.crt")}" + etcd_ca_key_pem = "${file("${local.tls_path}/etcd-client-ca.key")}" + etcd_client_cert_pem = "${file("${local.tls_path}/etcd-client.crt")}" + etcd_client_key_pem = "${file("${local.tls_path}/etcd-client.key")}" + ingress_ca_cert_pem = "${file("${local.tls_path}/ingress-ca.crt")}" + ingress_cert_pem = "${file("${local.tls_path}/ingress.crt")}" + ingress_key_pem = "${file("${local.tls_path}/ingress.key")}" + kube_ca_cert_pem = "${file("${local.tls_path}/kube-ca.crt")}" + kube_ca_key_pem = "${file("${local.tls_path}/kube-ca.key")}" + kubelet_cert_pem = "${file("${local.tls_path}/kubelet.crt")}" + kubelet_key_pem = "${file("${local.tls_path}/kubelet.key")}" + oidc_ca_cert = "${file("${local.tls_path}/ingress-ca.crt")}" + openshift_apiserver_cert_pem = "${file("${local.tls_path}/openshift-apiserver.crt")}" + openshift_apiserver_key_pem = "${file("${local.tls_path}/openshift-apiserver.key")}" + root_ca_cert_pem = "${file("${local.tls_path}/root-ca.crt")}" + service_serving_ca_cert_pem = "${file("${local.tls_path}/service-serving-ca.crt")}" + service_serving_ca_key_pem = "${file("${local.tls_path}/service-serving-ca.key")}" + tls_path = "${path.cwd}/generated/tls" + tnc_cert_pem = "${file("${local.tls_path}/tnc.crt")}" + tnc_key_pem = "${file("${local.tls_path}/tnc.key")}" + service_account_public_key_pem = "${file("${local.tls_path}/service-account.pub")}" + service_account_private_key_pem = "${file("${local.tls_path}/service-account.key")}" } diff --git a/steps/assets/base/outputs.tf b/steps/assets/base/outputs.tf index b7133955a33..648c3de865a 100644 --- a/steps/assets/base/outputs.tf +++ b/steps/assets/base/outputs.tf @@ -21,6 +21,7 @@ output "ignition_bootstrap_files" { local.etcd_certs_ignition_file_id_list, local.kube_certs_ignition_file_id_list, local.tnc_certs_ignition_file_id_list, + local.service_account_keys_ignition_file_id_list, )))}"] } diff --git a/steps/assets/base/tectonic.tf b/steps/assets/base/tectonic.tf index dca6accd5ca..b366d8739ae 100644 --- a/steps/assets/base/tectonic.tf +++ b/steps/assets/base/tectonic.tf @@ -21,31 +21,33 @@ module "bootkube" { pull_secret_path = "${pathexpand(var.tectonic_pull_secret_path)}" - admin_cert_pem = "${local.admin_cert_pem}" - admin_key_pem = "${local.admin_key_pem}" - aggregator_ca_cert_pem = "${local.aggregator_ca_cert_pem}" - aggregator_ca_key_pem = "${local.aggregator_ca_key_pem}" - apiserver_cert_pem = "${local.apiserver_cert_pem}" - apiserver_key_pem = "${local.apiserver_key_pem}" - apiserver_proxy_cert_pem = "${local.apiserver_proxy_cert_pem}" - apiserver_proxy_key_pem = "${local.apiserver_proxy_key_pem}" - etcd_ca_cert_pem = "${local.etcd_ca_cert_pem}" - etcd_client_cert_pem = "${local.etcd_client_cert_pem}" - etcd_client_key_pem = "${local.etcd_client_key_pem}" - kube_ca_cert_pem = "${local.kube_ca_cert_pem}" - kube_ca_key_pem = "${local.kube_ca_key_pem}" - kubelet_cert_pem = "${local.kubelet_cert_pem}" - kubelet_key_pem = "${local.kubelet_key_pem}" - clusterapi_ca_cert_pem = "${local.clusterapi_ca_cert_pem}" - clusterapi_ca_key_pem = "${local.clusterapi_ca_key_pem}" - oidc_ca_cert = "${local.oidc_ca_cert}" - openshift_apiserver_cert_pem = "${local.openshift_apiserver_cert_pem}" - openshift_apiserver_key_pem = "${local.openshift_apiserver_key_pem}" - root_ca_cert_pem = "${local.root_ca_cert_pem}" - service_serving_ca_cert_pem = "${local.service_serving_ca_cert_pem}" - service_serving_ca_key_pem = "${local.service_serving_ca_key_pem}" - tnc_cert_pem = "${local.tnc_cert_pem}" - tnc_key_pem = "${local.tnc_key_pem}" + admin_cert_pem = "${local.admin_cert_pem}" + admin_key_pem = "${local.admin_key_pem}" + aggregator_ca_cert_pem = "${local.aggregator_ca_cert_pem}" + aggregator_ca_key_pem = "${local.aggregator_ca_key_pem}" + apiserver_cert_pem = "${local.apiserver_cert_pem}" + apiserver_key_pem = "${local.apiserver_key_pem}" + apiserver_proxy_cert_pem = "${local.apiserver_proxy_cert_pem}" + apiserver_proxy_key_pem = "${local.apiserver_proxy_key_pem}" + etcd_ca_cert_pem = "${local.etcd_ca_cert_pem}" + etcd_client_cert_pem = "${local.etcd_client_cert_pem}" + etcd_client_key_pem = "${local.etcd_client_key_pem}" + kube_ca_cert_pem = "${local.kube_ca_cert_pem}" + kube_ca_key_pem = "${local.kube_ca_key_pem}" + kubelet_cert_pem = "${local.kubelet_cert_pem}" + kubelet_key_pem = "${local.kubelet_key_pem}" + clusterapi_ca_cert_pem = "${local.clusterapi_ca_cert_pem}" + clusterapi_ca_key_pem = "${local.clusterapi_ca_key_pem}" + oidc_ca_cert = "${local.oidc_ca_cert}" + openshift_apiserver_cert_pem = "${local.openshift_apiserver_cert_pem}" + openshift_apiserver_key_pem = "${local.openshift_apiserver_key_pem}" + root_ca_cert_pem = "${local.root_ca_cert_pem}" + service_serving_ca_cert_pem = "${local.service_serving_ca_cert_pem}" + service_serving_ca_key_pem = "${local.service_serving_ca_key_pem}" + tnc_cert_pem = "${local.tnc_cert_pem}" + tnc_key_pem = "${local.tnc_key_pem}" + service_account_public_key_pem = "${local.service_account_public_key_pem}" + service_account_private_key_pem = "${local.service_account_private_key_pem}" etcd_endpoints = "${data.template_file.etcd_hostname_list.*.rendered}" }