## IAM Policies and Roles ## locals { account_id = "${data.aws_caller_identity.current.account_id}" } resource "aws_iam_role" "ecs_service_role" { name = "ecs_service_role" path = "/" assume_role_policy = data.aws_iam_policy_document.ecs_service_role_pd.json inline_policy { name = "ecs-service" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:Describe*", "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:RegisterTargets", "ec2:Describe*", "ec2:AuthorizeSecurityGroupIngress" ] Effect = "Allow" Resource = "*" } ] }) } } resource "aws_iam_role" "ec2_role" { name = "ec2_role" path = "/" assume_role_policy = data.aws_iam_policy_document.ec2_role_pd.json managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"] inline_policy { name = "ecs-service" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ec2:DescribeTags", "ecs:CreateCluster", "ecs:DeregisterContainerInstance", "ecs:DiscoverPollEndpoint", "ecs:Poll", "ecs:RegisterContainerInstance", "ecs:StartTelemetrySession", "ecs:UpdateContainerInstancesState", "ecs:Submit*" ] Effect = "Allow" Resource = "*" } ] }) } inline_policy { name = "dynamo-access" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "logs:CreateLogStream", "logs:PutLogEvents", "dynamodb:Query", "dynamodb:Scan", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem" ] Effect = "Allow" Resource = [ "arn:aws:logs:us-east-1:${local.account_id}:*/*", "arn:aws:dynamodb:us-east-1:${local.account_id}:*/*" ] } ] }) } inline_policy { name = "ecr-access" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken" ] Effect = "Allow" Resource = "*" } ] }) } } resource "aws_iam_role" "autoscaling_role" { name = "autoscaling_role" path = "/" assume_role_policy = data.aws_iam_policy_document.autoscaling_pd.json inline_policy { name = "service-autoscaling" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ecs:DescribeServices", "ecs:UpdateService", "cloudwatch:PutMetricAlarm", "cloudwatch:DescribeAlarms", "cloudwatch:DeleteAlarms" ] Effect = "Allow" Resource = [ "arn:aws:ecs:us-east-1:${local.account_id}:*/*", "arn:aws:cloudwatch:us-east-1:${local.account_id}:*/*" ] } ] }) } } # Create a VPC. resource "aws_vpc" "main" { cidr_block = var.vpc_cidr enable_dns_support = var.vpc_dns_support enable_dns_hostnames = var.vpc_dns_hostnames tags = { Name = "terraform" } } # Create an Internet Gateway. resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.main.id } # Create the first public subnet in the VPC for external traffic. resource "aws_subnet" "public_1" { vpc_id = aws_vpc.main.id cidr_block = var.public_cidr_1 availability_zone = var.availability_zone[0] map_public_ip_on_launch = var.map_public_ip } # Create the second public subnet in the VPC for external traffic. resource "aws_subnet" "public_2" { vpc_id = aws_vpc.main.id cidr_block = var.public_cidr_2 availability_zone = var.availability_zone[1] map_public_ip_on_launch = var.map_public_ip } # Create the first private subnet in the VPC for internal traffic. resource "aws_subnet" "private_1" { vpc_id = aws_vpc.main.id cidr_block = var.private_cidr_1 availability_zone = var.availability_zone[0] } # Create the second private subnet in the VPC for internal traffic. resource "aws_subnet" "private_2" { vpc_id = aws_vpc.main.id cidr_block = var.private_cidr_2 availability_zone = var.availability_zone[1] } # A NAT gateway is required for the private subnet. # Configure EIP for the first NAT Gateway. resource "aws_eip" "nat_1" { vpc = true } # configure EIP for the second NAT gateway. resource "aws_eip" "nat_2" { vpc = true } # Create the first NAT gateway. resource "aws_nat_gateway" "ngw_1" { subnet_id = aws_subnet.public_1.id allocation_id = aws_eip.nat_1.id # Requires a resource dependency. depends_on = [aws_internet_gateway.igw] } # Create the second NAT gateway. resource "aws_nat_gateway" "ngw_2" { subnet_id = aws_subnet.public_2.id allocation_id = aws_eip.nat_2.id # Requires a resource dependency. depends_on = [aws_internet_gateway.igw] } # Create the route tables for the subnets. # Create the first private subnet route table. resource "aws_route_table" "private_1" { vpc_id = aws_vpc.main.id } # Cerate the second private subnet route table. resource "aws_route_table" "private_2" { vpc_id = aws_vpc.main.id } # Create the first private subnet route. resource "aws_route" "private_1" { route_table_id = aws_route_table.private_1.id destination_cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.ngw_1.id } # create the second perivate subnet route. resource "aws_route" "private_2" { route_table_id = aws_route_table.private_2.id destination_cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.ngw_2.id } # Associate the private subnet route table to the first private subnet. resource "aws_route_table_association" "private_1" { subnet_id = aws_subnet.private_1.id route_table_id = aws_route_table.private_1.id } # Associate the private subnet route table to the second private subnet. resource "aws_route_table_association" "private_2" { subnet_id = aws_subnet.private_2.id route_table_id = aws_route_table.private_2.id } # Create the public subnet route table. resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id } # Create the public subnet route. resource "aws_route" "public" { route_table_id = aws_route_table.public.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.igw.id } # Associate the public subnet route table to the first public subnet. resource "aws_route_table_association" "public_1" { subnet_id = aws_subnet.public_1.id route_table_id = aws_route_table.public.id } # Associate the public subnet route table to the second public subnet. resource "aws_route_table_association" "public_2" { subnet_id = aws_subnet.public_2.id route_table_id = aws_route_table.public.id } # Create a public NACL. resource "aws_network_acl" "public" { vpc_id = aws_vpc.main.id } # Create the NACL rules for the public NACL. resource "aws_network_acl_rule" "public_ingress" { network_acl_id = aws_network_acl.public.id rule_number = 100 protocol = "-1" rule_action = "allow" cidr_block = "0.0.0.0/0" } resource "aws_network_acl_rule" "public_egress" { network_acl_id = aws_network_acl.public.id rule_number = 100 egress = true protocol = "-1" rule_action = "allow" cidr_block = "0.0.0.0/0" } # Create a private NACL. resource "aws_network_acl" "private" { vpc_id = aws_vpc.main.id } # Create the NACL rules for the private NACL. resource "aws_network_acl_rule" "private_ingress" { network_acl_id = aws_network_acl.private.id rule_number = 100 protocol = "-1" rule_action = "allow" cidr_block = "0.0.0.0/0" } resource "aws_network_acl_rule" "private_egress" { network_acl_id = aws_network_acl.private.id rule_number = 100 egress = true protocol = "-1" rule_action = "allow" cidr_block = "0.0.0.0/0" } # Create a security group for the ALB. resource "aws_security_group" "ecs_sg" { name = "ecs-sg" description = "ECS security group for the ALB." vpc_id = aws_vpc.main.id ingress { protocol = "tcp" from_port = 80 to_port = 80 cidr_blocks = ["0.0.0.0/0"] } ingress { protocol = "tcp" from_port = 8080 to_port = 8080 cidr_blocks = ["0.0.0.0/0"] } ingress { protocol = "tcp" from_port = 31000 to_port = 61000 self = true } egress { protocol = "-1" from_port = 0 to_port = 0 cidr_blocks = ["0.0.0.0/0"] } } # Create a CloudWatch log group. resource "aws_cloudwatch_log_group" "ecs_logs" { name = "ecs-logs" retention_in_days = 14 } # Create an ECS task definition. resource "aws_ecs_task_definition" "ecs_task_definition" { family = "${var.service_name}-ecs-demo-app" container_definitions = <