diff --git a/bastion/main.tf b/bastion/main.tf new file mode 100644 index 0000000..625ce2d --- /dev/null +++ b/bastion/main.tf @@ -0,0 +1,19 @@ +variable "environment" {} +variable "subnet_id" {} +variable "key_name" {} +variable "sg_id" {} + +resource "aws_instance" "bastion_instance" { + ami = "ami-5189a661" + instance_type = "t2.micro" + vpc_security_group_ids = ["${var.sg_id}"] + subnet_id = "${var.subnet_id}" + key_name = "${var.key_name}" + + associate_public_ip_address = true + source_dest_check = false + + tags { + Name = "${var.environment}-bastion" + } +} diff --git a/database/main.tf b/database/main.tf index 748389d..0ddd7f6 100644 --- a/database/main.tf +++ b/database/main.tf @@ -3,23 +3,9 @@ variable "username" {} variable "password" {} variable "port" {} variable "subnet_group_name" {} -variable "vpc_id" {} -variable "main_host_security_group_id" {} +variable "security_group_id" {} variable "instance_class" {} -resource "aws_security_group" "database_sg" { - name = "${var.environment}-database-sg" - description = "Allow inbound traffic from main host to DB port" - vpc_id = "${var.vpc_id}" - - ingress { - from_port = 5432 - to_port = 5432 - protocol = "tcp" - security_groups = ["${var.main_host_security_group_id}"] - } -} - resource "aws_db_instance" "main_postgres_db" { allocated_storage = 10 engine = "postgres" @@ -30,6 +16,6 @@ resource "aws_db_instance" "main_postgres_db" { password = "${var.password}" port = "${var.port}" db_subnet_group_name = "${var.subnet_group_name}" - vpc_security_group_ids = ["${aws_security_group.database_sg.id}"] + vpc_security_group_ids = ["${var.security_group_id}"] skip_final_snapshot = true } diff --git a/environments/runnable-on-prem.example.tfvars b/environments/runnable-on-prem.example.tfvars index 8aea5f0..fb59ae6 100644 --- a/environments/runnable-on-prem.example.tfvars +++ b/environments/runnable-on-prem.example.tfvars @@ -1,15 +1,9 @@ # All variables in this document should match domain = "" +github_org_id = "" +public_key = "" db_username = "" # Must start with a letter db_password = "" -db_subnet_group_name = "" -main_host_vpc_id = "" -main_host_subnet_id = "" -main_host_private_ip = "10.4.0.100" -dock_subnet_id = "" -github_org_id = "" -key_name = "" lc_user_data_file_location = "~/dock-runnable-on-prem.sh" -bastion_sg_id = "" environment = "runnable-on-prem" aws_region = "us-west-2" diff --git a/instances-and-security-groups/main.tf b/instances-and-security-groups/main.tf deleted file mode 100644 index f3cbd78..0000000 --- a/instances-and-security-groups/main.tf +++ /dev/null @@ -1,185 +0,0 @@ -variable "environment" {} -variable "vpc_id" {} -variable "main_host_subnet_id" {} -variable "main_host_instance_type" {} -variable "dock_subnet_id" {} -variable "dock_instance_type" {} -variable "private_ip" {} -variable "github_org_id" {} -variable "lc_user_data_file_location" {} -variable "key_name" {} -variable "bastion_sg_id" {} - -# Changing AMI forces new resource and will delete all everything in main host -# Ovewrite this variable with previous AMI if update is pushed -variable "main_host_ami" { - default = "ami-5fa7353f" # singe-host-ami-build-v0.0.4 -} - -variable "dock_ami" { - default = "ami-557dee35" # dock-ami-build-v.0.0.8 -} - -resource "aws_security_group" "main_host_sg" { - name = "${var.environment}-main-host-sg" - description = "Allow all inbound traffic on all traffic over port 80" - vpc_id = "${var.vpc_id}" - - ingress { - from_port = 80 - to_port = 65535 - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] - } - - ingress { - from_port = 22 - to_port = 22 - protocol = "tcp" - security_groups = ["${var.bastion_sg_id}"] - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_security_group" "dock_sg" { - name = "${var.environment}-dock-sg" - description = "Allow all traffic from main host and between docks" - vpc_id = "${var.vpc_id}" - - ingress { - from_port = 22 - to_port = 22 - protocol = "tcp" - security_groups = ["${var.bastion_sg_id}"] - } - - ingress { - from_port = 32768 - to_port = 65535 - protocol = "tcp" - security_groups = ["${aws_security_group.main_host_sg.id}"] - } - - ingress { - from_port = 8200 - to_port = 8201 - protocol = "tcp" - security_groups = ["${aws_security_group.main_host_sg.id}"] - } - - ingress { - from_port = 4242 - to_port = 4242 - protocol = "tcp" - security_groups = ["${aws_security_group.main_host_sg.id}"] - } - - ingress { - from_port = 29006 - to_port = 29007 - protocol = "tcp" - security_groups = ["${aws_security_group.main_host_sg.id}"] - } - - ingress { - from_port = 3100 - to_port = 3100 - protocol = "tcp" - security_groups = ["${aws_security_group.main_host_sg.id}"] - } - - ingress { - from_port = 6783 - to_port = 6783 - protocol = "tcp" - self = true - } - - ingress { - from_port = 6783 - to_port = 6783 - protocol = "udp" - self = true - } - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } -} - -resource "aws_instance" "main-instance" { - ami = "${var.main_host_ami}" - instance_type = "${var.main_host_instance_type}" - associate_public_ip_address = true - private_ip = "${var.private_ip}" - vpc_security_group_ids = ["${aws_security_group.main_host_sg.id}"] - subnet_id = "${var.main_host_subnet_id}" - key_name = "${var.key_name}" - - tags { - Name = "${var.environment}-main" - } -} - -resource "aws_launch_configuration" "dock_lc" { - name_prefix = "${var.environment}-dock-lc-" - image_id = "${var.dock_ami}" - instance_type = "${var.dock_instance_type}" - user_data = "${file("${var.lc_user_data_file_location}")}" - key_name = "${var.key_name}" - security_groups = ["${aws_security_group.dock_sg.id}"] - - root_block_device { - volume_size = 10 - } - - ebs_block_device { - device_name = "/dev/sdb" - snapshot_id = "snap-c77705e9" - volume_size = 50 - } - - lifecycle { - create_before_destroy = true - } -} - -resource "aws_autoscaling_group" "dock-auto-scaling-group" { - name = "asg-${var.environment}-${var.github_org_id}" - max_size = 30 - min_size = 2 - health_check_grace_period = 300 - health_check_type = "EC2" - desired_capacity = 2 # Start off with 0 and increase manually when main host is running - vpc_zone_identifier = ["${var.dock_subnet_id}"] - launch_configuration = "${aws_launch_configuration.dock_lc.name}" - - lifecycle { - create_before_destroy = true - } - - tag { - key = "org" - value = "${var.github_org_id}" - propagate_at_launch = true - } - - tag { - key = "enviroment" - value = "${var.environment}" - propagate_at_launch = true - } -} - -output "main_security_group_id" { - value = "${aws_security_group.main_host_sg.id}" -} diff --git a/instances/main.tf b/instances/main.tf new file mode 100644 index 0000000..0885fc2 --- /dev/null +++ b/instances/main.tf @@ -0,0 +1,85 @@ +variable "environment" {} +variable "main_host_subnet_id" {} +variable "main_host_instance_type" {} +variable "dock_subnet_id" {} +variable "dock_instance_type" {} +variable "private_ip" {} +variable "github_org_id" {} +variable "lc_user_data_file_location" {} +variable "key_name" {} +variable "main_sg_id" {} +variable "dock_sg_id" {} + +# Changing AMI forces new resource and will delete all everything in main host +# Ovewrite this variable with previous AMI if update is pushed +variable "main_host_ami" { + default = "ami-5fa7353f" # singe-host-ami-build-v0.0.4 +} + +variable "dock_ami" { + default = "ami-557dee35" # dock-ami-build-v.0.0.8 +} + +resource "aws_instance" "main_instance" { + ami = "${var.main_host_ami}" + instance_type = "${var.main_host_instance_type}" + associate_public_ip_address = true + private_ip = "${var.private_ip}" + vpc_security_group_ids = ["${var.main_sg_id}"] + subnet_id = "${var.main_host_subnet_id}" + key_name = "${var.key_name}" + + tags { + Name = "${var.environment}-main" + } +} + +resource "aws_launch_configuration" "dock_lc" { + name_prefix = "${var.environment}-dock-lc-" + image_id = "${var.dock_ami}" + instance_type = "${var.dock_instance_type}" + user_data = "${file("${var.lc_user_data_file_location}")}" + key_name = "${var.key_name}" + security_groups = ["${var.dock_sg_id}"] + + root_block_device { + volume_size = 10 + } + + ebs_block_device { + device_name = "/dev/sdb" + snapshot_id = "snap-c77705e9" + volume_size = 50 + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_autoscaling_group" "dock_auto_scaling_group" { + name = "asg-${var.environment}-${var.github_org_id}" + max_size = 30 + min_size = 2 + health_check_grace_period = 300 + health_check_type = "EC2" + desired_capacity = 2 # Start off with 0 and increase manually when main host is running + vpc_zone_identifier = ["${var.dock_subnet_id}"] + launch_configuration = "${aws_launch_configuration.dock_lc.name}" + + lifecycle { + create_before_destroy = true + } + + tag { + key = "org" + value = "${var.github_org_id}" + propagate_at_launch = true + } + + tag { + key = "enviroment" + value = "${var.environment}" + propagate_at_launch = true + } +} diff --git a/keypair/main.tf b/keypair/main.tf new file mode 100644 index 0000000..225f297 --- /dev/null +++ b/keypair/main.tf @@ -0,0 +1,12 @@ +variable "public_key" {} +variable "environment" {} + +resource "aws_key_pair" "main_key" { + key_name = "${var.environment}-key-pair" + public_key = "${var.public_key}" +} + +output "key_pair_name" { + value = "${aws_key_pair.main_key.key_name}" +} + diff --git a/main.tf b/main.tf index 843623f..d9cf6e5 100644 --- a/main.tf +++ b/main.tf @@ -2,6 +2,31 @@ provider "aws" { region = "${var.aws_region}" } +module "key_pair" { + source = "./keypair" + environment = "${var.environment}" + public_key = "${var.public_key}" +} + +module "vpc" { + source = "./vpc" + environment = "${var.environment}" +} + +module "subnets" { + source = "./subnets" + environment = "${var.environment}" + region = "${var.aws_region}" + vpc_id = "${module.vpc.main_vpc_id}" + public_route_table_id = "${module.vpc.public_route_table_id}" +} + +module "security_groups" { + source = "./security-groups" + environment = "${var.environment}" + vpc_id = "${module.vpc.main_vpc_id}" +} + module "s3" { source = "./s3" domain = "${var.domain}" @@ -9,29 +34,76 @@ module "s3" { force_destroy = "${var.force_destroy_s3_buckets}" } -module "instances-and-security-groups" { - source = "./instances-and-security-groups" +module "bastion" { + source = "./bastion" + environment = "${var.environment}" + sg_id = "${module.security_groups.bastion_sg_id}" + subnet_id = "${module.subnets.main_subnet_id}" + key_name = "${module.key_pair.key_pair_name}" +} + +module "instances" { + source = "./instances" environment = "${var.environment}" - vpc_id = "${var.main_host_vpc_id}" - main_host_subnet_id = "${var.main_host_subnet_id}" - dock_subnet_id = "${var.dock_subnet_id}" + main_host_subnet_id = "${module.subnets.main_subnet_id}" + dock_subnet_id = "${module.subnets.dock_subnet_id}" private_ip = "${var.main_host_private_ip}" github_org_id = "${var.github_org_id}" lc_user_data_file_location = "${var.lc_user_data_file_location}" - key_name = "${var.key_name}" - bastion_sg_id = "${var.bastion_sg_id}" + key_name = "${module.key_pair.key_pair_name}" main_host_instance_type = "${var.main_host_instance_type}" dock_instance_type = "${var.dock_instance_type}" + main_sg_id = "${module.security_groups.main_sg_id}" + dock_sg_id = "${module.security_groups.dock_sg_id}" } module "database" { - source = "./database" - environment = "${var.environment}" - username = "${var.db_username}" - password = "${var.db_password}" - port = "${var.db_port}" - subnet_group_name = "${var.db_subnet_group_name}" - main_host_security_group_id = "${module.instances-and-security-groups.main_security_group_id}" - vpc_id = "${var.main_host_vpc_id}" - instance_class = "${var.db_instance_class}" + source = "./database" + environment = "${var.environment}" + username = "${var.db_username}" + password = "${var.db_password}" + port = "${var.db_port}" + subnet_group_name = "${module.subnets.database_subnet_group_name}" + security_group_id = "${module.security_groups.db_sg_id}" + instance_class = "${var.db_instance_class}" +} + +output "environment" { + value = "${var.environment}" +} + +output "vpc_id" { + value = "${module.vpc.main_vpc_id}" +} + +output "main_host_subnet_id" { + value = "${module.subnets.main_subnet_id}" +} + +output "dock_subnet_id" { + value = "${module.subnets.dock_subnet_id}" +} + +output "database_subnet_group_name" { + value = "${module.subnets.database_subnet_group_name}" +} + +output "key_pair_name" { + value = "${module.key_pair.key_pair_name}" +} + +output "aws_region" { + value = "${var.aws_region}" +} + +output "postgres_user" { + value = "${var.db_username}" +} + +output "postgres_password" { + value = "${var.db_password}" +} + +output "main_host_private_ip" { + value = "${var.main_host_private_ip}" } diff --git a/security-groups/main.tf b/security-groups/main.tf new file mode 100644 index 0000000..9e5013e --- /dev/null +++ b/security-groups/main.tf @@ -0,0 +1,148 @@ +variable "environment" {} +variable "vpc_id" {} + +resource "aws_security_group" "bastion_sg" { + name = "${var.environment}-bastion-sg" + description = "Allow ssh access through this box" + vpc_id = "${var.vpc_id}" + + ingress = { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + self = false + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_security_group" "main_host_sg" { + name = "${var.environment}-main-host-sg" + description = "Allow all inbound traffic on all traffic over port 80" + vpc_id = "${var.vpc_id}" + + ingress { + from_port = 80 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + security_groups = ["${aws_security_group.bastion_sg.id}"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_security_group" "dock_sg" { + name = "${var.environment}-dock-sg" + description = "Allow all traffic from main host and between docks" + vpc_id = "${var.vpc_id}" + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + security_groups = ["${aws_security_group.bastion_sg.id}"] + } + + ingress { + from_port = 32768 + to_port = 65535 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } + + ingress { + from_port = 8200 + to_port = 8201 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } + + ingress { + from_port = 4242 + to_port = 4242 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } + + ingress { + from_port = 29006 + to_port = 29007 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } + + ingress { + from_port = 3100 + to_port = 3100 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } + + ingress { + from_port = 6783 + to_port = 6783 + protocol = "tcp" + self = true + } + + ingress { + from_port = 6783 + to_port = 6783 + protocol = "udp" + self = true + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_security_group" "database_sg" { + name = "${var.environment}-database-sg" + description = "Allow inbound traffic from main host to DB port" + vpc_id = "${var.vpc_id}" + + ingress { + from_port = 5432 + to_port = 5432 + protocol = "tcp" + security_groups = ["${aws_security_group.main_host_sg.id}"] + } +} + +output "bastion_sg_id" { + value = "${aws_security_group.bastion_sg.id}" +} + +output "main_sg_id" { + value = "${aws_security_group.main_host_sg.id}" +} + +output "db_sg_id" { + value = "${aws_security_group.database_sg.id}" +} + +output "dock_sg_id" { + value = "${aws_security_group.dock_sg.id}" +} diff --git a/subnets/main.tf b/subnets/main.tf new file mode 100644 index 0000000..b85a946 --- /dev/null +++ b/subnets/main.tf @@ -0,0 +1,63 @@ +variable "environment" {} +variable "vpc_id" {} +variable "region" {} +variable "public_route_table_id" {} + +resource "aws_subnet" "main_subnet" { + vpc_id = "${var.vpc_id}" + cidr_block = "10.10.1.0/24" + map_public_ip_on_launch = true + availability_zone = "${var.region}a" + + tags { + Name = "${var.environment}-main-subnet" + Environment = "${var.environment}" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_subnet" "dock_subnet" { + vpc_id = "${var.vpc_id}" + cidr_block = "10.10.2.0/24" + availability_zone = "${var.region}b" + + tags { + Name = "${var.environment}-dock-subnet" + Environment = "${var.environment}" + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_db_subnet_group" "database_subnet_group" { + name = "${var.environment}-database-subnet-group" + # NOTE: What subnets should this have? + subnet_ids = ["${aws_subnet.main_subnet.id}", "${aws_subnet.dock_subnet.id}"] + + tags { + Name = "${var.environment}-database-subnet-group" + Environment = "${var.environment}" + } +} + +resource "aws_route_table_association" "public" { + subnet_id = "${aws_subnet.main_subnet.id}" + route_table_id = "${var.public_route_table_id}" +} + +output "main_subnet_id" { + value = "${aws_subnet.main_subnet.id}" +} + +output "dock_subnet_id" { + value = "${aws_subnet.dock_subnet.id}" +} + +output "database_subnet_group_name" { + value = "${aws_db_subnet_group.database_subnet_group.name}" +} diff --git a/variables.tf b/variables.tf index 6005f5d..7013980 100644 --- a/variables.tf +++ b/variables.tf @@ -1,6 +1,5 @@ # General - variable "aws_region" { description = "AWS region to launch servers." default = "us-west-2" @@ -18,12 +17,19 @@ variable "domain" { type = "string" } +# Key Pair + +variable "public_key" { + description = "Public key for key which will be used for sshing into instances through bastion" + type = "string" +} + # S3 Buckets variable "force_destroy_s3_buckets" { description = "Forces destroy of S3 buckets and deletes all their content. Default to false. Use this only when tearing down an environment. Before running `terraform destroy`, `terraform apply` must be run to updates buckets." type = "string" - default = "false" # https://www.terraform.io/docs/configuration/variables.html#booleans + default = "true" # https://www.terraform.io/docs/configuration/variables.html#booleans } # Databases @@ -44,11 +50,6 @@ variable "db_port" { type = "string" } -variable "db_subnet_group_name" { - description = "Subnet in which database will be created" - type = "string" -} - variable "db_instance_class" { description = "Type of instance that will be used for database" type = "string" @@ -57,24 +58,9 @@ variable "db_instance_class" { # EC2 Instances -variable "main_host_vpc_id" { - description = "VPC in which security groups and instance for main host will be created." - type = "string" -} - -variable "main_host_subnet_id" { - description = "Subnet in which main host EC2 instance will be created. Subnet must be part of VPC in `main_host_vpc_id`" - type = "string" -} - -variable "bastion_sg_id" { - description = "Security group id for bastion instance" - type = "string" -} - variable "main_host_private_ip" { description = "Private IP address in VPC for main-host. This is important because ip address is encoded in launch configuration for docks." - default = "10.4.0.100" + default = "10.10.1.100" type = "string" } @@ -84,11 +70,6 @@ variable "main_host_instance_type" { default = "m4.2xlarge" } -variable "dock_subnet_id" { - description = "Subnet in which dock EC2 instance will be created. Subnet must be part of VPC in `main_host_vpc_id`" - type = "string" -} - variable "dock_instance_type" { description = "Type of instance that will be used for all docks" type = "string" @@ -104,8 +85,3 @@ variable "lc_user_data_file_location" { description = "Location for file generated for launch configuration. This file needs to have correct IPs, ports, and files" type = "string" } - -variable "key_name" { - description = "Name of ssh key to be used for accessing all instances" - type = "string" -} diff --git a/vpc/main.tf b/vpc/main.tf new file mode 100644 index 0000000..15274a1 --- /dev/null +++ b/vpc/main.tf @@ -0,0 +1,44 @@ +variable "environment" {} + +resource "aws_vpc" "main" { + cidr_block = "10.10.0.0/16" + enable_dns_hostnames = true + + tags { + Name = "${var.environment}-main" + } +} + +resource "aws_internet_gateway" "main" { + vpc_id = "${aws_vpc.main.id}" + + tags { + Name = "${var.environment}-main-ig" + } +} + +resource "aws_route_table" "main" { + vpc_id = "${aws_vpc.main.id}" + + route { + cidr_block = "0.0.0.0/0" + gateway_id = "${aws_internet_gateway.main.id}" + } + + tags { + Name = "${var.environment}-main-route-table" + } +} + +resource "aws_main_route_table_association" "main_route_table" { + vpc_id = "${aws_vpc.main.id}" + route_table_id = "${aws_route_table.main.id}" +} + +output "main_vpc_id" { + value = "${aws_vpc.main.id}" +} + +output "public_route_table_id" { + value = "${aws_route_table.main.id}" +}