Production-ready Vault in a Terraform module
This is a Terraform module for creating a production-grade Hashicorp Vault deployment on AWS. Some stated goals:
- Maximum security
- Minimal unmanaged dependencies, to reduce operational complexity
- Ease of deployment, able to be used out of the box
Normally, Hashicorp recommends using Consul (another one of their tools) as both the storage and high-availability (HA) backend for Vault. This presents a number of challenges:
- Generating Consul agent certificates and Gossip token
- Deploying Consul in an autoscaling group along with IAM resources
- Bootstrapping Consul's ACL system and backing up the master token
- Keeping Consul single-tenant (to prevent data loss/corruption in Vault)
- Monitoring and logging of Consul itself
- Taking periodic Consul snapshots as backup
In order to reduce operational complexity as much as possible, we instead opt for Amazon S3 for Vault's storage backend and AWS DynamoDB for its HA backend. As these are managed services, we can offload much our SLA onto them and focus on maintaining Vault itself. This also loosens our coupling to Consul and simplifies deployment greatly.
SSM Parameter Store
/vault/${vault_cluster_name}/sumologic_access_key
/vault/${vault_cluster_name}/sumologic_access_id
/vault/${vault_cluster_name}/dd_api_key
/vault/${vault_cluster_name}/vault.pem
/vault/${vault_cluster_name}/vault-key.pem
In progress:
- TLS is disabled by default in the user data
- TODO: make Sumo Logic, Datadog, and TLS certs optional at build time
Name | Description | Type | Default | Required |
---|---|---|---|---|
ami_id | AMI ID to launch the Vault auto scaling group with | string | n/a | yes |
cluster_name | Name of the Vault cluster | string | "vault" |
no |
domain_name | Domain name of DNS entry to create | string | n/a | yes |
dynamodb_read_capacity | Read capacity for Vault's DynamoDB high availability backend | string | "5" |
no |
dynamodb_write_capacity | Write capacity for Vault's DynamoDB high availability backend | string | "5" |
no |
enable_termination_protection | Enable EC2 instance termination protection | string | "true" |
no |
instance_type | EC2 instance type for Vault instances | string | "t2.medium" |
no |
internal_lb | Whether to make the Vault load balancer internal | string | "true" |
no |
max_instances | Maximum number of Vault instances in the auto scaling group | string | "3" |
no |
min_instances | Minimum number of Vault instances in the auto scaling group | string | "3" |
no |
ssh_key_name | Name of the SSH keypair to use for the Vault EC2 instances | string | n/a | yes |
subnet_ids | List of subnet IDs to launch the Vault auto scaling group in | list | n/a | yes |
tags | Extra tags to add to all resources created by this module | map | {} |
no |
vpc_id | ID of the AWS VPC to create the Vault cluster in | string | n/a | yes |
zone_id | Route53 hosted zone ID to create the DNS entry in | string | n/a | yes |
Name | Description |
---|---|
kms_key_id | ID of the KMS key that Vault uses for Auto-Unseal, S3 encryption, and SSM parameters |
vault_client_sg_id | ID of the security group used by clients to connect to Vault |
vault_cluster_fqdn | Fully qualified domain name for the Vault cluster |
vault_cluster_role_arn | ARN of the AWS IAM role that Vault runs as |
vault_cluster_role_name | Name of the AWS IAM role that Vault runs as |