diff --git a/modules/bootkube/assets.tf b/modules/bootkube/assets.tf index 6507432adf..df1a1449f1 100644 --- a/modules/bootkube/assets.tf +++ b/modules/bootkube/assets.tf @@ -8,16 +8,16 @@ resource "template_dir" "experimental" { etcd_service_ip = "${cidrhost(var.service_cidr, 15)}" kenc_image = "${var.container_images["kenc"]}" - etcd_ca_cert = "${base64encode(data.template_file.etcd_ca_cert_pem.rendered)}" + etcd_ca_cert = "${base64encode(var.etcd_ca_cert_pem)}" - etcd_server_cert = "${base64encode(join("", tls_locally_signed_cert.etcd_server.*.cert_pem))}" - etcd_server_key = "${base64encode(join("", tls_private_key.etcd_server.*.private_key_pem))}" + etcd_server_cert = "${base64encode(var.etcd_server_cert_pem)}" + etcd_server_key = "${base64encode(var.etcd_server_key_pem)}" - etcd_client_cert = "${base64encode(data.template_file.etcd_client_crt.rendered)}" - etcd_client_key = "${base64encode(data.template_file.etcd_client_key.rendered)}" + etcd_client_cert = "${base64encode(var.etcd_client_cert_pem)}" + etcd_client_key = "${base64encode(var.etcd_client_key_pem)}" - etcd_peer_cert = "${base64encode(join("", tls_locally_signed_cert.etcd_peer.*.cert_pem))}" - etcd_peer_key = "${base64encode(join("", tls_private_key.etcd_peer.*.private_key_pem))}" + etcd_peer_cert = "${base64encode(var.etcd_peer_cert_pem)}" + etcd_peer_key = "${base64encode(var.etcd_peer_key_pem)}" } } @@ -66,7 +66,7 @@ resource "template_dir" "bootkube" { etcd_servers = "${ var.experimental_enabled ? format("https://%s:2379", cidrhost(var.service_cidr, 15)) - : data.template_file.etcd_ca_cert_pem.rendered == "" + : var.etcd_ca_cert_pem == "" ? join(",", formatlist("http://%s:2379", var.etcd_endpoints)) : join(",", formatlist("https://%s:2379", var.etcd_endpoints)) }" @@ -88,20 +88,21 @@ resource "template_dir" "bootkube" { oidc_client_id = "${var.oidc_client_id}" oidc_username_claim = "${var.oidc_username_claim}" oidc_groups_claim = "${var.oidc_groups_claim}" + oidc_ca_cert = "${base64encode(var.oidc_ca_cert)}" - ca_cert = "${base64encode(var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert)}" - apiserver_key = "${base64encode(tls_private_key.apiserver.private_key_pem)}" - apiserver_cert = "${base64encode(tls_locally_signed_cert.apiserver.cert_pem)}" + kube_ca_cert = "${base64encode(var.kube_ca_cert_pem)}" + apiserver_key = "${base64encode(var.apiserver_key_pem)}" + apiserver_cert = "${base64encode(var.apiserver_cert_pem)}" serviceaccount_pub = "${base64encode(tls_private_key.service_account.public_key_pem)}" serviceaccount_key = "${base64encode(tls_private_key.service_account.private_key_pem)}" - etcd_ca_flag = "${data.template_file.etcd_ca_cert_pem.rendered != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }" - etcd_cert_flag = "${data.template_file.etcd_client_crt.rendered != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }" - etcd_key_flag = "${data.template_file.etcd_client_key.rendered != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }" + etcd_ca_flag = "${var.etcd_ca_cert_pem != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }" + etcd_cert_flag = "${var.etcd_client_cert_pem != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }" + etcd_key_flag = "${var.etcd_client_key_pem != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }" - etcd_ca_cert = "${base64encode(data.template_file.etcd_ca_cert_pem.rendered)}" - etcd_client_cert = "${base64encode(data.template_file.etcd_client_crt.rendered)}" - etcd_client_key = "${base64encode(data.template_file.etcd_client_key.rendered)}" + etcd_ca_cert = "${base64encode(var.etcd_ca_cert_pem)}" + etcd_client_cert = "${base64encode(var.etcd_client_cert_pem)}" + etcd_client_key = "${base64encode(var.etcd_client_key_pem)}" kubernetes_version = "${replace(var.versions["kubernetes"], "+", "-")}" @@ -126,14 +127,14 @@ resource "template_dir" "bootkube_bootstrap" { etcd_servers = "${ var.experimental_enabled ? format("https://%s:2379,https://127.0.0.1:12379", cidrhost(var.service_cidr, 15)) - : data.template_file.etcd_ca_cert_pem.rendered == "" + : var.etcd_ca_cert_pem == "" ? join(",", formatlist("http://%s:2379", var.etcd_endpoints)) : join(",", formatlist("https://%s:2379", var.etcd_endpoints)) }" - etcd_ca_flag = "${data.template_file.etcd_ca_cert_pem.rendered != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }" - etcd_cert_flag = "${data.template_file.etcd_client_crt.rendered != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }" - etcd_key_flag = "${data.template_file.etcd_client_key.rendered != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }" + etcd_ca_flag = "${var.etcd_ca_cert_pem != "" ? "- --etcd-cafile=/etc/kubernetes/secrets/etcd-client-ca.crt" : "# no etcd-client-ca.crt given" }" + etcd_cert_flag = "${var.etcd_client_cert_pem != "" ? "- --etcd-certfile=/etc/kubernetes/secrets/etcd-client.crt" : "# no etcd-client.crt given" }" + etcd_key_flag = "${var.etcd_client_key_pem != "" ? "- --etcd-keyfile=/etc/kubernetes/secrets/etcd-client.key" : "# no etcd-client.key given" }" cloud_provider = "${var.cloud_provider}" cloud_provider_config = "${var.cloud_provider_config}" @@ -150,9 +151,9 @@ data "template_file" "kubeconfig" { template = "${file("${path.module}/resources/kubeconfig")}" vars { - ca_cert = "${base64encode(var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert)}" - kubelet_cert = "${base64encode(tls_locally_signed_cert.kubelet.cert_pem)}" - kubelet_key = "${base64encode(tls_private_key.kubelet.private_key_pem)}" + kube_ca_cert = "${base64encode(var.kube_ca_cert_pem)}" + kubelet_cert = "${base64encode(var.kubelet_cert_pem)}" + kubelet_key = "${base64encode(var.kubelet_key_pem)}" server = "${var.kube_apiserver_url}" cluster_name = "${var.cluster_name}" } @@ -198,108 +199,3 @@ data "ignition_systemd_unit" "bootkube_path_unit" { enable = true content = "${data.template_file.bootkube_path_unit.rendered}" } - -# etcd assets -data "template_file" "etcd_ca_cert_pem" { - template = "${var.experimental_enabled || var.etcd_tls_enabled - ? join("", tls_self_signed_cert.etcd_ca.*.cert_pem) - : file(var.etcd_ca_cert) - }" -} - -data "template_file" "etcd_client_crt" { - template = "${var.experimental_enabled || var.etcd_tls_enabled - ? join("", tls_locally_signed_cert.etcd_client.*.cert_pem) - : file(var.etcd_client_cert) - }" -} - -data "template_file" "etcd_client_key" { - template = "${var.experimental_enabled || var.etcd_tls_enabled - ? join("", tls_private_key.etcd_client.*.private_key_pem) - : file(var.etcd_client_key) - }" -} - -resource "local_file" "etcd_ca_crt" { - count = "${var.experimental_enabled || var.etcd_tls_enabled || var.etcd_ca_cert != "/dev/null" ? 1 : 0}" - content = "${data.template_file.etcd_ca_cert_pem.rendered}" - filename = "./generated/tls/etcd-client-ca.crt" -} - -resource "local_file" "etcd_client_crt" { - count = "${var.experimental_enabled || var.etcd_tls_enabled || var.etcd_client_cert != "/dev/null" ? 1 : 0}" - content = "${data.template_file.etcd_client_crt.rendered}" - filename = "./generated/tls/etcd-client.crt" -} - -resource "local_file" "etcd_client_key" { - count = "${var.experimental_enabled || var.etcd_tls_enabled || var.etcd_client_key != "/dev/null" ? 1 : 0}" - content = "${data.template_file.etcd_client_key.rendered}" - filename = "./generated/tls/etcd-client.key" -} - -resource "local_file" "etcd_server_crt" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" - content = "${join("", tls_locally_signed_cert.etcd_server.*.cert_pem)}" - filename = "./generated/tls/etcd/server.crt" -} - -resource "local_file" "etcd_server_key" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" - content = "${join("", tls_private_key.etcd_server.*.private_key_pem)}" - filename = "./generated/tls/etcd/server.key" -} - -resource "local_file" "etcd_peer_crt" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" - content = "${join("", tls_locally_signed_cert.etcd_peer.*.cert_pem)}" - filename = "./generated/tls/etcd/peer.crt" -} - -resource "local_file" "etcd_peer_key" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" - content = "${join("", tls_private_key.etcd_peer.*.private_key_pem)}" - filename = "./generated/tls/etcd/peer.key" -} - -data "archive_file" "etcd_tls_zip" { - type = "zip" - - output_path = "./.terraform/etcd_tls.zip" - - source { - filename = "ca.crt" - content = "${data.template_file.etcd_ca_cert_pem.rendered}" - } - - source { - filename = "server.crt" - content = "${join("", tls_locally_signed_cert.etcd_server.*.cert_pem)}" - } - - source { - filename = "server.key" - content = "${join("", tls_private_key.etcd_server.*.private_key_pem)}" - } - - source { - filename = "peer.crt" - content = "${join("", tls_locally_signed_cert.etcd_peer.*.cert_pem)}" - } - - source { - filename = "peer.key" - content = "${join("", tls_private_key.etcd_peer.*.private_key_pem)}" - } - - source { - filename = "client.crt" - content = "${data.template_file.etcd_client_crt.rendered}" - } - - source { - filename = "client.key" - content = "${data.template_file.etcd_client_key.rendered}" - } -} diff --git a/modules/bootkube/outputs.tf b/modules/bootkube/outputs.tf index f21f428c86..cff3acad88 100644 --- a/modules/bootkube/outputs.tf +++ b/modules/bootkube/outputs.tf @@ -17,18 +17,10 @@ # interpolated once the assets have all been created. output "id" { value = "${sha1(" - ${data.archive_file.etcd_tls_zip.id} ${local_file.kubeconfig.id} ${local_file.bootkube_sh.id} ${template_dir.bootkube.id} ${template_dir.bootkube_bootstrap.id} ${join(" ", - local_file.etcd_ca_crt.*.id, - local_file.etcd_server_crt.*.id, - local_file.etcd_server_key.*.id, - local_file.etcd_client_crt.*.id, - local_file.etcd_client_key.*.id, - local_file.etcd_peer_crt.*.id, - local_file.etcd_peer_key.*.id, template_dir.experimental.*.id, template_dir.bootstrap_experimental.*.id, template_dir.etcd_experimental.*.id, @@ -36,26 +28,10 @@ output "id" { ")}" } -output "etcd_tls_zip" { - value = "${data.archive_file.etcd_tls_zip.id != "" ? file("./.terraform/etcd_tls.zip") : ""}" -} - output "kubeconfig" { value = "${data.template_file.kubeconfig.rendered}" } -output "ca_cert" { - value = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert}" -} - -output "ca_key_alg" { - value = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" -} - -output "ca_key" { - value = "${var.ca_cert == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key}" -} - output "systemd_service_rendered" { value = "${data.template_file.bootkube_service.rendered}" } @@ -75,31 +51,3 @@ output "systemd_path_unit_id" { output "kube_dns_service_ip" { value = "${cidrhost(var.service_cidr, 10)}" } - -output "etcd_ca_crt_pem" { - value = "${join("", tls_self_signed_cert.etcd_ca.*.cert_pem)}" -} - -output "etcd_server_crt_pem" { - value = "${join("", tls_locally_signed_cert.etcd_server.*.cert_pem)}" -} - -output "etcd_server_key_pem" { - value = "${join("", tls_private_key.etcd_server.*.private_key_pem)}" -} - -output "etcd_client_crt_pem" { - value = "${join("", tls_locally_signed_cert.etcd_client.*.cert_pem)}" -} - -output "etcd_client_key_pem" { - value = "${join("", tls_private_key.etcd_client.*.private_key_pem)}" -} - -output "etcd_peer_crt_pem" { - value = "${join("", tls_locally_signed_cert.etcd_peer.*.cert_pem)}" -} - -output "etcd_peer_key_pem" { - value = "${join("", tls_private_key.etcd_peer.*.private_key_pem)}" -} diff --git a/modules/bootkube/resources/kubeconfig b/modules/bootkube/resources/kubeconfig index eea7fb08e1..050f605d16 100644 --- a/modules/bootkube/resources/kubeconfig +++ b/modules/bootkube/resources/kubeconfig @@ -4,7 +4,7 @@ clusters: - name: ${cluster_name} cluster: server: ${server} - certificate-authority-data: ${ca_cert} + certificate-authority-data: ${kube_ca_cert} users: - name: kubelet user: diff --git a/modules/bootkube/resources/manifests/kube-apiserver-secret.yaml b/modules/bootkube/resources/manifests/kube-apiserver-secret.yaml index 4ead60ba95..8731c3e454 100644 --- a/modules/bootkube/resources/manifests/kube-apiserver-secret.yaml +++ b/modules/bootkube/resources/manifests/kube-apiserver-secret.yaml @@ -8,7 +8,8 @@ data: apiserver.key: ${apiserver_key} apiserver.crt: ${apiserver_cert} service-account.pub: ${serviceaccount_pub} - ca.crt: ${ca_cert} + ca.crt: ${kube_ca_cert} etcd-client-ca.crt: ${etcd_ca_cert} etcd-client.crt: ${etcd_client_cert} etcd-client.key: ${etcd_client_key} + oidc-ca.crt: ${oidc_ca_cert} diff --git a/modules/bootkube/resources/manifests/kube-apiserver.yaml b/modules/bootkube/resources/manifests/kube-apiserver.yaml index 5854f78fc1..6bd9d32873 100644 --- a/modules/bootkube/resources/manifests/kube-apiserver.yaml +++ b/modules/bootkube/resources/manifests/kube-apiserver.yaml @@ -54,7 +54,7 @@ spec: - --oidc-client-id=${oidc_client_id} - --oidc-username-claim=${oidc_username_claim} - --oidc-groups-claim=${oidc_groups_claim} - - --oidc-ca-file=/etc/kubernetes/secrets/ca.crt + - --oidc-ca-file=/etc/kubernetes/secrets/oidc-ca.crt - --cloud-provider=${cloud_provider} ${cloud_provider_config_flag} - --audit-log-path=/var/log/kubernetes/kube-apiserver-audit.log diff --git a/modules/bootkube/resources/manifests/kube-controller-manager-secret.yaml b/modules/bootkube/resources/manifests/kube-controller-manager-secret.yaml index 50efc76a0d..321c2fde5a 100644 --- a/modules/bootkube/resources/manifests/kube-controller-manager-secret.yaml +++ b/modules/bootkube/resources/manifests/kube-controller-manager-secret.yaml @@ -6,4 +6,4 @@ metadata: type: Opaque data: service-account.key: ${serviceaccount_key} - ca.crt: ${ca_cert} \ No newline at end of file + ca.crt: ${kube_ca_cert} diff --git a/modules/bootkube/service-account.tf b/modules/bootkube/service-account.tf new file mode 100644 index 0000000000..00fbaf11a7 --- /dev/null +++ b/modules/bootkube/service-account.tf @@ -0,0 +1,15 @@ +# 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" +} + +resource "local_file" "service_account_crt" { + content = "${tls_private_key.service_account.public_key_pem}" + filename = "./generated/tls/service-account.pub" +} diff --git a/modules/bootkube/tls_kube.tf b/modules/bootkube/tls_kube.tf deleted file mode 100644 index d3e50d86e7..0000000000 --- a/modules/bootkube/tls_kube.tf +++ /dev/null @@ -1,165 +0,0 @@ -# NOTE: Across this module, the following syntax is used at various places: -# `"${var.ca_cert == "" ? join(" ", tls_private_key.kube-ca.*.private_key_pem) : var.ca_key}"` -# -# Due to https://github.com/hashicorp/hil/issues/50, both sides of conditions -# are evaluated, until one of them is discarded. Unfortunately, the -# `{tls_private_key/tls_self_signed_cert}.kube-ca` resources are created -# conditionally and might not be present - in which case an error is -# generated. Because a `count` is used on these ressources, the resources can be -# referenced as lists with the `.*` notation, and arrays are allowed to be -# empty. The `join()` interpolation function is then used to cast them back to -# a string. Since `count` can only be 0 or 1, the returned value is either empty -# (and discarded anyways) or the desired value. - -# Kubernetes CA (resources/generated/tls/{ca.crt,ca.key}) -resource "tls_private_key" "kube_ca" { - count = "${var.ca_cert == "" ? 1 : 0}" - - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_self_signed_cert" "kube_ca" { - count = "${var.ca_cert == "" ? 1 : 0}" - - key_algorithm = "${tls_private_key.kube_ca.algorithm}" - private_key_pem = "${tls_private_key.kube_ca.private_key_pem}" - - subject { - common_name = "kube-ca" - organization = "bootkube" - } - - is_ca_certificate = true - validity_period_hours = 8760 - - allowed_uses = [ - "key_encipherment", - "digital_signature", - "cert_signing", - ] -} - -resource "local_file" "kube_ca_key" { - content = "${var.ca_cert == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key}" - filename = "./generated/tls/ca.key" -} - -resource "local_file" "kube_ca_crt" { - content = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert}" - filename = "./generated/tls/ca.crt" -} - -# Kubernetes API Server (resources/generated/tls/{apiserver.key,apiserver.crt}) -resource "tls_private_key" "apiserver" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_cert_request" "apiserver" { - key_algorithm = "${tls_private_key.apiserver.algorithm}" - private_key_pem = "${tls_private_key.apiserver.private_key_pem}" - - subject { - common_name = "kube-apiserver" - organization = "kube-master" - } - - dns_names = [ - "${replace(element(split(":", var.kube_apiserver_url), 1), "/", "")}", - "kubernetes", - "kubernetes.default", - "kubernetes.default.svc", - "kubernetes.default.svc.cluster.local", - ] - - ip_addresses = [ - "${cidrhost(var.service_cidr, 1)}", - ] -} - -resource "tls_locally_signed_cert" "apiserver" { - cert_request_pem = "${tls_cert_request.apiserver.cert_request_pem}" - - ca_key_algorithm = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" - ca_private_key_pem = "${var.ca_cert == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key}" - ca_cert_pem = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem): var.ca_cert}" - - validity_period_hours = 8760 - - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - "client_auth", - ] -} - -resource "local_file" "apiserver_key" { - content = "${tls_private_key.apiserver.private_key_pem}" - filename = "./generated/tls/apiserver.key" -} - -resource "local_file" "apiserver_crt" { - content = "${tls_locally_signed_cert.apiserver.cert_pem}" - filename = "./generated/tls/apiserver.crt" -} - -# 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" -} - -resource "local_file" "service_account_crt" { - content = "${tls_private_key.service_account.public_key_pem}" - filename = "./generated/tls/service-account.pub" -} - -# Kubelet -resource "tls_private_key" "kubelet" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_cert_request" "kubelet" { - key_algorithm = "${tls_private_key.kubelet.algorithm}" - private_key_pem = "${tls_private_key.kubelet.private_key_pem}" - - subject { - common_name = "kubelet" - organization = "system:masters" - } -} - -resource "tls_locally_signed_cert" "kubelet" { - cert_request_pem = "${tls_cert_request.kubelet.cert_request_pem}" - - ca_key_algorithm = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" - ca_private_key_pem = "${var.ca_cert == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key}" - ca_cert_pem = "${var.ca_cert == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert}" - - validity_period_hours = 8760 - - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - "client_auth", - ] -} - -resource "local_file" "kubelet_key" { - content = "${tls_private_key.kubelet.private_key_pem}" - filename = "./generated/tls/kubelet.key" -} - -resource "local_file" "kubelet_crt" { - content = "${tls_locally_signed_cert.kubelet.cert_pem}" - filename = "./generated/tls/kubelet.crt" -} diff --git a/modules/bootkube/variables.tf b/modules/bootkube/variables.tf index 62e5dd1a26..364636fa0d 100644 --- a/modules/bootkube/variables.tf +++ b/modules/bootkube/variables.tf @@ -1,110 +1,130 @@ -variable "cluster_name" { - type = "string" +variable "advertise_address" { + description = "The IP address on which to advertise the apiserver to members of the cluster" + type = "string" } -variable "container_images" { - description = "Container images to use" - type = "map" +variable "anonymous_auth" { + description = "Enables anonymous requests to the secure port of the API server" + type = "string" } -variable "versions" { - description = "Container versions to use" - type = "map" +variable "apiserver_cert_pem" { + type = "string" + description = "The API server certificate in PEM format." } -variable "kube_apiserver_url" { - description = "URL used to reach kube-apiserver" +variable "apiserver_key_pem" { type = "string" + description = "The API server key in PEM format." } -variable "etcd_tls_enabled" { - default = false +variable "cloud_provider" { + description = "The provider for cloud services (empty string for no provider)" + type = "string" } -variable "etcd_cert_dns_names" { - type = "list" +variable "cloud_provider_config" { + description = "Content of cloud provider config" + type = "string" + default = "" } -variable "etcd_endpoints" { - description = "List of etcd endpoints to connect with (hostnames/IPs only)" - type = "list" +variable "cluster_cidr" { + description = "A CIDR notation IP range from which to assign pod IPs" + type = "string" } -variable "etcd_ca_cert" { +variable "cluster_name" { type = "string" } -variable "etcd_client_cert" { - type = "string" +variable "container_images" { + description = "Container images to use" + type = "map" } -variable "etcd_client_key" { - type = "string" +variable "etcd_ca_cert_pem" { + type = "string" + description = "The etcd CA certificate in PEM format." } -variable "experimental_enabled" { - description = "If set to true, provision experimental assets, like self-hosted etcd." - default = false +variable "etcd_client_cert_pem" { + type = "string" + description = "The etcd client certificate in PEM format." } -variable "cloud_provider" { - description = "The provider for cloud services (empty string for no provider)" +variable "etcd_client_key_pem" { type = "string" + description = "The etcd client key in PEM format." } -variable "cloud_provider_config" { - description = "Content of cloud provider config" +variable "etcd_endpoints" { + description = "List of etcd endpoints to connect with (hostnames/IPs only)" + type = "list" +} + +variable "etcd_peer_cert_pem" { type = "string" - default = "" + description = "The etcd peer certificate in PEM format." } -variable "service_cidr" { - description = "A CIDR notation IP range from which to assign service cluster IPs" +variable "etcd_peer_key_pem" { type = "string" + description = "The etcd peer key in PEM format." } -variable "cluster_cidr" { - description = "A CIDR notation IP range from which to assign pod IPs" +variable "etcd_server_cert_pem" { type = "string" + description = "The etcd server certificate in PEM format." } -variable "advertise_address" { - description = "The IP address on which to advertise the apiserver to members of the cluster" +variable "etcd_server_key_pem" { type = "string" + description = "The etcd server key in PEM format." } -variable "ca_cert" { - description = "PEM-encoded CA certificate (generated if blank)" +variable "experimental_enabled" { + description = "If set to true, provision experimental assets, like self-hosted etcd." + default = false +} + +variable "kube_apiserver_url" { + description = "URL used to reach kube-apiserver" type = "string" } -variable "ca_key_alg" { - description = "Algorithm used to generate ca_key (required if ca_cert is specified)" +variable "kube_ca_cert_pem" { type = "string" + description = "The Kubernetes CA in PEM format." } -variable "ca_key" { - description = "PEM-encoded CA key (required if ca_cert is specified)" +variable "kubelet_cert_pem" { type = "string" + description = "The kubelet certificate in PEM format." } -variable "anonymous_auth" { - description = "Enables anonymous requests to the secure port of the API server" +variable "kubelet_key_pem" { type = "string" + description = "The kubelet key in PEM format." } -variable "oidc_issuer_url" { - description = "The URL of the OpenID issuer, only HTTPS scheme will be accepted" +variable "master_count" { + description = "The number of the master nodes" type = "string" } -variable "oidc_client_id" { - description = "The client ID for the OpenID Connect client" +variable "node_monitor_grace_period" { + description = "Amount of time which we allow running Node to be unresponsive before marking it unhealthy. Must be N times more than kubelet's nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet to post node status. N must be stricly > 1." type = "string" + default = "40s" } -variable "oidc_username_claim" { - description = "The OpenID claim to use as the user name" +variable "oidc_ca_cert" { + type = "string" +} + +variable "oidc_client_id" { + description = "The client ID for the OpenID Connect client" type = "string" } @@ -113,15 +133,14 @@ variable "oidc_groups_claim" { type = "string" } -variable "master_count" { - description = "The number of the master nodes" +variable "oidc_issuer_url" { + description = "The URL of the OpenID issuer, only HTTPS scheme will be accepted" type = "string" } -variable "node_monitor_grace_period" { - description = "Amount of time which we allow running Node to be unresponsive before marking it unhealthy. Must be N times more than kubelet's nodeStatusUpdateFrequency, where N means number of retries allowed for kubelet to post node status. N must be stricly > 1." +variable "oidc_username_claim" { + description = "The OpenID claim to use as the user name" type = "string" - default = "40s" } variable "pod_eviction_timeout" { @@ -134,3 +153,13 @@ variable "cloud_config_path" { description = "The path to the secret file that contains the cloud config contents. Either be empty ('') or ('/etc/kubernetes/cloud/config')." type = "string" } + +variable "service_cidr" { + description = "A CIDR notation IP range from which to assign service cluster IPs" + type = "string" +} + +variable "versions" { + description = "Container versions to use" + type = "map" +} diff --git a/modules/tectonic/assets.tf b/modules/tectonic/assets.tf index 085167d650..cfd2532f43 100644 --- a/modules/tectonic/assets.tf +++ b/modules/tectonic/assets.tf @@ -70,13 +70,14 @@ resource "template_dir" "tectonic" { prometheus_callback = "https://${var.base_address}/prometheus/auth/callback" ingress_kind = "${var.ingress_kind}" - ingress_tls_cert = "${base64encode(tls_locally_signed_cert.ingress.cert_pem)}" - ingress_tls_key = "${base64encode(tls_private_key.ingress.private_key_pem)}" - - identity_server_tls_cert = "${base64encode(tls_locally_signed_cert.identity_server.cert_pem)}" - identity_server_tls_key = "${base64encode(tls_private_key.identity_server.private_key_pem)}" - identity_client_tls_cert = "${base64encode(tls_locally_signed_cert.identity_client.cert_pem)}" - identity_client_tls_key = "${base64encode(tls_private_key.identity_client.private_key_pem)}" + ingress_ca_cert = "${base64encode(var.ingress_ca_cert_pem)}" + ingress_tls_cert = "${base64encode(var.ingress_cert_pem)}" + ingress_tls_key = "${base64encode(var.ingress_key_pem)}" + + identity_server_tls_cert = "${base64encode(var.identity_server_cert_pem)}" + identity_server_tls_key = "${base64encode(var.identity_server_key_pem)}" + identity_client_tls_cert = "${base64encode(var.identity_client_cert_pem)}" + identity_client_tls_key = "${base64encode(var.identity_client_key_pem)}" kubectl_client_id = "${var.kubectl_client_id}" kubectl_secret = "${random_id.kubectl_secret.b64}" diff --git a/modules/tectonic/crypto.tf b/modules/tectonic/crypto.tf index 84a6cbcd23..5fbb0db00c 100644 --- a/modules/tectonic/crypto.tf +++ b/modules/tectonic/crypto.tf @@ -15,100 +15,3 @@ resource "random_id" "console_secret" { resource "random_id" "tectonic_monitoring_auth_cookie_secret" { byte_length = 16 } - -# Ingress' server certificate - -resource "tls_private_key" "ingress" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_cert_request" "ingress" { - key_algorithm = "${tls_private_key.ingress.algorithm}" - private_key_pem = "${tls_private_key.ingress.private_key_pem}" - - subject { - common_name = "${element(split(":", var.base_address), 0)}" - } - - # subject commonName is deprecated per RFC2818 in favor of - # subjectAltName - dns_names = [ - "${element(split(":", var.base_address), 0)}", - ] -} - -resource "tls_locally_signed_cert" "ingress" { - cert_request_pem = "${tls_cert_request.ingress.cert_request_pem}" - - ca_key_algorithm = "${var.ca_key_alg}" - ca_private_key_pem = "${var.ca_key}" - ca_cert_pem = "${var.ca_cert}" - - validity_period_hours = 8760 - - allowed_uses = [ - "key_encipherment", - "digital_signature", - "server_auth", - "client_auth", - ] -} - -# Identity's gRPC server/client certificates - -resource "tls_private_key" "identity_server" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_cert_request" "identity_server" { - key_algorithm = "${tls_private_key.identity_server.algorithm}" - private_key_pem = "${tls_private_key.identity_server.private_key_pem}" - - subject { - common_name = "tectonic-identity-api.tectonic-system.svc.cluster.local" - } -} - -resource "tls_locally_signed_cert" "identity_server" { - cert_request_pem = "${tls_cert_request.identity_server.cert_request_pem}" - - ca_key_algorithm = "${var.ca_key_alg}" - ca_private_key_pem = "${var.ca_key}" - ca_cert_pem = "${var.ca_cert}" - - validity_period_hours = 8760 - - allowed_uses = [ - "server_auth", - ] -} - -resource "tls_private_key" "identity_client" { - algorithm = "RSA" - rsa_bits = "2048" -} - -resource "tls_cert_request" "identity_client" { - key_algorithm = "${tls_private_key.identity_client.algorithm}" - private_key_pem = "${tls_private_key.identity_client.private_key_pem}" - - subject { - common_name = "tectonic-identity-api.tectonic-system.svc.cluster.local" - } -} - -resource "tls_locally_signed_cert" "identity_client" { - cert_request_pem = "${tls_cert_request.identity_client.cert_request_pem}" - - ca_key_algorithm = "${var.ca_key_alg}" - ca_private_key_pem = "${var.ca_key}" - ca_cert_pem = "${var.ca_cert}" - - validity_period_hours = 8760 - - allowed_uses = [ - "client_auth", - ] -} diff --git a/modules/tectonic/resources/manifests/console/deployment.yaml b/modules/tectonic/resources/manifests/console/deployment.yaml index 2296a0007c..b8a81153ca 100644 --- a/modules/tectonic/resources/manifests/console/deployment.yaml +++ b/modules/tectonic/resources/manifests/console/deployment.yaml @@ -107,6 +107,8 @@ spec: configMapKeyRef: name: tectonic-config key: dexAPIHost + - name: BRIDGE_DEX_CLIENT_CA_FILE + value: /etc/tectonic-identity-grpc-client-secret/ca-cert image: ${console_image} imagePullPolicy: IfNotPresent livenessProbe: diff --git a/modules/tectonic/resources/manifests/secrets/ca-cert.yaml b/modules/tectonic/resources/manifests/secrets/ca-cert.yaml index d9c885e373..88f71093b8 100644 --- a/modules/tectonic/resources/manifests/secrets/ca-cert.yaml +++ b/modules/tectonic/resources/manifests/secrets/ca-cert.yaml @@ -5,4 +5,4 @@ metadata: namespace: tectonic-system type: Opaque data: - ca-cert: ${ca_cert} \ No newline at end of file + ca-cert: ${ingress_ca_cert} diff --git a/modules/tectonic/resources/manifests/secrets/identity-grpc-client.yaml b/modules/tectonic/resources/manifests/secrets/identity-grpc-client.yaml index d4bf1234a6..5312799626 100644 --- a/modules/tectonic/resources/manifests/secrets/identity-grpc-client.yaml +++ b/modules/tectonic/resources/manifests/secrets/identity-grpc-client.yaml @@ -7,4 +7,4 @@ type: Opaque data: tls-cert: ${identity_client_tls_cert} tls-key: ${identity_client_tls_key} - ca-cert: ${ca_cert} \ No newline at end of file + ca-cert: ${ca_cert} diff --git a/modules/tectonic/resources/manifests/secrets/identity-grpc-server.yaml b/modules/tectonic/resources/manifests/secrets/identity-grpc-server.yaml index 4d6541ab32..de48861cc8 100644 --- a/modules/tectonic/resources/manifests/secrets/identity-grpc-server.yaml +++ b/modules/tectonic/resources/manifests/secrets/identity-grpc-server.yaml @@ -7,4 +7,4 @@ type: Opaque data: tls-cert: ${identity_server_tls_cert} tls-key: ${identity_server_tls_key} - ca-cert: ${ca_cert} \ No newline at end of file + ca-cert: ${ca_cert} diff --git a/modules/tectonic/variables.tf b/modules/tectonic/variables.tf index f1a0b8fb05..5342cb4c6b 100644 --- a/modules/tectonic/variables.tf +++ b/modules/tectonic/variables.tf @@ -44,16 +44,6 @@ variable "ca_cert" { type = "string" } -variable "ca_key_alg" { - description = "Algorithm used to generate ca_key. Example: RSA." - type = "string" -} - -variable "ca_key" { - description = "Contents of a PEM-encoded CA key, used to generate Tectonic Console's server certificate. Leave blank to generate a new CA." - type = "string" -} - variable "base_address" { description = "Base address used to access the Tectonic Console, without protocol nor trailing forward slash (may contain a port). Example: console.example.com:30000." type = "string" @@ -129,3 +119,31 @@ EOF type = "string" } + +variable "ingress_ca_cert_pem" { + type = "string" +} + +variable "ingress_cert_pem" { + type = "string" +} + +variable "ingress_key_pem" { + type = "string" +} + +variable "identity_server_cert_pem" { + type = "string" +} + +variable "identity_server_key_pem" { + type = "string" +} + +variable "identity_client_cert_pem" { + type = "string" +} + +variable "identity_client_key_pem" { + type = "string" +} diff --git a/modules/tls/etcd/assets.tf b/modules/tls/etcd/assets.tf new file mode 100644 index 0000000000..32a848b299 --- /dev/null +++ b/modules/tls/etcd/assets.tf @@ -0,0 +1,63 @@ +# etcd assets +data "template_file" "etcd_ca_cert_pem" { + template = "${var.self_signed + ? join("", tls_self_signed_cert.etcd_ca.*.cert_pem) + : file(var.etcd_ca_cert_path) + }" +} + +data "template_file" "etcd_client_crt" { + template = "${var.self_signed + ? join("", tls_locally_signed_cert.etcd_client.*.cert_pem) + : file(var.etcd_client_cert_path) + }" +} + +data "template_file" "etcd_client_key" { + template = "${var.self_signed + ? join("", tls_private_key.etcd_client.*.private_key_pem) + : file(var.etcd_client_key_path) + }" +} + +resource "local_file" "etcd_ca_crt" { + count = "${var.self_signed || var.etcd_ca_cert_path != "/dev/null" ? 1 : 0}" + content = "${data.template_file.etcd_ca_cert_pem.rendered}" + filename = "./generated/tls/etcd-client-ca.crt" +} + +resource "local_file" "etcd_client_crt" { + count = "${var.self_signed || var.etcd_client_cert_path != "/dev/null" ? 1 : 0}" + content = "${data.template_file.etcd_client_crt.rendered}" + filename = "./generated/tls/etcd-client.crt" +} + +resource "local_file" "etcd_client_key" { + count = "${var.self_signed || var.etcd_client_key_path != "/dev/null" ? 1 : 0}" + content = "${data.template_file.etcd_client_key.rendered}" + filename = "./generated/tls/etcd-client.key" +} + +resource "local_file" "etcd_server_crt" { + count = "${var.self_signed ? 1 : 0}" + content = "${join("", tls_locally_signed_cert.etcd_server.*.cert_pem)}" + filename = "./generated/tls/etcd/server.crt" +} + +resource "local_file" "etcd_server_key" { + count = "${var.self_signed ? 1 : 0}" + content = "${join("", tls_private_key.etcd_server.*.private_key_pem)}" + filename = "./generated/tls/etcd/server.key" +} + +resource "local_file" "etcd_peer_crt" { + count = "${var.self_signed ? 1 : 0}" + content = "${join("", tls_locally_signed_cert.etcd_peer.*.cert_pem)}" + filename = "./generated/tls/etcd/peer.crt" +} + +resource "local_file" "etcd_peer_key" { + count = "${var.self_signed ? 1 : 0}" + content = "${join("", tls_private_key.etcd_peer.*.private_key_pem)}" + filename = "./generated/tls/etcd/peer.key" +} diff --git a/modules/bootkube/tls_etcd.tf b/modules/tls/etcd/main.tf similarity index 82% rename from modules/bootkube/tls_etcd.tf rename to modules/tls/etcd/main.tf index bf4e02fff4..a28b3ac165 100644 --- a/modules/bootkube/tls_etcd.tf +++ b/modules/tls/etcd/main.tf @@ -1,14 +1,14 @@ // root CA resource "tls_private_key" "etcd_ca" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" algorithm = "RSA" rsa_bits = "2048" } resource "tls_self_signed_cert" "etcd_ca" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" key_algorithm = "${tls_private_key.etcd_ca.algorithm}" private_key_pem = "${tls_private_key.etcd_ca.private_key_pem}" @@ -32,14 +32,14 @@ resource "tls_self_signed_cert" "etcd_ca" { // These are used for etcd-to-etcd member communcation resource "tls_private_key" "etcd_server" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" algorithm = "RSA" rsa_bits = "2048" } resource "tls_cert_request" "etcd_server" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" key_algorithm = "${tls_private_key.etcd_server.algorithm}" private_key_pem = "${tls_private_key.etcd_server.private_key_pem}" @@ -65,7 +65,7 @@ resource "tls_cert_request" "etcd_server" { } resource "tls_locally_signed_cert" "etcd_server" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" cert_request_pem = "${tls_cert_request.etcd_server.cert_request_pem}" @@ -85,14 +85,14 @@ resource "tls_locally_signed_cert" "etcd_server" { // These are used for "api server"-to-etcd and "etcd operator"-to-etcd client communication resource "tls_private_key" "etcd_client" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" algorithm = "RSA" rsa_bits = "2048" } resource "tls_cert_request" "etcd_client" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" key_algorithm = "${tls_private_key.etcd_client.algorithm}" private_key_pem = "${tls_private_key.etcd_client.private_key_pem}" @@ -104,7 +104,7 @@ resource "tls_cert_request" "etcd_client" { } resource "tls_locally_signed_cert" "etcd_client" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" cert_request_pem = "${tls_cert_request.etcd_client.cert_request_pem}" @@ -124,14 +124,14 @@ resource "tls_locally_signed_cert" "etcd_client" { // These are used for etcd-to-etcd member communcation resource "tls_private_key" "etcd_peer" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" algorithm = "RSA" rsa_bits = "2048" } resource "tls_cert_request" "etcd_peer" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" key_algorithm = "${tls_private_key.etcd_peer.algorithm}" private_key_pem = "${tls_private_key.etcd_peer.private_key_pem}" @@ -155,7 +155,7 @@ resource "tls_cert_request" "etcd_peer" { } resource "tls_locally_signed_cert" "etcd_peer" { - count = "${var.experimental_enabled || var.etcd_tls_enabled ? 1 : 0}" + count = "${var.self_signed ? 1 : 0}" cert_request_pem = "${tls_cert_request.etcd_peer.cert_request_pem}" diff --git a/modules/tls/etcd/outputs.tf b/modules/tls/etcd/outputs.tf new file mode 100644 index 0000000000..f883c7371b --- /dev/null +++ b/modules/tls/etcd/outputs.tf @@ -0,0 +1,48 @@ +output "etcd_ca_crt_pem" { + value = "${data.template_file.etcd_ca_cert_pem.rendered}" +} + +output "etcd_client_crt_pem" { + value = "${data.template_file.etcd_client_crt.rendered}" +} + +output "etcd_client_key_pem" { + value = "${data.template_file.etcd_client_key.rendered}" +} + +output "etcd_peer_crt_pem" { + value = "${join("", tls_locally_signed_cert.etcd_peer.*.cert_pem)}" +} + +output "etcd_peer_key_pem" { + value = "${join("", tls_private_key.etcd_peer.*.private_key_pem)}" +} + +output "etcd_server_crt_pem" { + value = "${join("", tls_locally_signed_cert.etcd_server.*.cert_pem)}" +} + +output "etcd_server_key_pem" { + value = "${join("", tls_private_key.etcd_server.*.private_key_pem)}" +} + +// The data.archive_file.etcd_tls_zip.id != "" assertion forces the etcd_tls_zip datasource to be run, +// hence ./.terraform/etcd_tls.zip must be generated and present. +output "etcd_tls_zip" { + value = "${data.archive_file.etcd_tls_zip.id != "" ? file("./.terraform/etcd_tls.zip") : ""}" +} + +output "id" { + value = "${sha1(" + ${data.archive_file.etcd_tls_zip.id}, + ${join(" ", + local_file.etcd_ca_crt.*.id, + local_file.etcd_server_crt.*.id, + local_file.etcd_server_key.*.id, + local_file.etcd_client_crt.*.id, + local_file.etcd_client_key.*.id, + local_file.etcd_peer_crt.*.id, + local_file.etcd_peer_key.*.id, + )} + ")}" +} diff --git a/modules/tls/etcd/variables.tf b/modules/tls/etcd/variables.tf new file mode 100644 index 0000000000..febfc4f476 --- /dev/null +++ b/modules/tls/etcd/variables.tf @@ -0,0 +1,29 @@ +// usually the caller sets this to: +// var.tectonic_experimental || var.tectonic_etcd_tls_enabled +variable "self_signed" { + description = < +-----END CERTIFICATE----- +EOF + + cert_pem = < +-----END CERTIFICATE----- +EOF + + key_pem = < +-----END RSA PRIVATE KEY----- +EOF +} +``` diff --git a/modules/tls/ingress/user-provided/outputs.tf b/modules/tls/ingress/user-provided/outputs.tf new file mode 100644 index 0000000000..29339deaf0 --- /dev/null +++ b/modules/tls/ingress/user-provided/outputs.tf @@ -0,0 +1,11 @@ +output "ca_cert_pem" { + value = "${var.ca_cert_pem}" +} + +output "cert_pem" { + value = "${var.cert_pem}" +} + +output "key_pem" { + value = "${var.key_pem}" +} diff --git a/modules/tls/ingress/user-provided/variables.tf b/modules/tls/ingress/user-provided/variables.tf new file mode 100644 index 0000000000..13f5980a8f --- /dev/null +++ b/modules/tls/ingress/user-provided/variables.tf @@ -0,0 +1,11 @@ +variable "ca_cert_pem" { + type = "string" +} + +variable "cert_pem" { + type = "string" +} + +variable "key_pem" { + type = "string" +} diff --git a/modules/tls/kube/self-signed/api.tf b/modules/tls/kube/self-signed/api.tf new file mode 100644 index 0000000000..14ac3e2646 --- /dev/null +++ b/modules/tls/kube/self-signed/api.tf @@ -0,0 +1,54 @@ +# Kubernetes API Server (resources/generated/tls/{apiserver.key,apiserver.crt}) +resource "tls_private_key" "apiserver" { + algorithm = "RSA" + rsa_bits = "2048" +} + +resource "tls_cert_request" "apiserver" { + key_algorithm = "${tls_private_key.apiserver.algorithm}" + private_key_pem = "${tls_private_key.apiserver.private_key_pem}" + + subject { + common_name = "kube-apiserver" + organization = "kube-master" + } + + dns_names = [ + "${replace(element(split(":", var.kube_apiserver_url), 1), "/", "")}", + "kubernetes", + "kubernetes.default", + "kubernetes.default.svc", + "kubernetes.default.svc.cluster.local", + ] + + ip_addresses = [ + "${cidrhost(var.service_cidr, 1)}", + ] +} + +resource "tls_locally_signed_cert" "apiserver" { + cert_request_pem = "${tls_cert_request.apiserver.cert_request_pem}" + + ca_key_algorithm = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" + ca_private_key_pem = "${var.ca_cert_pem == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key_pem}" + ca_cert_pem = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem): var.ca_cert_pem}" + + validity_period_hours = 8760 + + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + "client_auth", + ] +} + +resource "local_file" "apiserver_key" { + content = "${tls_private_key.apiserver.private_key_pem}" + filename = "./generated/tls/apiserver.key" +} + +resource "local_file" "apiserver_crt" { + content = "${tls_locally_signed_cert.apiserver.cert_pem}" + filename = "./generated/tls/apiserver.crt" +} diff --git a/modules/tls/kube/self-signed/ca.tf b/modules/tls/kube/self-signed/ca.tf new file mode 100644 index 0000000000..00e795d66e --- /dev/null +++ b/modules/tls/kube/self-signed/ca.tf @@ -0,0 +1,51 @@ +# NOTE: Across this module, the following syntax is used at various places: +# `"${var.ca_cert_pem == "" ? join(" ", tls_private_key.kube-ca.*.private_key_pem) : var.ca_key_pem}"` +# +# Due to https://github.com/hashicorp/hil/issues/50, both sides of conditions +# are evaluated, until one of them is discarded. Unfortunately, the +# `{tls_private_key/tls_self_signed_cert}.kube-ca` resources are created +# conditionally and might not be present - in which case an error is +# generated. Because a `count` is used on these ressources, the resources can be +# referenced as lists with the `.*` notation, and arrays are allowed to be +# empty. The `join()` interpolation function is then used to cast them back to +# a string. Since `count` can only be 0 or 1, the returned value is either empty +# (and discarded anyways) or the desired value. + +# Kubernetes CA (resources/generated/tls/{ca.crt,ca.key}) +resource "tls_private_key" "kube_ca" { + count = "${var.ca_cert_pem == "" ? 1 : 0}" + + algorithm = "RSA" + rsa_bits = "2048" +} + +resource "tls_self_signed_cert" "kube_ca" { + count = "${var.ca_cert_pem == "" ? 1 : 0}" + + key_algorithm = "${tls_private_key.kube_ca.algorithm}" + private_key_pem = "${tls_private_key.kube_ca.private_key_pem}" + + subject { + common_name = "kube-ca" + organization = "bootkube" + } + + is_ca_certificate = true + validity_period_hours = 8760 + + allowed_uses = [ + "key_encipherment", + "digital_signature", + "cert_signing", + ] +} + +resource "local_file" "kube_ca_key" { + content = "${var.ca_cert_pem == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key_pem}" + filename = "./generated/tls/ca.key" +} + +resource "local_file" "kube_ca_crt" { + content = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert_pem}" + filename = "./generated/tls/ca.crt" +} diff --git a/modules/tls/kube/self-signed/kubelet.tf b/modules/tls/kube/self-signed/kubelet.tf new file mode 100644 index 0000000000..03bd97beca --- /dev/null +++ b/modules/tls/kube/self-signed/kubelet.tf @@ -0,0 +1,42 @@ +# Kubelet +resource "tls_private_key" "kubelet" { + algorithm = "RSA" + rsa_bits = "2048" +} + +resource "tls_cert_request" "kubelet" { + key_algorithm = "${tls_private_key.kubelet.algorithm}" + private_key_pem = "${tls_private_key.kubelet.private_key_pem}" + + subject { + common_name = "kubelet" + organization = "system:masters" + } +} + +resource "tls_locally_signed_cert" "kubelet" { + cert_request_pem = "${tls_cert_request.kubelet.cert_request_pem}" + + ca_key_algorithm = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" + ca_private_key_pem = "${var.ca_cert_pem == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key_pem}" + ca_cert_pem = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert_pem}" + + validity_period_hours = 8760 + + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth", + "client_auth", + ] +} + +resource "local_file" "kubelet_key" { + content = "${tls_private_key.kubelet.private_key_pem}" + filename = "./generated/tls/kubelet.key" +} + +resource "local_file" "kubelet_crt" { + content = "${tls_locally_signed_cert.kubelet.cert_pem}" + filename = "./generated/tls/kubelet.crt" +} diff --git a/modules/tls/kube/self-signed/outputs.tf b/modules/tls/kube/self-signed/outputs.tf new file mode 100644 index 0000000000..3239299e7a --- /dev/null +++ b/modules/tls/kube/self-signed/outputs.tf @@ -0,0 +1,27 @@ +output "ca_cert_pem" { + value = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.cert_pem) : var.ca_cert_pem}" +} + +output "ca_key_alg" { + value = "${var.ca_cert_pem == "" ? join(" ", tls_self_signed_cert.kube_ca.*.key_algorithm) : var.ca_key_alg}" +} + +output "ca_key_pem" { + value = "${var.ca_cert_pem == "" ? join(" ", tls_private_key.kube_ca.*.private_key_pem) : var.ca_key_pem}" +} + +output "kubelet_cert_pem" { + value = "${tls_locally_signed_cert.kubelet.cert_pem}" +} + +output "kubelet_key_pem" { + value = "${tls_private_key.kubelet.private_key_pem}" +} + +output "apiserver_cert_pem" { + value = "${tls_locally_signed_cert.apiserver.cert_pem}" +} + +output "apiserver_key_pem" { + value = "${tls_private_key.apiserver.private_key_pem}" +} diff --git a/modules/tls/kube/self-signed/variables.tf b/modules/tls/kube/self-signed/variables.tf new file mode 100644 index 0000000000..18799d932d --- /dev/null +++ b/modules/tls/kube/self-signed/variables.tf @@ -0,0 +1,22 @@ +variable "ca_cert_pem" { + description = "PEM-encoded CA certificate (generated if blank)" + type = "string" +} + +variable "ca_key_alg" { + description = "Algorithm used to generate ca_key (required if ca_cert is specified)" + type = "string" +} + +variable "ca_key_pem" { + description = "PEM-encoded CA key (required if ca_cert is specified)" + type = "string" +} + +variable "kube_apiserver_url" { + type = "string" +} + +variable "service_cidr" { + type = "string" +} diff --git a/platforms/aws/main.tf b/platforms/aws/main.tf index 690572e20e..64d8b4b06e 100644 --- a/platforms/aws/main.tf +++ b/platforms/aws/main.tf @@ -80,7 +80,7 @@ module "etcd" { dns_enabled = "${!var.tectonic_experimental && length(compact(var.tectonic_etcd_servers)) == 0}" tls_enabled = "${var.tectonic_etcd_tls_enabled}" - tls_zip = "${module.bootkube.etcd_tls_zip}" + tls_zip = "${module.etcd_certs.etcd_tls_zip}" } module "ignition_masters" { diff --git a/platforms/aws/tectonic.tf b/platforms/aws/tectonic.tf index 2105415a6e..71fb8ee436 100644 --- a/platforms/aws/tectonic.tf +++ b/platforms/aws/tectonic.tf @@ -1,3 +1,50 @@ +module "kube_certs" { + source = "../../modules/tls/kube/self-signed" + + ca_cert_pem = "${var.tectonic_ca_cert}" + ca_key_alg = "${var.tectonic_ca_key_alg}" + ca_key_pem = "${var.tectonic_ca_key}" + kube_apiserver_url = "https://${module.masters.api_internal_fqdn}:443" + service_cidr = "${var.tectonic_service_cidr}" +} + +module "etcd_certs" { + source = "../../modules/tls/etcd" + + etcd_ca_cert_path = "${var.tectonic_etcd_ca_cert_path}" + etcd_client_cert_path = "${var.tectonic_etcd_client_cert_path}" + etcd_client_key_path = "${var.tectonic_etcd_client_key_path}" + self_signed = "${var.tectonic_experimental || var.tectonic_etcd_tls_enabled}" + service_cidr = "${var.tectonic_service_cidr}" + + etcd_cert_dns_names = [ + "${var.tectonic_cluster_name}-etcd-0.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-1.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-2.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-3.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-4.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-5.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-6.${var.tectonic_base_domain}", + ] +} + +module "ingress_certs" { + source = "../../modules/tls/ingress/self-signed" + + base_address = "${module.masters.ingress_internal_fqdn}" + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + +module "identity_certs" { + source = "../../modules/tls/identity/self-signed" + + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + module "bootkube" { source = "../../modules/bootkube" cloud_provider = "aws" @@ -11,10 +58,6 @@ module "bootkube" { container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" - ca_cert = "${var.tectonic_ca_cert}" - ca_key = "${var.tectonic_ca_key}" - ca_key_alg = "${var.tectonic_ca_key_alg}" - service_cidr = "${var.tectonic_service_cidr}" cluster_cidr = "${var.tectonic_cluster_cidr}" @@ -24,26 +67,24 @@ module "bootkube" { oidc_username_claim = "email" oidc_groups_claim = "groups" oidc_client_id = "tectonic-kubectl" - - etcd_endpoints = "${module.etcd.endpoints}" - etcd_ca_cert = "${var.tectonic_etcd_ca_cert_path}" - etcd_client_cert = "${var.tectonic_etcd_client_cert_path}" - etcd_client_key = "${var.tectonic_etcd_client_key_path}" - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - - etcd_cert_dns_names = [ - "${var.tectonic_cluster_name}-etcd-0.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-1.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-2.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-3.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-4.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-5.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-6.${var.tectonic_base_domain}", - ] - + oidc_ca_cert = "${module.ingress_certs.ca_cert_pem}" + + apiserver_cert_pem = "${module.kube_certs.apiserver_cert_pem}" + apiserver_key_pem = "${module.kube_certs.apiserver_key_pem}" + etcd_ca_cert_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + etcd_client_cert_pem = "${module.etcd_certs.etcd_client_crt_pem}" + etcd_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + etcd_peer_cert_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + etcd_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" + etcd_server_cert_pem = "${module.etcd_certs.etcd_server_crt_pem}" + etcd_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + kube_ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + kubelet_cert_pem = "${module.kube_certs.kubelet_cert_pem}" + kubelet_key_pem = "${module.kube_certs.kubelet_key_pem}" + + etcd_endpoints = "${module.etcd.endpoints}" experimental_enabled = "${var.tectonic_experimental}" - - master_count = "${var.tectonic_master_count}" + master_count = "${var.tectonic_master_count}" # The default behavior of Kubernetes's controller manager is to mark a node # as Unhealthy after 40s without an update from the node's kubelet. However, @@ -93,10 +134,17 @@ module "tectonic" { update_app_id = "${var.tectonic_update_app_id}" update_server = "${var.tectonic_update_server}" - ca_generated = "${module.bootkube.ca_cert == "" ? false : true}" - ca_cert = "${module.bootkube.ca_cert}" - ca_key_alg = "${module.bootkube.ca_key_alg}" - ca_key = "${module.bootkube.ca_key}" + ca_generated = "${var.tectonic_ca_cert == "" ? false : true}" + ca_cert = "${module.kube_certs.ca_cert_pem}" + + ingress_ca_cert_pem = "${module.ingress_certs.ca_cert_pem}" + ingress_cert_pem = "${module.ingress_certs.cert_pem}" + ingress_key_pem = "${module.ingress_certs.key_pem}" + + identity_client_cert_pem = "${module.identity_certs.client_cert_pem}" + identity_client_key_pem = "${module.identity_certs.client_key_pem}" + identity_server_cert_pem = "${module.identity_certs.server_cert_pem}" + identity_server_key_pem = "${module.identity_certs.server_key_pem}" console_client_id = "tectonic-console" kubectl_client_id = "tectonic-kubectl" @@ -144,5 +192,5 @@ data "archive_file" "assets" { # Additionally, data sources do not support managing any lifecycle whatsoever, # and therefore, the archive is never deleted. To avoid cluttering the module # folder, we write it in the Terraform managed hidden folder `.terraform`. - output_path = "./.terraform/generated_${sha1("${module.tectonic.id} ${module.bootkube.id} ${module.flannel-vxlan.id} ${module.calico-network-policy.id}")}.zip" + output_path = "./.terraform/generated_${sha1("${module.etcd_certs.id} ${module.tectonic.id} ${module.bootkube.id} ${module.flannel-vxlan.id} ${module.calico-network-policy.id}")}.zip" } diff --git a/platforms/azure/bootstrap.tf b/platforms/azure/bootstrap.tf index c85b3cace0..b5599f5de7 100644 --- a/platforms/azure/bootstrap.tf +++ b/platforms/azure/bootstrap.tf @@ -7,6 +7,6 @@ locals { module "bootstrapper" { source = "../../modules/bootstrap-ssh" - # depends_on = ["module.vnet", "module.dns", "module.etcd", "module.masters", "module.bootkube", "module.tectonic", "module.flannel-vxlan", "module.calico-network-policy"] + # depends_on = ["module.etcd_certs", "module.vnet", "module.dns", "module.etcd", "module.masters", "module.bootkube", "module.tectonic", "module.flannel-vxlan", "module.calico-network-policy"] bootstrapping_host = "${local.bootstrapping_host}" } diff --git a/platforms/azure/main.tf b/platforms/azure/main.tf index 985d5753fd..875a20c613 100644 --- a/platforms/azure/main.tf +++ b/platforms/azure/main.tf @@ -68,13 +68,13 @@ module "etcd" { cl_channel = "${var.tectonic_cl_channel}" tls_enabled = "${var.tectonic_etcd_tls_enabled}" - tls_ca_crt_pem = "${module.bootkube.etcd_ca_crt_pem}" - tls_server_crt_pem = "${module.bootkube.etcd_server_crt_pem}" - tls_server_key_pem = "${module.bootkube.etcd_server_key_pem}" - tls_client_crt_pem = "${module.bootkube.etcd_client_crt_pem}" - tls_client_key_pem = "${module.bootkube.etcd_client_key_pem}" - tls_peer_crt_pem = "${module.bootkube.etcd_peer_crt_pem}" - tls_peer_key_pem = "${module.bootkube.etcd_peer_key_pem}" + tls_ca_crt_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + tls_server_crt_pem = "${module.etcd_certs.etcd_server_crt_pem}" + tls_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + tls_client_crt_pem = "${module.etcd_certs.etcd_client_crt_pem}" + tls_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + tls_peer_crt_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + tls_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" extra_tags = "${var.tectonic_azure_extra_tags}" } diff --git a/platforms/azure/tectonic.tf b/platforms/azure/tectonic.tf index 4bb64817eb..8dba762258 100644 --- a/platforms/azure/tectonic.tf +++ b/platforms/azure/tectonic.tf @@ -1,3 +1,42 @@ +module "kube_certs" { + source = "../../modules/tls/kube/self-signed" + + ca_cert_pem = "${var.tectonic_ca_cert}" + ca_key_alg = "${var.tectonic_ca_key_alg}" + ca_key_pem = "${var.tectonic_ca_key}" + kube_apiserver_url = "https://${module.vnet.api_fqdn}:443" + service_cidr = "${var.tectonic_service_cidr}" +} + +module "etcd_certs" { + source = "../../modules/tls/etcd" + + etcd_ca_cert_path = "${var.tectonic_etcd_ca_cert_path}" + etcd_client_cert_path = "${var.tectonic_etcd_client_cert_path}" + etcd_client_key_path = "${var.tectonic_etcd_client_key_path}" + self_signed = "${var.tectonic_experimental || var.tectonic_etcd_tls_enabled}" + service_cidr = "${var.tectonic_service_cidr}" + + etcd_cert_dns_names = "${module.etcd.node_names}" +} + +module "ingress_certs" { + source = "../../modules/tls/ingress/self-signed" + + base_address = "${module.vnet.ingress_fqdn}" + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + +module "identity_certs" { + source = "../../modules/tls/identity/self-signed" + + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + module "bootkube" { source = "../../modules/bootkube" @@ -13,10 +52,6 @@ module "bootkube" { container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" - ca_cert = "${var.tectonic_ca_cert}" - ca_key = "${var.tectonic_ca_key}" - ca_key_alg = "${var.tectonic_ca_key_alg}" - service_cidr = "${var.tectonic_service_cidr}" cluster_cidr = "${var.tectonic_cluster_cidr}" @@ -26,14 +61,22 @@ module "bootkube" { oidc_username_claim = "email" oidc_groups_claim = "groups" oidc_client_id = "tectonic-kubectl" - - etcd_endpoints = "${module.etcd.node_names}" - etcd_cert_dns_names = "${module.etcd.node_names}" - etcd_ca_cert = "${var.tectonic_etcd_ca_cert_path}" - etcd_client_cert = "${var.tectonic_etcd_client_cert_path}" - etcd_client_key = "${var.tectonic_etcd_client_key_path}" - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - + oidc_ca_cert = "${module.ingress_certs.ca_cert_pem}" + + apiserver_cert_pem = "${module.kube_certs.apiserver_cert_pem}" + apiserver_key_pem = "${module.kube_certs.apiserver_key_pem}" + etcd_ca_cert_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + etcd_client_cert_pem = "${module.etcd_certs.etcd_client_crt_pem}" + etcd_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + etcd_peer_cert_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + etcd_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" + etcd_server_cert_pem = "${module.etcd_certs.etcd_server_crt_pem}" + etcd_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + kube_ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + kubelet_cert_pem = "${module.kube_certs.kubelet_cert_pem}" + kubelet_key_pem = "${module.kube_certs.kubelet_key_pem}" + + etcd_endpoints = "${module.etcd.node_names}" experimental_enabled = "${var.tectonic_experimental}" master_count = "${var.tectonic_master_count}" @@ -64,10 +107,17 @@ module "tectonic" { update_app_id = "${var.tectonic_update_app_id}" update_server = "${var.tectonic_update_server}" - ca_generated = "${module.bootkube.ca_cert == "" ? false : true}" - ca_cert = "${module.bootkube.ca_cert}" - ca_key_alg = "${module.bootkube.ca_key_alg}" - ca_key = "${module.bootkube.ca_key}" + ca_generated = "${var.tectonic_ca_cert == "" ? false : true}" + ca_cert = "${module.kube_certs.ca_cert_pem}" + + ingress_ca_cert_pem = "${module.ingress_certs.ca_cert_pem}" + ingress_cert_pem = "${module.ingress_certs.cert_pem}" + ingress_key_pem = "${module.ingress_certs.key_pem}" + + identity_client_cert_pem = "${module.identity_certs.client_cert_pem}" + identity_client_key_pem = "${module.identity_certs.client_key_pem}" + identity_server_cert_pem = "${module.identity_certs.server_cert_pem}" + identity_server_key_pem = "${module.identity_certs.server_key_pem}" console_client_id = "tectonic-console" kubectl_client_id = "tectonic-kubectl" diff --git a/platforms/metal/remote.tf b/platforms/metal/remote.tf index b8d02dee2d..56d92dbd23 100644 --- a/platforms/metal/remote.tf +++ b/platforms/metal/remote.tf @@ -9,27 +9,27 @@ resource "null_resource" "etcd_secrets" { } provisioner "file" { - content = "${module.bootkube.etcd_ca_crt_pem}" + content = "${module.etcd_certs.etcd_ca_crt_pem}" destination = "$HOME/etcd_ca.crt" } provisioner "file" { - content = "${module.bootkube.etcd_server_crt_pem}" + content = "${module.etcd_certs.etcd_server_crt_pem}" destination = "$HOME/etcd_server.crt" } provisioner "file" { - content = "${module.bootkube.etcd_server_key_pem}" + content = "${module.etcd_certs.etcd_server_key_pem}" destination = "$HOME/etcd_server.key" } provisioner "file" { - content = "${module.bootkube.etcd_peer_crt_pem}" + content = "${module.etcd_certs.etcd_peer_crt_pem}" destination = "$HOME/etcd_peer.crt" } provisioner "file" { - content = "${module.bootkube.etcd_peer_key_pem}" + content = "${module.etcd_certs.etcd_peer_key_pem}" destination = "$HOME/etcd_peer.key" } diff --git a/platforms/metal/tectonic.tf b/platforms/metal/tectonic.tf index 163eb6c704..44678580fb 100644 --- a/platforms/metal/tectonic.tf +++ b/platforms/metal/tectonic.tf @@ -1,23 +1,57 @@ +module "kube_certs" { + source = "../../modules/tls/kube/self-signed" + + ca_cert_pem = "${var.tectonic_ca_cert}" + ca_key_alg = "${var.tectonic_ca_key_alg}" + ca_key_pem = "${var.tectonic_ca_key}" + kube_apiserver_url = "https://${var.tectonic_metal_controller_domain}:443" + service_cidr = "${var.tectonic_service_cidr}" +} + +module "etcd_certs" { + source = "../../modules/tls/etcd" + + etcd_ca_cert_path = "${var.tectonic_etcd_ca_cert_path}" + etcd_client_cert_path = "${var.tectonic_etcd_client_cert_path}" + etcd_client_key_path = "${var.tectonic_etcd_client_key_path}" + self_signed = "${var.tectonic_experimental || var.tectonic_etcd_tls_enabled}" + service_cidr = "${var.tectonic_service_cidr}" + + etcd_cert_dns_names = "${var.tectonic_metal_controller_domains}" +} + +module "ingress_certs" { + source = "../../modules/tls/ingress/self-signed" + + base_address = "${var.tectonic_metal_ingress_domain}" + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + +module "identity_certs" { + source = "../../modules/tls/identity/self-signed" + + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + module "bootkube" { - source = "../../modules/bootkube" - cloud_provider = "" + source = "../../modules/bootkube" + + cloud_provider = "" + cloud_provider_config = "" cluster_name = "${var.tectonic_cluster_name}" - # Address of kube-apiserver kube_apiserver_url = "https://${var.tectonic_metal_controller_domain}:443" - - # Address of Identity service - oidc_issuer_url = "https://${var.tectonic_metal_ingress_domain}/identity" + oidc_issuer_url = "https://${var.tectonic_metal_ingress_domain}/identity" # platform-independent defaults container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" - ca_cert = "${var.tectonic_ca_cert}" - ca_key = "${var.tectonic_ca_key}" - ca_key_alg = "${var.tectonic_ca_key_alg}" - service_cidr = "${var.tectonic_service_cidr}" cluster_cidr = "${var.tectonic_cluster_cidr}" @@ -27,6 +61,20 @@ module "bootkube" { oidc_username_claim = "email" oidc_groups_claim = "groups" oidc_client_id = "tectonic-kubectl" + oidc_ca_cert = "${module.ingress_certs.ca_cert_pem}" + + apiserver_cert_pem = "${module.kube_certs.apiserver_cert_pem}" + apiserver_key_pem = "${module.kube_certs.apiserver_key_pem}" + etcd_ca_cert_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + etcd_client_cert_pem = "${module.etcd_certs.etcd_client_crt_pem}" + etcd_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + etcd_peer_cert_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + etcd_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" + etcd_server_cert_pem = "${module.etcd_certs.etcd_server_crt_pem}" + etcd_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + kube_ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + kubelet_cert_pem = "${module.kube_certs.kubelet_cert_pem}" + kubelet_key_pem = "${module.kube_certs.kubelet_key_pem}" etcd_endpoints = "${split(",", length(compact(var.tectonic_etcd_servers)) == 0 @@ -34,12 +82,6 @@ module "bootkube" { : join(",", var.tectonic_etcd_servers) )}" - etcd_ca_cert = "${var.tectonic_etcd_ca_cert_path}" - etcd_client_cert = "${var.tectonic_etcd_client_cert_path}" - etcd_client_key = "${var.tectonic_etcd_client_key_path}" - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - etcd_cert_dns_names = "${var.tectonic_metal_controller_domains}" - experimental_enabled = "${var.tectonic_experimental}" master_count = "${length(var.tectonic_metal_controller_names)}" @@ -53,12 +95,10 @@ module "tectonic" { cluster_name = "${var.tectonic_cluster_name}" - # Address of kube-apiserver + base_address = "${var.tectonic_metal_ingress_domain}" kube_apiserver_url = "https://${var.tectonic_metal_controller_domain}:443" # Address of the Tectonic console (without protocol) - base_address = "${var.tectonic_metal_ingress_domain}" - container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" @@ -72,10 +112,17 @@ module "tectonic" { update_app_id = "${var.tectonic_update_app_id}" update_server = "${var.tectonic_update_server}" - ca_generated = "${module.bootkube.ca_cert == "" ? false : true}" - ca_cert = "${module.bootkube.ca_cert}" - ca_key_alg = "${module.bootkube.ca_key_alg}" - ca_key = "${module.bootkube.ca_key}" + ca_generated = "${var.tectonic_ca_cert == "" ? false : true}" + ca_cert = "${module.kube_certs.ca_cert_pem}" + + ingress_ca_cert_pem = "${module.ingress_certs.ca_cert_pem}" + ingress_cert_pem = "${module.ingress_certs.cert_pem}" + ingress_key_pem = "${module.ingress_certs.key_pem}" + + identity_client_cert_pem = "${module.identity_certs.client_cert_pem}" + identity_client_key_pem = "${module.identity_certs.client_key_pem}" + identity_server_cert_pem = "${module.identity_certs.server_cert_pem}" + identity_server_key_pem = "${module.identity_certs.server_key_pem}" console_client_id = "tectonic-console" kubectl_client_id = "tectonic-kubectl" diff --git a/platforms/openstack/neutron/main.tf b/platforms/openstack/neutron/main.tf index dd6c576478..155954d749 100644 --- a/platforms/openstack/neutron/main.tf +++ b/platforms/openstack/neutron/main.tf @@ -2,9 +2,58 @@ provider "openstack" { version = "0.2.1" } +module "kube_certs" { + source = "../../../modules/tls/kube/self-signed" + + ca_cert_pem = "${var.tectonic_ca_cert}" + ca_key_alg = "${var.tectonic_ca_key_alg}" + ca_key_pem = "${var.tectonic_ca_key}" + kube_apiserver_url = "https://${var.tectonic_cluster_name}-k8s.${var.tectonic_base_domain}:443" + service_cidr = "${var.tectonic_service_cidr}" +} + +module "etcd_certs" { + source = "../../../modules/tls/etcd" + + etcd_ca_cert_path = "${var.tectonic_etcd_ca_cert_path}" + etcd_client_cert_path = "${var.tectonic_etcd_client_cert_path}" + etcd_client_key_path = "${var.tectonic_etcd_client_key_path}" + self_signed = "${var.tectonic_experimental || var.tectonic_etcd_tls_enabled}" + service_cidr = "${var.tectonic_service_cidr}" + + etcd_cert_dns_names = [ + "${var.tectonic_cluster_name}-etcd-0.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-1.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-2.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-3.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-4.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-5.${var.tectonic_base_domain}", + "${var.tectonic_cluster_name}-etcd-6.${var.tectonic_base_domain}", + ] +} + +module "ingress_certs" { + source = "../../../modules/tls/ingress/self-signed" + + base_address = "${var.tectonic_cluster_name}.${var.tectonic_base_domain}" + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + +module "identity_certs" { + source = "../../../modules/tls/identity/self-signed" + + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + module "bootkube" { - source = "../../../modules/bootkube" - cloud_provider = "" + source = "../../../modules/bootkube" + + cloud_provider = "" + cloud_provider_config = "" cluster_name = "${var.tectonic_cluster_name}" @@ -15,10 +64,6 @@ module "bootkube" { container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" - ca_cert = "${var.tectonic_ca_cert}" - ca_key = "${var.tectonic_ca_key}" - ca_key_alg = "${var.tectonic_ca_key_alg}" - service_cidr = "${var.tectonic_service_cidr}" cluster_cidr = "${var.tectonic_cluster_cidr}" @@ -28,23 +73,22 @@ module "bootkube" { oidc_username_claim = "email" oidc_groups_claim = "groups" oidc_client_id = "tectonic-kubectl" - - etcd_endpoints = "${module.dns.etcd_a_nodes}" - etcd_ca_cert = "${var.tectonic_etcd_ca_cert_path}" - etcd_client_cert = "${var.tectonic_etcd_client_cert_path}" - etcd_client_key = "${var.tectonic_etcd_client_key_path}" - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - - etcd_cert_dns_names = [ - "${var.tectonic_cluster_name}-etcd-0.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-1.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-2.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-3.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-4.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-5.${var.tectonic_base_domain}", - "${var.tectonic_cluster_name}-etcd-6.${var.tectonic_base_domain}", - ] - + oidc_ca_cert = "${module.ingress_certs.ca_cert_pem}" + + apiserver_cert_pem = "${module.kube_certs.apiserver_cert_pem}" + apiserver_key_pem = "${module.kube_certs.apiserver_key_pem}" + etcd_ca_cert_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + etcd_client_cert_pem = "${module.etcd_certs.etcd_client_crt_pem}" + etcd_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + etcd_peer_cert_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + etcd_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" + etcd_server_cert_pem = "${module.etcd_certs.etcd_server_crt_pem}" + etcd_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + kube_ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + kubelet_cert_pem = "${module.kube_certs.kubelet_cert_pem}" + kubelet_key_pem = "${module.kube_certs.kubelet_key_pem}" + + etcd_endpoints = "${module.dns.etcd_a_nodes}" experimental_enabled = "${var.tectonic_experimental}" master_count = "${var.tectonic_master_count}" @@ -75,10 +119,17 @@ module "tectonic" { update_app_id = "${var.tectonic_update_app_id}" update_server = "${var.tectonic_update_server}" - ca_generated = "${module.bootkube.ca_cert == "" ? false : true}" - ca_cert = "${module.bootkube.ca_cert}" - ca_key_alg = "${module.bootkube.ca_key_alg}" - ca_key = "${module.bootkube.ca_key}" + ca_generated = "${var.tectonic_ca_cert == "" ? false : true}" + ca_cert = "${module.kube_certs.ca_cert_pem}" + + ingress_ca_cert_pem = "${module.ingress_certs.ca_cert_pem}" + ingress_cert_pem = "${module.ingress_certs.cert_pem}" + ingress_key_pem = "${module.ingress_certs.key_pem}" + + identity_client_cert_pem = "${module.identity_certs.client_cert_pem}" + identity_client_key_pem = "${module.identity_certs.client_key_pem}" + identity_server_cert_pem = "${module.identity_certs.server_cert_pem}" + identity_server_key_pem = "${module.identity_certs.server_key_pem}" console_client_id = "tectonic-console" kubectl_client_id = "tectonic-kubectl" @@ -105,13 +156,13 @@ EOF tectonic_experimental = "${var.tectonic_experimental}" tls_enabled = "${var.tectonic_etcd_tls_enabled}" - tls_ca_crt_pem = "${module.bootkube.etcd_ca_crt_pem}" - tls_server_crt_pem = "${module.bootkube.etcd_server_crt_pem}" - tls_server_key_pem = "${module.bootkube.etcd_server_key_pem}" - tls_client_crt_pem = "${module.bootkube.etcd_client_crt_pem}" - tls_client_key_pem = "${module.bootkube.etcd_client_key_pem}" - tls_peer_crt_pem = "${module.bootkube.etcd_peer_crt_pem}" - tls_peer_key_pem = "${module.bootkube.etcd_peer_key_pem}" + tls_ca_crt_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + tls_server_crt_pem = "${module.etcd_certs.etcd_server_crt_pem}" + tls_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + tls_client_crt_pem = "${module.etcd_certs.etcd_client_crt_pem}" + tls_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + tls_peer_crt_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + tls_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" instance_count = "${var.tectonic_etcd_count}" } diff --git a/platforms/vmware/main.tf b/platforms/vmware/main.tf index 66eadb8e54..fdd64eb368 100644 --- a/platforms/vmware/main.tf +++ b/platforms/vmware/main.tf @@ -12,13 +12,13 @@ module "etcd" { base_domain = "${var.tectonic_base_domain}" external_endpoints = ["${compact(var.tectonic_etcd_servers)}"] - tls_ca_crt_pem = "${module.bootkube.etcd_ca_crt_pem}" - tls_server_crt_pem = "${module.bootkube.etcd_server_crt_pem}" - tls_server_key_pem = "${module.bootkube.etcd_server_key_pem}" - tls_client_crt_pem = "${module.bootkube.etcd_client_crt_pem}" - tls_client_key_pem = "${module.bootkube.etcd_client_key_pem}" - tls_peer_key_pem = "${module.bootkube.etcd_peer_key_pem}" - tls_peer_crt_pem = "${module.bootkube.etcd_peer_crt_pem}" + tls_ca_crt_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + tls_server_crt_pem = "${module.etcd_certs.etcd_server_crt_pem}" + tls_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + tls_client_crt_pem = "${module.etcd_certs.etcd_client_crt_pem}" + tls_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + tls_peer_crt_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + tls_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" hostname = "${var.tectonic_vmware_etcd_hostnames}" dns_server = "${var.tectonic_vmware_node_dns}" diff --git a/platforms/vmware/tectonic.tf b/platforms/vmware/tectonic.tf index a37abf2d7d..564f26221e 100644 --- a/platforms/vmware/tectonic.tf +++ b/platforms/vmware/tectonic.tf @@ -1,23 +1,60 @@ +module "kube_certs" { + source = "../../modules/tls/kube/self-signed" + + ca_cert_pem = "${var.tectonic_ca_cert}" + ca_key_alg = "${var.tectonic_ca_key_alg}" + ca_key_pem = "${var.tectonic_ca_key}" + kube_apiserver_url = "https://${var.tectonic_vmware_controller_domain}:443" + service_cidr = "${var.tectonic_service_cidr}" +} + +module "etcd_certs" { + source = "../../modules/tls/etcd" + + etcd_ca_cert_path = "${var.tectonic_etcd_ca_cert_path}" + etcd_client_cert_path = "${var.tectonic_etcd_client_cert_path}" + etcd_client_key_path = "${var.tectonic_etcd_client_key_path}" + self_signed = "${var.tectonic_experimental || var.tectonic_etcd_tls_enabled}" + service_cidr = "${var.tectonic_service_cidr}" + + etcd_cert_dns_names = ["${formatlist("%s.%s", + values(var.tectonic_vmware_etcd_hostnames), + var.tectonic_base_domain + )}"] +} + +module "ingress_certs" { + source = "../../modules/tls/ingress/self-signed" + + base_address = "${var.tectonic_vmware_ingress_domain}" + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + +module "identity_certs" { + source = "../../modules/tls/identity/self-signed" + + ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + ca_key_alg = "${module.kube_certs.ca_key_alg}" + ca_key_pem = "${module.kube_certs.ca_key_pem}" +} + module "bootkube" { - source = "../../modules/bootkube" - cloud_provider = "" + source = "../../modules/bootkube" + + cloud_provider = "" + cloud_provider_config = "" cluster_name = "${var.tectonic_cluster_name}" - # Address of kube-apiserver kube_apiserver_url = "https://${var.tectonic_vmware_controller_domain}:443" - - # Address of Identity service - oidc_issuer_url = "https://${var.tectonic_vmware_ingress_domain}/identity" + oidc_issuer_url = "https://${var.tectonic_vmware_ingress_domain}/identity" # Platform-independent variables wiring, do not modify. container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" - ca_cert = "${var.tectonic_ca_cert}" - ca_key = "${var.tectonic_ca_key}" - ca_key_alg = "${var.tectonic_ca_key_alg}" - service_cidr = "${var.tectonic_service_cidr}" cluster_cidr = "${var.tectonic_cluster_cidr}" @@ -27,20 +64,22 @@ module "bootkube" { oidc_username_claim = "email" oidc_groups_claim = "groups" oidc_client_id = "tectonic-kubectl" - - etcd_endpoints = "${formatlist("%s.%s", values(var.tectonic_vmware_etcd_hostnames), var.tectonic_base_domain)}" - etcd_ca_cert = "${var.tectonic_etcd_ca_cert_path}" - etcd_client_cert = "${var.tectonic_etcd_client_cert_path}" - etcd_client_key = "${var.tectonic_etcd_client_key_path}" - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - - etcd_cert_dns_names = ["${formatlist("%s.%s", - values(var.tectonic_vmware_etcd_hostnames), - var.tectonic_base_domain - )}"] - - etcd_tls_enabled = "${var.tectonic_etcd_tls_enabled}" - + oidc_ca_cert = "${module.ingress_certs.ca_cert_pem}" + + apiserver_cert_pem = "${module.kube_certs.apiserver_cert_pem}" + apiserver_key_pem = "${module.kube_certs.apiserver_key_pem}" + etcd_ca_cert_pem = "${module.etcd_certs.etcd_ca_crt_pem}" + etcd_client_cert_pem = "${module.etcd_certs.etcd_client_crt_pem}" + etcd_client_key_pem = "${module.etcd_certs.etcd_client_key_pem}" + etcd_peer_cert_pem = "${module.etcd_certs.etcd_peer_crt_pem}" + etcd_peer_key_pem = "${module.etcd_certs.etcd_peer_key_pem}" + etcd_server_cert_pem = "${module.etcd_certs.etcd_server_crt_pem}" + etcd_server_key_pem = "${module.etcd_certs.etcd_server_key_pem}" + kube_ca_cert_pem = "${module.kube_certs.ca_cert_pem}" + kubelet_cert_pem = "${module.kube_certs.kubelet_cert_pem}" + kubelet_key_pem = "${module.kube_certs.kubelet_key_pem}" + + etcd_endpoints = "${formatlist("%s.%s", values(var.tectonic_vmware_etcd_hostnames), var.tectonic_base_domain)}" experimental_enabled = "${var.tectonic_experimental}" master_count = "${var.tectonic_master_count}" @@ -54,12 +93,9 @@ module "tectonic" { cluster_name = "${var.tectonic_cluster_name}" - # Address of kube-apiserver + base_address = "${var.tectonic_vmware_ingress_domain}" kube_apiserver_url = "https://${var.tectonic_vmware_controller_domain}:443" - # Address of the Tectonic console (without protocol) - base_address = "${var.tectonic_vmware_ingress_domain}" - # Platform-independent variables wiring, do not modify. container_images = "${var.tectonic_container_images}" versions = "${var.tectonic_versions}" @@ -74,10 +110,17 @@ module "tectonic" { update_app_id = "${var.tectonic_update_app_id}" update_server = "${var.tectonic_update_server}" - ca_generated = "${module.bootkube.ca_cert == "" ? false : true}" - ca_cert = "${module.bootkube.ca_cert}" - ca_key_alg = "${module.bootkube.ca_key_alg}" - ca_key = "${module.bootkube.ca_key}" + ca_generated = "${var.tectonic_ca_cert == "" ? false : true}" + ca_cert = "${module.kube_certs.ca_cert_pem}" + + ingress_ca_cert_pem = "${module.ingress_certs.ca_cert_pem}" + ingress_cert_pem = "${module.ingress_certs.cert_pem}" + ingress_key_pem = "${module.ingress_certs.key_pem}" + + identity_client_cert_pem = "${module.identity_certs.client_cert_pem}" + identity_client_key_pem = "${module.identity_certs.client_key_pem}" + identity_server_cert_pem = "${module.identity_certs.server_cert_pem}" + identity_server_key_pem = "${module.identity_certs.server_key_pem}" console_client_id = "tectonic-console" kubectl_client_id = "tectonic-kubectl" @@ -125,5 +168,5 @@ data "archive_file" "assets" { # Additionally, data sources do not support managing any lifecycle whatsoever, # and therefore, the archive is never deleted. To avoid cluttering the module # folder, we write it in the Terraform managed hidden folder `.terraform`. - output_path = "./.terraform/generated_${sha1("${module.tectonic.id} ${module.bootkube.id} ${module.flannel-vxlan.id} ${module.calico-network-policy.id}")}.zip" + output_path = "./.terraform/generated_${sha1("${module.etcd_certs.id} ${module.tectonic.id} ${module.bootkube.id} ${module.flannel-vxlan.id} ${module.calico-network-policy.id}")}.zip" }