initial commit
This commit is contained in:
commit
ddf83c628c
|
@ -0,0 +1,6 @@
|
|||
.terraform
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
terraform.tfvars
|
||||
todos.md
|
||||
.DS_Store
|
|
@ -0,0 +1,3 @@
|
|||
data "aws_availability_zones" "available" {
|
||||
state = "available"
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
# DynamoDB
|
||||
|
||||
resource "aws_dynamodb_table" "vault_storage" {
|
||||
name = var.dynamodb_table_name
|
||||
billing_mode = "PAY_PER_REQUEST"
|
||||
hash_key = "Path"
|
||||
range_key = "Key"
|
||||
|
||||
attribute {
|
||||
name = "Path"
|
||||
type = "S"
|
||||
}
|
||||
|
||||
attribute {
|
||||
name = "Key"
|
||||
type = "S"
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = var.dynamodb_table_name
|
||||
Project = var.main_project_tag
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
# IAM Policies
|
||||
|
||||
## KMS Policy
|
||||
data "aws_iam_policy_document" "kms_vault_policy" {
|
||||
statement {
|
||||
sid = "EncryptDecryptAndDescribe"
|
||||
effect = "Allow"
|
||||
actions = [
|
||||
"kms:Decrypt",
|
||||
"kms:Encrypt",
|
||||
"kms:DescribeKey"
|
||||
]
|
||||
resources = [
|
||||
aws_kms_key.seal.arn
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
## DynamoDB Policy
|
||||
data "aws_iam_policy_document" "dynamodb_vault_policy" {
|
||||
statement {
|
||||
sid = "ManageTable"
|
||||
effect = "Allow"
|
||||
actions = [
|
||||
"dynamodb:BatchGetItem",
|
||||
"dynamodb:BatchWriteItem",
|
||||
"dynamodb:PutItem",
|
||||
"dynamodb:DescribeTable",
|
||||
"dynamodb:DeleteItem",
|
||||
"dynamodb:GetItem",
|
||||
"dynamodb:ListTagsOfResource",
|
||||
"dynamodb:UpdateItem",
|
||||
"dynamodb:DescribeTimeToLive"
|
||||
]
|
||||
resources = [
|
||||
aws_dynamodb_table.vault_storage.arn
|
||||
]
|
||||
}
|
||||
|
||||
statement {
|
||||
sid = "GetStreamRecords"
|
||||
effect = "Allow"
|
||||
actions = [
|
||||
"dynamodb:GetRecords"
|
||||
]
|
||||
resources = [
|
||||
"${aws_dynamodb_table.vault_storage.arn}/stream/*"
|
||||
]
|
||||
}
|
||||
|
||||
statement {
|
||||
sid = "QueryAndScanTable"
|
||||
effect = "Allow"
|
||||
actions = [
|
||||
"dynamodb:Scan",
|
||||
"dynamodb:Query"
|
||||
]
|
||||
resources = [
|
||||
"${aws_dynamodb_table.vault_storage.arn}/index/*",
|
||||
aws_dynamodb_table.vault_storage.arn
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
## AutoScalingGroup Instance Trust Policy
|
||||
data "aws_iam_policy_document" "asg_trust_policy" {
|
||||
statement {
|
||||
effect = "Allow"
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = ["ec2.amazonaws.com"]
|
||||
}
|
||||
actions = [
|
||||
"sts:AssumeRole"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
# IAM Roles
|
||||
|
||||
## Role for Vault EC2 Instances via AutoScalingGroup
|
||||
|
||||
resource "aws_iam_role" "vault_instance" {
|
||||
name_prefix = "${var.main_project_tag}-instance-role-"
|
||||
assume_role_policy = data.aws_iam_policy_document.asg_trust_policy.json
|
||||
}
|
||||
|
||||
## Policy Attachments
|
||||
|
||||
resource "aws_iam_role_policy" "vault_instance_kms_policy" {
|
||||
name_prefix = "${var.main_project_tag}-instance-kms-policy-"
|
||||
role = aws_iam_role.vault_instance.id
|
||||
policy = data.aws_iam_policy_document.kms_vault_policy.json
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "vault_instance_dynamodb_policy" {
|
||||
name_prefix = "${var.main_project_tag}-instance-dynamodb-policy-"
|
||||
role = aws_iam_role.vault_instance.id
|
||||
policy = data.aws_iam_policy_document.dynamodb_vault_policy.json
|
||||
}
|
||||
|
||||
## Instance Profile
|
||||
|
||||
resource "aws_iam_instance_profile" "vault_instance_profile" {
|
||||
name_prefix = "${var.main_project_tag}-instance-profile-"
|
||||
role = aws_iam_role.vault_instance.name
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
# AWS KMS Key
|
||||
resource "aws_kms_key" "seal" {
|
||||
description = "The KMS key to unseal Vault."
|
||||
enable_key_rotation = true
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-seal-key" },
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.kms_tags
|
||||
)
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "seal" {
|
||||
name = "alias/${var.main_project_tag}-seal-key"
|
||||
target_key_id = aws_kms_key.seal.key_id
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
provider "aws" {
|
||||
region = var.aws_default_region
|
||||
profile = var.aws_profile
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
# Organization
|
||||
|
||||
variable "main_project_tag" {
|
||||
description = "Tag that will be attached to all resources."
|
||||
type = string
|
||||
default = "vault-deployment"
|
||||
}
|
||||
|
||||
# AWS Provider
|
||||
|
||||
variable "aws_profile" {
|
||||
description = "The AWS Profile to use for this project."
|
||||
type = string
|
||||
default = "default"
|
||||
}
|
||||
|
||||
variable "aws_default_region" {
|
||||
description = "The default region to deploy this."
|
||||
type = string
|
||||
default = "us-east-1"
|
||||
}
|
||||
|
||||
# AWS VPC
|
||||
|
||||
variable "vpc_cidr" {
|
||||
description = "Cidr block for the VPC. Using a /16 or /20 Subnet Mask is recommended."
|
||||
type = string
|
||||
default = "10.255.0.0/20"
|
||||
}
|
||||
|
||||
variable "vpc_instance_tenancy" {
|
||||
description = "Tenancy for instances launched into the VPC"
|
||||
type = string
|
||||
default = "default"
|
||||
}
|
||||
|
||||
variable "vpc_enable_dns_support" {
|
||||
description = "Whether the DNS resolution is supported."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "vpc_enable_dns_hostnames" {
|
||||
description = "Whether instances with public IP addresses get corresponding public DNS hostnames."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "vpc_tags" {
|
||||
description = "Additional tags to add to the VPC and its resources."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
# VPC Subnets
|
||||
|
||||
variable "vpc_public_subnet_count" {
|
||||
description = "The number of public subnets to create. Cannot exceed the number of AZs in your selected region. 2 is more than enough."
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "vpc_private_subnet_count" {
|
||||
description = "The number of private subnets to create. Cannot exceed the number of AZs in your selected region."
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
# KMS
|
||||
|
||||
variable "kms_tags" {
|
||||
description = "Tags for the KMS key used to seal and unseal the Vault."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
# DynamoDB
|
||||
|
||||
variable "dynamodb_table_name" {
|
||||
description = "Name of the DynamoDB Table used for the Vault Storage Backend."
|
||||
type = string
|
||||
default = "vault_storage"
|
||||
}
|
||||
|
||||
# Operator Mode
|
||||
## Turning this on will enable NAT and Bastion to access the Vault Instances
|
||||
|
||||
variable "operator_mode" {
|
||||
description = "Enable a NAT Gateway and Bastion for operator access into the Vault Instances."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
# VPC
|
||||
resource "aws_vpc" "vault" {
|
||||
cidr_block = var.vpc_cidr
|
||||
instance_tenancy = var.vpc_instance_tenancy
|
||||
enable_dns_support = var.vpc_enable_dns_support
|
||||
enable_dns_hostnames = var.vpc_enable_dns_hostnames
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-vpc" },
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Gateways
|
||||
|
||||
## Internet Gateway
|
||||
resource "aws_internet_gateway" "igw" {
|
||||
vpc_id = aws_vpc.vault.id
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-igw"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
## NAT Gateway
|
||||
|
||||
#### The NAT Elastic IP
|
||||
resource "aws_eip" "nat" {
|
||||
count = var.operator_mode ? 1 : 0
|
||||
|
||||
vpc = true
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-nat-eip"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
|
||||
depends_on = [aws_internet_gateway.igw]
|
||||
}
|
||||
|
||||
#### The NAT Gateway
|
||||
resource "aws_nat_gateway" "nat" {
|
||||
count = var.operator_mode ? 1 : 0
|
||||
|
||||
allocation_id = aws_eip.nat[0].id
|
||||
subnet_id = aws_subnet.public.0.id
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-nat"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
|
||||
depends_on = [
|
||||
aws_internet_gateway.igw,
|
||||
aws_eip.nat
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Route Tables
|
||||
# NOTE: Routing to the VPC's CIDR is allowed by default, so no route is needed
|
||||
|
||||
## Public Route Table
|
||||
resource "aws_route_table" "public" {
|
||||
vpc_id = aws_vpc.vault.id
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-public-rtb"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
#### Public routes
|
||||
resource "aws_route" "public_internet_access" {
|
||||
route_table_id = aws_route_table.public.id
|
||||
destination_cidr_block = "0.0.0.0/0"
|
||||
gateway_id = aws_internet_gateway.igw.id
|
||||
}
|
||||
|
||||
## Private Route Table
|
||||
resource "aws_route_table" "private" {
|
||||
vpc_id = aws_vpc.vault.id
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-private-rtb"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
#### Private Routes
|
||||
resource "aws_route" "private_internet_access" {
|
||||
count = var.operator_mode ? 1 : 0
|
||||
|
||||
route_table_id = aws_route_table.private.id
|
||||
destination_cidr_block = "0.0.0.0/0"
|
||||
nat_gateway_id = aws_nat_gateway.nat[0].id
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Subnets
|
||||
|
||||
## Public Subnets
|
||||
resource "aws_subnet" "public" {
|
||||
count = var.vpc_public_subnet_count
|
||||
|
||||
vpc_id = aws_vpc.vault.id
|
||||
cidr_block = cidrsubnet(aws_vpc.vault.cidr_block, 4, count.index)
|
||||
availability_zone = data.aws_availability_zones.available.names[count.index]
|
||||
map_public_ip_on_launch = true
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-public-${data.aws_availability_zones.available.names[count.index]}"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
## Private Subnets
|
||||
resource "aws_subnet" "private" {
|
||||
count = var.vpc_private_subnet_count
|
||||
|
||||
vpc_id = aws_vpc.vault.id
|
||||
|
||||
# Increment the netnum by the number of public subnets to avoid overlap
|
||||
cidr_block = cidrsubnet(aws_vpc.vault.cidr_block, 4, count.index + var.vpc_public_subnet_count)
|
||||
availability_zone = data.aws_availability_zones.available.names[count.index]
|
||||
|
||||
tags = merge(
|
||||
{ "Name" = "${var.main_project_tag}-private-${data.aws_availability_zones.available.names[count.index]}"},
|
||||
{ "Project" = var.main_project_tag },
|
||||
var.vpc_tags
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# VPC Endpoints
|
||||
# Make safe calls to KMS and DynamoDB without leaving the VPC.
|
Loading…
Reference in New Issue