resource "linode_instance" "servers" {
count = var.servers
label = "vault-server-${random_id.servers[count.index].keepers.datacenter}-${random_id.servers[count.index].hex}"
region = random_id.servers[count.index].keepers.datacenter
image = random_id.servers[count.index].keepers.image
type = random_id.servers[count.index].keepers.instance_type
authorized_users = var.authorized_users
group = terraform.workspace
stackscript_id = var.stackscript_id
stackscript_data = {
hostname = "vault-server-${random_id.servers[count.index].keepers.datacenter}-${random_id.servers[count.index].hex}"
consul_version = random_id.servers[count.index].keepers.consul_version
vault_version = random_id.servers[count.index].keepers.vault_version
}
lifecycle {
create_before_destroy = true
}
// wait for stackscript to complete
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"while ! [[ -f /root/StackScript.complete ]]; do echo 'waiting for stackscript to complete...'; sleep 3; done",
]
}
// systemd service files
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/systemd/system/"
source = "../services/"
}
// cfssl config
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/ssl/cfssl.json"
content = data.template_file.cfssl_config.rendered
}
// consul config
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/consul.d"
source = "../config/consul"
}
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/consul.d/client.hcl"
content = <<-EOT
datacenter = "${var.datacenter}"
server = false
retry_join = [
%{for ip in var.consul_server_ips~}
"${split("/", ip)[0]}",
%{endfor~}
]
EOT
}
// vault config
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/vault.d"
source = "../config/vault"
}
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/vault.d/server.hcl"
content = <<-EOT
datacenter = "${var.datacenter}"
server {
enabled = true
bootstrap_expect = ${var.servers}
}
EOT
}
// firewall services
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/firewalld/services"
source = "../firewall/services/"
}
// firewall zones
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/firewalld/zones"
source = "../firewall/zones/"
}
// issue-cert script
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/usr/local/bin/issue-cert.sh"
source = "../scripts/issue-cert.sh"
}
// Consul certificate authority
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/ssl/consul/ca.pem"
source = "/etc/ssl/consul/ca.pem"
}
// Vault certificate authority
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/ssl/vault/ca.pem"
source = "/etc/ssl/vault/ca.pem"
}
// set global environment variables
provisioner "file" {
connection { host = split("/", self.ipv6)[0] }
destination = "/etc/profile.local"
content = <<-EOT
export CONSUL_HTTP_ADDR=unix:///var/run/consul/consul_https.sock
export VAULT_ADDR=https://localhost:8200
export VAULT_CACERT=/etc/ssl/vault/ca.pem
export VAULT_CLIENT_CERT=/etc/ssl/vault/cli.pem
export VAULT_CLIENT_KEY=/etc/ssl/vault/cli-key.pem
EOT
}
// reload firewall
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = ["service firewalld reload"]
}
// fix permissions
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"chown -R consul:consul /etc/consul.d",
"chown -R vault:vault /etc/vault.d",
"chmod +x /usr/local/bin/issue-cert.sh",
"chmod 0400 /etc/ssl/cfssl.json",
]
}
// issue certs
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"/usr/local/bin/issue-cert.sh --user consul --ca consul --name consul",
"/usr/local/bin/issue-cert.sh --user vault --ca consul --name consul",
"/usr/local/bin/issue-cert.sh --user vault --ca vault --name vault --hostnames vault.service.consul,active.vault.service.consul,${split("/", self.ipv6)[0]}",
"/usr/local/bin/issue-cert.sh --user vault --ca vault --name cli",
]
}
// fix CLI key permissions
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"chmod g+r /etc/ssl/vault/cli-key.pem",
]
}
// start services
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"systemctl enable consul && service consul start",
"systemctl enable vault && service vault start",
]
}
// install autocompletion
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"sudo -u damien /usr/local/bin/consul -autocomplete-install",
"sudo -u damien /usr/local/bin/vault -autocomplete-install",
]
}
// disable further root ssh
provisioner "remote-exec" {
connection { host = split("/", self.ipv6)[0] }
inline = [
"sed -i 's/PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config",
"service sshd reload",
]
}
}
resource "random_id" "servers" {
count = var.servers
keepers = {
datacenter = var.datacenter
image = var.image
instance_type = var.instance_type
consul_version = var.consul_version
vault_version = var.vault_version
}
byte_length = 3
}
data "template_file" "cfssl_config" {
template = file("${path.module}/../../../config/cfssl.json")
vars = {
ca_host = var.ca_host
ca_key = var.ca_key
}
}
// vim: set expandtab shiftwidth=2 tabstop=2: