From a866b0ec9f501fe4951f504dd60daeb48c477939 Mon Sep 17 00:00:00 2001 From: J Cole Morrison Date: Mon, 13 Apr 2020 18:31:14 -0700 Subject: [PATCH] launch template and auto scaling group --- ec2-auto-scaling-group.tf | 52 +++++++++++++++++++++++++++++++++++++++ ec2-launch-template.tf | 45 +++++++++++++++++++++++++++++++++ files/userdata.sh | 15 +++++++---- outputs.tf | 2 +- variables.tf | 16 ++++++++++++ vpc-security-groups.tf | 52 +++++++++++++++++++++++++++++++++++++++ vpc.tf | 2 +- 7 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 ec2-auto-scaling-group.tf create mode 100644 ec2-launch-template.tf diff --git a/ec2-auto-scaling-group.tf b/ec2-auto-scaling-group.tf new file mode 100644 index 0000000..e4af511 --- /dev/null +++ b/ec2-auto-scaling-group.tf @@ -0,0 +1,52 @@ +# EC2 Auto Scaling Group + +resource "aws_autoscaling_group" "vault-asg" { + name_prefix = "${var.main_project_tag}-asg-" + + launch_template { + id = aws_launch_template.vault_instance.id + version = aws_launch_template.vault_instance.latest_version + } + + # All the same to keep at a fixed size + desired_capacity = var.vault_instance_count + min_size = var.vault_instance_count + max_size = var.vault_instance_count + + # AKA the subnets to launch resources in + vpc_zone_identifier = aws_subnet.private.*.id + + health_check_grace_period = 300 + health_check_type = "EC2" + termination_policies = ["OldestLaunchTemplate"] + wait_for_capacity_timeout = 0 + + enabled_metrics = [ + "GroupDesiredCapacity", + "GroupInServiceCapacity", + "GroupPendingCapacity", + "GroupMinSize", + "GroupMaxSize", + "GroupInServiceInstances", + "GroupPendingInstances", + "GroupStandbyInstances", + "GroupStandbyCapacity", + "GroupTerminatingCapacity", + "GroupTerminatingInstances", + "GroupTotalCapacity", + "GroupTotalInstances" + ] + + tags = [ + { + key = "Name" + value = "${var.main_project_tag}-instance" + propagate_at_launch = true + }, + { + key = "Project" + value = var.main_project_tag + propagate_at_launch = true + } + ] +} \ No newline at end of file diff --git a/ec2-launch-template.tf b/ec2-launch-template.tf new file mode 100644 index 0000000..22a162d --- /dev/null +++ b/ec2-launch-template.tf @@ -0,0 +1,45 @@ +# EC2 Launch Template +resource "aws_launch_template" "vault_instance" { + name_prefix = "${var.main_project_tag}-lt-" + image_id = var.use_lastest_ami ? data.aws_ssm_parameter.latest_ami.value : "ami-0323c3dd2da7fb37d" + instance_type = var.vault_instance_type + key_name = var.ec2_key_pair_name + vpc_security_group_ids = [aws_security_group.vault_instance.id] + + iam_instance_profile { + arn = aws_iam_instance_profile.vault_instance_profile.arn + } + + tag_specifications { + resource_type = "instance" + + tags = merge( + { "Name" = "${var.main_project_tag}-instance" }, + { "Project" = var.main_project_tag } + ) + } + + tag_specifications { + resource_type = "volume" + + tags = merge( + { "Name" = "${var.main_project_tag}-volume" }, + { "Project" = var.main_project_tag } + ) + } + + tags = merge( + { "Name" = "${var.main_project_tag}-lt" }, + { "Project" = var.main_project_tag } + ) + + user_data = base64encode(templatefile("${path.module}/files/userdata.sh", { + VAULT_VERSION = var.vault_version + VAULT_CLUSTER_NAME = var.main_project_tag + VAULT_DNS = var.domain_name + VAULT_KMS_KEY_ID = aws_kms_key.seal.key_id + VAULT_CLUSTER_REGION = data.aws_region.current.name + VAULT_DYNAMODB_TABLE = var.dynamodb_table_name # dynamodb resource doesn't return name.... + VAULT_S3_BUCKET_NAME = aws_s3_bucket.vault_data.id + })) +} \ No newline at end of file diff --git a/files/userdata.sh b/files/userdata.sh index f928a06..6839bd7 100644 --- a/files/userdata.sh +++ b/files/userdata.sh @@ -72,8 +72,9 @@ max_lease_ttl = "192h" # One week default_lease_ttl = "192h" # One week ui = "true" -# Where can the Vault API be reached? At the load balancer. -api_addr = "https://${VAULT_LOAD_BALANCER_DNS}" +# Where can the Vault API be reached? At DNS for the load balancer, or the CNAME created. +# Note: this maps to the environment variable VAULT_API_ADDR not VAULT_ADDR +api_addr = "https://${VAULT_DNS}" # For forwarding between vault servers. Set to own ip. cluster_addr = "http://INSTANCE_IP_ADDR:8201" @@ -84,6 +85,7 @@ seal "awskms" { kms_key_id = "${VAULT_KMS_KEY_ID}" } +# Apply Listener for local listener "tcp" { address = "0.0.0.0:8200" cluster_address = "0.0.0.0:8201" @@ -120,7 +122,7 @@ AmbientCapabilities=CAP_IPC_LOCK Capabilities=CAP_IPC_LOCK+ep CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK NoNewPrivileges=yes -ExecStart=/opt/vault/bin/vault server -config /opt/vault/config/ -log-level=info +ExecStart=/opt/vault/bin/vault server -config=/opt/vault/config/ -log-level=debug ExecReload=/bin/kill --signal HUP \$MAINPID KillMode=process KillSignal=SIGINT @@ -152,7 +154,7 @@ sed -i -e "s/INSTANCE_IP_ADDR/$INSTANCE_IP_ADDR/g" /opt/vault/config/server.hcl systemctl daemon-reload systemctl enable vault -systemctl restart vault +# systemctl restart vault --==BOUNDARY== Content-Type: text/x-shellscript; charset="us-ascii" @@ -170,6 +172,9 @@ Content-Type: text/x-shellscript; charset="us-ascii" # - Delete the local file # - Erase bash history +export VAULT_ADDR="http://127.0.0.1:8200" +export AWS_DEFAULT_REGION="${VAULT_CLUSTER_REGION}" + VAULT_INITIALIZED=$(vault operator init -status) function initialize_vault { @@ -192,7 +197,7 @@ if [ "$VAULT_INITIALIZED" = "Vault is initialized" ]; then echo "Vault is already initialized." else echo "Initializing vault..." - initialize_vault + # initialize_vault fi --==BOUNDARY==-- \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index dca3cbf..c4793e4 100644 --- a/outputs.tf +++ b/outputs.tf @@ -3,7 +3,7 @@ resource "local_file" "user_data_compiled" { content = templatefile("${path.module}/files/userdata.sh", { VAULT_VERSION = var.vault_version VAULT_CLUSTER_NAME = var.main_project_tag - VAULT_LOAD_BALANCER_DNS = aws_lb.alb.dns_name + VAULT_DNS = var.domain_name VAULT_KMS_KEY_ID = aws_kms_key.seal.key_id VAULT_CLUSTER_REGION = data.aws_region.current.name VAULT_DYNAMODB_TABLE = var.dynamodb_table_name # dynamodb resource doesn't return name.... diff --git a/variables.tf b/variables.tf index d401970..6dec910 100644 --- a/variables.tf +++ b/variables.tf @@ -105,6 +105,22 @@ variable "use_lastest_ami" { default = false } +# EC2 - Vault Instance Launch Template + +variable "vault_instance_type" { + description = "The EC2 instance size of the vault instances." + type = string + default = "t2.micro" +} + +# EC2 - Vault Instance AutoScaling Group + +variable "vault_instance_count" { + description = "The number of EC2 instances to launch as vault instances. Should be no less than 2." + type = number + default = 2 +} + # SSL Certificate for HTTPS Access variable "domain_name" { diff --git a/vpc-security-groups.tf b/vpc-security-groups.tf index 17579e3..a5e3e8a 100644 --- a/vpc-security-groups.tf +++ b/vpc-security-groups.tf @@ -79,6 +79,16 @@ resource "aws_security_group_rule" "vault_instance_allow_8201" { description = "Allow traffic from fellow vault instances that have this SG." } +resource "aws_security_group_rule" "vault_instance_allow_22_bastion" { + security_group_id = aws_security_group.vault_instance.id + type = "ingress" + protocol = "tcp" + from_port = 22 + to_port = 22 + source_security_group_id = aws_security_group.bastion.id + description = "Allow SSH traffic from vault bastion." +} + resource "aws_security_group_rule" "vault_instance_allow_outbound" { security_group_id = aws_security_group.vault_instance.id type = "egress" @@ -121,4 +131,46 @@ resource "aws_security_group_rule" "bastion_allow_outbound" { cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = length(var.allowed_bastion_cidr_blocks_ipv6) > 0 ? ["::/0"] : null description = "Allow any outbound traffic." +} + +## KMS Endpoint SG + +resource "aws_security_group" "kms_endpoint" { + name_prefix = "${var.main_project_tag}-kms-endpoint-sg" + description = "Firewall for the KMS Endpoint." + vpc_id = aws_vpc.vault.id + tags = merge( + { "Name" = "${var.main_project_tag}-kms-endpoint-sg" }, + { "Project" = var.main_project_tag } + ) +} + +resource "aws_security_group_rule" "vault_instance_allow_80" { + security_group_id = aws_security_group.kms_endpoint.id + type = "ingress" + protocol = "tcp" + from_port = 80 + to_port = 80 + source_security_group_id = aws_security_group.vault_instance.id + description = "Allow HTTP traffic from vault instances." +} + +resource "aws_security_group_rule" "vault_instance_allow_443" { + security_group_id = aws_security_group.kms_endpoint.id + type = "ingress" + protocol = "tcp" + from_port = 443 + to_port = 443 + source_security_group_id = aws_security_group.vault_instance.id + description = "Allow HTTPS traffic from vault instances." +} + +resource "aws_security_group_rule" "kms_allow_outbound" { + security_group_id = aws_security_group.kms_endpoint.id + type = "egress" + protocol = "-1" + from_port = 0 + to_port = 0 + cidr_blocks = ["0.0.0.0/0"] + description = "Allow any outbound traffic." } \ No newline at end of file diff --git a/vpc.tf b/vpc.tf index b4c7218..e40bf98 100644 --- a/vpc.tf +++ b/vpc.tf @@ -225,7 +225,7 @@ resource "aws_vpc_endpoint" "kms" { // Can also be done with "aws_vpc_endpoint_subnet_association" subnet_ids = aws_subnet.private.*.id - security_group_ids = [aws_security_group.vault_instance.id] + security_group_ids = [aws_security_group.kms_endpoint.id] tags = merge( { "Name" = "${var.main_project_tag}-kms-endpoint"},