Skip to content

Instantly share code, notes, and snippets.

@mauilion
Last active November 9, 2021 21:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mauilion/23691ebd727324d8bdbd012771097f13 to your computer and use it in GitHub Desktop.
Save mauilion/23691ebd727324d8bdbd012771097f13 to your computer and use it in GitHub Desktop.
terraform to generate tls assets for etcd.
*tfstate*
.terraform
etcd
certs
ca-keys
provider "tls" {
version = "1.0.0"
}
locals {
dns_names = [
"node001.metal.k8s.work",
"node002.metal.k8s.work",
"node003.metal.k8s.work",
]
kube_apiserver_certs = false
client_cert = true
organization = "dcooley-really-neat-ca"
algorithm = "RSA"
rsa_bits = "2048"
}
// root ca is self-signed
resource "tls_private_key" "root_ca" {
algorithm = "${local.algorithm}"
rsa_bits = "${local.rsa_bits}"
}
resource "local_file" "root_ca_key" {
content = "${tls_private_key.root_ca.0.private_key_pem}"
filename = "./ca-keys/root_ca.key"
}
resource "tls_self_signed_cert" "root_ca" {
key_algorithm = "${tls_private_key.root_ca.algorithm}"
private_key_pem = "${tls_private_key.root_ca.private_key_pem}"
subject {
common_name = "root-ca"
organization = "${local.organization}"
}
is_ca_certificate = true
validity_period_hours = 26280
allowed_uses = [
"key_encipherment",
"digital_signature",
"cert_signing",
]
}
resource "local_file" "root_ca_cert" {
content = "${tls_self_signed_cert.root_ca.0.cert_pem}"
filename = "./certs/root_ca.crt"
}
// intermediate cert is signed by root ca
resource "tls_private_key" "intermediate_ca" {
algorithm = "${local.algorithm}"
rsa_bits = "${local.rsa_bits}"
}
resource "local_file" "intermediate_ca_key" {
content = "${tls_private_key.intermediate_ca.0.private_key_pem}"
filename = "./ca-keys/intermediate_ca.key"
}
resource "tls_cert_request" "intermediate_ca" {
key_algorithm = "${tls_private_key.intermediate_ca.algorithm}"
private_key_pem = "${tls_private_key.intermediate_ca.private_key_pem}"
subject {
common_name = "intermediate-ca"
organization = "${local.organization}"
}
}
resource "tls_locally_signed_cert" "intermediate_ca" {
cert_request_pem = "${tls_cert_request.intermediate_ca.0.cert_request_pem}"
ca_key_algorithm = "${tls_private_key.root_ca.algorithm}"
ca_private_key_pem = "${tls_private_key.root_ca.private_key_pem}"
ca_cert_pem = "${tls_self_signed_cert.root_ca.cert_pem}"
is_ca_certificate = true
validity_period_hours = 26280
allowed_uses = [
"key_encipherment",
"digital_signature",
"cert_signing",
]
}
resource "local_file" "intermediate_ca_cert" {
content = "${tls_locally_signed_cert.intermediate_ca.0.cert_pem}"
filename = "./certs/intermediate_ca.crt"
}
// server certs and key.
resource "tls_private_key" "server" {
count = "${length(local.dns_names)}"
algorithm = "${local.algorithm}"
rsa_bits = "${local.rsa_bits}"
}
resource "local_file" "server_key" {
count = "${length(local.dns_names)}"
content = "${element(tls_private_key.server.*.private_key_pem, count.index)}"
filename = "./certs/${local.dns_names[count.index]}.key"
}
resource "random_id" "server" {
keepers = {
name = "${local.organization}"
}
byte_length = 8
}
resource "tls_cert_request" "server" {
count = "${length(local.dns_names)}"
key_algorithm = "${element(tls_private_key.server.*.algorithm, count.index)}"
private_key_pem = "${element(tls_private_key.server.*.private_key_pem, count.index)}"
subject {
common_name = "${local.dns_names[count.index]}"
organization = "${local.organization}"
serial_number = "${random_id.server.hex}"
}
dns_names = ["${local.dns_names[count.index]}"]
}
resource "tls_locally_signed_cert" "server" {
count = "${length(local.dns_names)}"
cert_request_pem = "${element(tls_cert_request.server.*.cert_request_pem, count.index)}"
ca_key_algorithm = "${tls_private_key.intermediate_ca.algorithm}"
ca_private_key_pem = "${tls_private_key.intermediate_ca.private_key_pem}"
ca_cert_pem = "${tls_locally_signed_cert.intermediate_ca.cert_pem}"
validity_period_hours = 26280
allowed_uses = [
"key_encipherment",
"server_auth",
]
}
resource "local_file" "server_cert" {
count = "${length(local.dns_names)}"
content = "${element(tls_locally_signed_cert.server.*.cert_pem, count.index)}"
filename = "./certs/${local.dns_names[count.index]}.crt"
}
resource "local_file" "server_full_chain" {
count = "${length(local.dns_names)}"
content = "${element(tls_locally_signed_cert.server.*.cert_pem, count.index)}${tls_locally_signed_cert.intermediate_ca.0.cert_pem}"
filename = "./certs/${local.dns_names[count.index]}.fullchain.crt"
}
// client cert and keys
resource "tls_private_key" "client" {
count = "${local.client_cert}"
algorithm = "${local.algorithm}"
rsa_bits = "${local.rsa_bits}"
}
resource "local_file" "client_key" {
count = "${local.client_cert}"
content = "${tls_private_key.client.0.private_key_pem}"
filename = "./certs/client.key"
}
resource "tls_cert_request" "client" {
count = "${local.client_cert}"
key_algorithm = "${tls_private_key.client.algorithm}"
private_key_pem = "${tls_private_key.client.private_key_pem}"
subject {
common_name = "client"
organization = "${local.organization}"
}
}
resource "tls_locally_signed_cert" "client" {
count = "${local.client_cert}"
cert_request_pem = "${tls_cert_request.client.cert_request_pem}"
ca_key_algorithm = "${tls_private_key.intermediate_ca.algorithm}"
ca_private_key_pem = "${tls_private_key.intermediate_ca.private_key_pem}"
ca_cert_pem = "${tls_locally_signed_cert.intermediate_ca.cert_pem}"
validity_period_hours = 26280
allowed_uses = [
"key_encipherment",
"client_auth",
]
}
resource "local_file" "client_cert" {
count = "${local.client_cert}"
content = "${tls_locally_signed_cert.client.cert_pem}"
filename = "./certs/client.crt"
}
// use openssl to verify certs that have been generated.
resource "null_resource" "check_certs" {
count = "${length(local_file.server_cert.*.filename)}"
provisioner "local-exec" {
command = "openssl verify -CAfile ${local_file.root_ca_cert.filename} -untrusted ${local_file.intermediate_ca_cert.filename} ${element(local_file.server_cert.*.filename, count.index)}"
}
}
@ArgonQQ
Copy link

ArgonQQ commented Feb 27, 2021

That really helped! Thanks a lot @mauilion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment