Skip to content

Commit

Permalink
Adds the Vault component (#15)
Browse files Browse the repository at this point in the history
* Adds the Vault component

Adds the vault component module and documentation.
  • Loading branch information
SamClinckspoor authored Nov 21, 2017
1 parent c0c1979 commit d8eaf48
Show file tree
Hide file tree
Showing 12 changed files with 700 additions and 0 deletions.
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,73 @@ module "tools_userdata" {
function = "tools"
}
```


## Vault

This terraform module sets up a HA vault with a DynamoDB backend.
The module sets up TLS using Letsencrypt with dns-01 challenge.

Both vault servers are configured with Teleport for SSH management.

2 route53 records are provided to access the individual instances.

![](vault/images/vault-component.svg)

### Available variables:
* [`acm_arn`]: String(required): The ACM ARN to use on the alb
* [`ami`]: String(required): The AMI ID to use for the vault instances
* [`dns_root`]: String(required): The root domain to configure for vault
* [`lb_subnets`]: List(required): The subnets to use for the alb
* [`key_name`]: String(required): Name of the sshkey to deploy on the vault instances
* [`teleport_auth_server`]: String(required): The hostname or ip of the Teleport auth server.
* [`teleport_node_sg`]: String(required): The security-group ID of the teleport server.
* [`teleport_token_1`]: String(required): The Teleport token for the first instance. This can be a dynamic short-lived token.
* [`teleport_token_2`]: String(required): The Teleport token for the second instance. This can be a dynamic short-lived token.
* [`vault1_subnet`]: String(required): The subnet ID for the first vault instance
* [`vault2_subnet`]: String(required): The subnet ID for the second vault instance
* [`vpc_id`]: String(required): The VPC id to launch the instances in.

* [`download_url_vault`]: String(optional): The download url for vault. Defaults to `https://releases.hashicorp.com/vault/0.9.0/vault_0.9.0_linux_amd64.zip`
* [`download_url_teleport`]: String(optional): The download url for Teleport. Defaults to `https://github.com/gravitational/teleport/releases/download/v2.3.5/teleport-v2.3.5-linux-amd64-bin.tar.gz`
* [`instance_type`]: String(optional): The instance type to use for the vault servers. Defaults to t2.micro
* [`lb_internal`]: Bool(optional): Should the ALB be created as an internal Loadbalancer
* [`project`]: String(optional): Name of the project
* [`vault_nproc`]: String(optional): The amount of nproc to configure vault with. Set this to the amount of CPU cores.

### Output
* [`sg_id`]: String: The vault security-group id
* [`vault_route53_record`]: String: The main vault route53 record id
* [`vault1_route53_record`]: String: The vault1 route53 record id
* [`vault2_route53_record`]: String: The vault2 route53 record id
* [`vault1_instance_id`]: String: The vault1 instance ID
* [`vault2_instance_id`]: String: The vault2 instance ID
* [`vault1_role_id`]: String: The vault1 instance-role ID
* [`vault2_role_id`]: String: The vault2 instance-role ID
* [`iam_policy`]: String: The iam policy ARN used for vault
* [`alb_main_target_group`]: String: The default alb target group ARN
* [`alb_vault1_target_group`]: String: The vault1 target group ARN
* [`alb_vault2_target_group`]: String: The vault2 target group ARN
* [`alb_sg_id`]: String: The alb security group ID
* [`alb_id`]: String: The alb id
* [`alb_arn`]: String: The alb ARN

### Example
```
module "ha_vault" {
source = "github.com/skyscrapers/terraform-instances//vault?ref=2.0.0"
teleport_auth_server = "10.10.0.100:3025"
ami = "ami-add175d4"
vault1_subnet = "${data.terraform_remote_state.static.private_app_subnets[0]}"
vault2_subnet = "${data.terraform_remote_state.static.private_app_subnets[1]}"
teleport_node_sg = "${data.terraform_remote_state.static.teleport_node_sg_id}"
vpc_id = "${data.terraform_remote_state.static.vpc_id}"
lb_subnets = "${data.terraform_remote_state.static.public_lb_subnets}"
acm_arn = "${data.aws_acm_certificate.vault.arn}"
teleport_token_1 = "c010f4fa754b7ad2a7a1d580e282d81b"
teleport_token_2 = "6b69a780b9137g467f79ab7263337fd6"
dns_root = "${var.dns_root}"
vault_nproc = "2"
key_name = "sam"
}
```
111 changes: 111 additions & 0 deletions vault/alb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
module "alb" {
source = "github.com/skyscrapers/terraform-loadbalancers//alb?ref=3.1.2"
name = "vault"
environment = "${terraform.workspace}"
project = "${var.project}"
vpc_id = "${var.vpc_id}"
subnets = "${var.lb_subnets}"
enable_http_listener = false
enable_https_listener = true
https_certificate_arn = "${var.acm_arn}"
target_security_groups = ["${aws_security_group.vault.id}"]
target_port = 8200
target_protocol = "HTTPS"
target_health_path = "/v1/sys/health"
target_health_protocol = "HTTPS"
target_security_groups_count = 1
internal = "${var.lb_internal}"

target_stickiness = [{
enabled = false
type = "lb_cookie"
}]
}

resource "aws_lb_target_group" "vault1" {
name = "vault1-group"
port = 8200
protocol = "HTTPS"
vpc_id = "${var.vpc_id}"

stickiness = {
enabled = false
type = "lb_cookie"
}

health_check = {
matcher = "404"
protocol = "HTTPS"
}
}

resource "aws_lb_target_group_attachment" "vault1" {
target_group_arn = "${aws_lb_target_group.vault1.arn}"
target_id = "${module.vault1.instance_ids[0]}"
port = 8200
}

resource "aws_lb_listener_rule" "vault1" {
listener_arn = "${module.alb.https_listener_id}"
priority = 10

action {
type = "forward"
target_group_arn = "${aws_lb_target_group.vault1.arn}"
}

condition {
field = "host-header"
values = ["${aws_route53_record.vault1.name}"]
}
}

resource "aws_lb_target_group" "vault2" {
name = "vault2-group"
port = 8200
protocol = "HTTPS"
vpc_id = "${var.vpc_id}"

stickiness = {
enabled = false
type = "lb_cookie"
}

health_check = {
matcher = "404"
protocol = "HTTPS"
}
}

resource "aws_lb_target_group_attachment" "vault2" {
target_group_arn = "${aws_lb_target_group.vault2.arn}"
target_id = "${module.vault2.instance_ids[0]}"
port = 8200
}

resource "aws_lb_listener_rule" "vault2" {
listener_arn = "${module.alb.https_listener_id}"
priority = 11

action {
type = "forward"
target_group_arn = "${aws_lb_target_group.vault2.arn}"
}

condition {
field = "host-header"
values = ["${aws_route53_record.vault2.name}"]
}
}

resource "aws_lb_target_group_attachment" "vault1_main" {
target_group_arn = "${module.alb.target_group_arn}"
target_id = "${module.vault1.instance_ids[0]}"
port = 8200
}

resource "aws_lb_target_group_attachment" "vault2_main" {
target_group_arn = "${module.alb.target_group_arn}"
target_id = "${module.vault2.instance_ids[0]}"
port = 8200
}
84 changes: 84 additions & 0 deletions vault/cloud-config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
data "template_cloudinit_config" "vault1" {
gzip = true
base64_encode = true

part {
content_type = "text/cloud-config"
content = "${data.template_file.cloudconfig_vault1.rendered}"
}

part {
content_type = "text/x-shellscript"
content = "${data.template_file.install.rendered}"
}

part {
content_type = "text/x-shellscript"
content = "${module.teleport_vault1.teleport_bootstrap_script}"
}
}

data "template_cloudinit_config" "vault2" {
gzip = true
base64_encode = true

part {
content_type = "text/cloud-config"
content = "${data.template_file.cloudconfig_vault2.rendered}"
}

part {
content_type = "text/x-shellscript"
content = "${data.template_file.install.rendered}"
}

part {
content_type = "text/x-shellscript"
content = "${module.teleport_vault2.teleport_bootstrap_script}"
}
}

data "template_file" "cloudconfig_vault1" {
template = "${file("${path.module}/templates/configure.yaml.tpl")}"

vars {
vault_dns = "vault1.${var.dns_root}"
vault_nproc = "${var.vault_nproc}"
vault_cluster_dns = "vault.${var.dns_root}"
}
}

data "template_file" "cloudconfig_vault2" {
template = "${file("${path.module}/templates/configure.yaml.tpl")}"

vars {
vault_dns = "vault2.${var.dns_root}"
vault_nproc = "${var.vault_nproc}"
vault_cluster_dns = "vault.${var.dns_root}"
}
}

data "template_file" "install" {
template = "${file("${path.module}/templates/install.sh.tpl")}"

vars {
download_url_vault = "${var.download_url_vault}"
download_url_teleport = "${var.download_url_teleport}"
}
}

module "teleport_vault1" {
source = "github.com/skyscrapers/terraform-teleport//teleport-bootstrap-script?ref=2.1.1"
auth_server = "${var.teleport_auth_server}"
auth_token = "${var.teleport_token_1}"
function = "vault1"
environment = "${terraform.workspace}"
}

module "teleport_vault2" {
source = "github.com/skyscrapers/terraform-teleport//teleport-bootstrap-script?ref=2.1.1"
auth_server = "${var.teleport_auth_server}"
auth_token = "${var.teleport_token_2}"
function = "vault2"
environment = "${terraform.workspace}"
}
84 changes: 84 additions & 0 deletions vault/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
data "aws_caller_identity" "current" {}

data "aws_region" "current" {
current = true
}

data "aws_iam_policy_document" "vault" {
statement {
sid = "getR53"

actions = [
"route53:ListHostedZones",
"route53:GetChange",
]

resources = [
"*",
]
}

statement {
sid = "changeR53"

actions = [
"route53:ChangeResourceRecordSets",
]

resources = [
"arn:aws:route53:::hostedzone/${data.aws_route53_zone.root.zone_id}",
]
}

statement {
sid = "vaultDynamoDBAccess"

actions = [
"dynamodb:CreateTable",
"dynamodb:BatchWriteItem",
"dynamodb:UpdateItem",
"dynamodb:BatchGetItem",
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan",
]

resources = [
"arn:aws:dynamodb:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/vault-dynamodb-backend",
]
}

statement {
sid = "vaultGeneralDynamoDBAccess"

actions = [
"dynamodb:ListTables",
"dynamodb:DescribeReservedCapacity",
"dynamodb:DescribeReservedCapacityOfferings",
"dynamodb:ListTagsOfResource",
"dynamodb:DescribeTimeToLive",
"dynamodb:DescribeLimits",
"dynamodb:DescribeTable",
]

resources = [
"arn:aws:dynamodb:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/*",
]
}
}

resource "aws_iam_policy" "vault" {
name = "vault_instance_policy"
path = "/"
policy = "${data.aws_iam_policy_document.vault.json}"
}

resource "aws_iam_role_policy_attachment" "vault1" {
role = "${module.vault1.role_id}"
policy_arn = "${aws_iam_policy.vault.arn}"
}

resource "aws_iam_role_policy_attachment" "vault2" {
role = "${module.vault2.role_id}"
policy_arn = "${aws_iam_policy.vault.arn}"
}
4 changes: 4 additions & 0 deletions vault/images/vault-component.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions vault/instances.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module "vault1" {
source = "github.com/skyscrapers/terraform-instances//instance?ref=1.3.1"
project = "${var.project}"
environment = "${terraform.workspace}"
name = "vault1"
sgs = ["${aws_security_group.vault.id}", "${var.teleport_node_sg}"]
subnets = ["${var.vault1_subnet}"]
key_name = "${var.key_name}"
ami = "${var.ami}"
instance_type = "${var.instance_type}"
user_data = ["${data.template_cloudinit_config.vault1.rendered}"]
}

module "vault2" {
source = "github.com/skyscrapers/terraform-instances//instance?ref=1.3.1"
project = "${var.project}"
environment = "${terraform.workspace}"
name = "vault2"
sgs = ["${aws_security_group.vault.id}", "${var.teleport_node_sg}"]
subnets = ["${var.vault2_subnet}"]
key_name = "${var.key_name}"
ami = "${var.ami}"
instance_type = "${var.instance_type}"
user_data = ["${data.template_cloudinit_config.vault2.rendered}"]
}
Loading

0 comments on commit d8eaf48

Please sign in to comment.