diff --git a/infra/alpha.tf b/infra/alpha.tf index 01f233d..255d740 100644 --- a/infra/alpha.tf +++ b/infra/alpha.tf @@ -2,19 +2,16 @@ # Essentially it is a cluster with services that we # choose to expose to the internet in one form or another -# Logging Configuration for services inside the cluster -####################################################### -resource "aws_cloudwatch_log_group" "alpha" { - name = "alpha-log" -} + # Alpha cluster definition ########################### resource "aws_ecs_cluster" "alpha" { - name = "alpha" + name = "${var.athens_prefix}-athens-alpha" configuration { execute_command_configuration { + logging = "OVERRIDE" log_configuration { cloud_watch_log_group_name = aws_cloudwatch_log_group.alpha.name } @@ -23,38 +20,70 @@ resource "aws_ecs_cluster" "alpha" { } -# Lewdlad Service Definition -############################ -resource "aws_ecs_task_definition" "lewdlad" { - family = "lewdlad-task-definition" +# Lewdlad Task Definition +# This is what the service will launch to actually provide the lewdlad service +############################################################################## +resource "aws_ecs_task_definition" "sample" { + family = "${var.athens_prefix}-sample" + + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + execution_role_arn = aws_iam_role.alpha_iam_role.arn + + cpu = 256 + memory = 512 + container_definitions = jsonencode([ { - name = "lewdlad-container" - image = "registry.gitlab.com/shockrah/left-coast-server-bot:latest" - # Literally the smallest amount that fargate will allow - cpu = 256 - memory = 512 + name = "${var.athens_prefix}-sample-container" + image = "nginx" + cpu = 256 + memory = 512 essential = true - environment = [ - { name: DISCORD_ID, value: var.DISCORD_ID }, - { name: DISCORD_TOKEN, value: var.DISCORD_TOKEN }, - { name: AWS_API_ID, value: var.AWS_API_ID }, - { name: AWS_API_STAGE, value: var.AWS_API_STAGE }, - { name: AWS_API_REGION, value: var.AWS_API_REGION }, - { name: AWS_API_KEY, value: var.AWS_API_KEY }, - { name: DEV_GUILD_ID, value: var.DEV_GUILD_ID }, - { name: BEEHIVE_ID, value: var.BEEHIVE_ID }, + portMappings = [ + { + containerPort = 80 + hostPort = 80 + } ] + logConfiguration = { + logDriver = "awslogs" + options = { + awslogs-group = aws_cloudwatch_log_group.alpha.name + awslogs-region = "us-west-1" + awslogs-stream-prefix = "sample-container" + } + } } ]) + tags = { + Name = "${var.athens_prefix}-sample-task-def-container" + } } -resource "aws_ecs_service" "lewdlad" { - name = "lewdlad" - cluster = aws_ecs_cluster.alpha.arn - task_definition = aws_ecs_task_definition.lewdlad.arn +# Service level definition +########################## +resource "aws_ecs_service" "sample" { + name = "${var.athens_prefix}-sample-service" + cluster = aws_ecs_cluster.alpha.id + task_definition = aws_ecs_task_definition.sample.arn desired_count = 1 + launch_type = "FARGATE" + load_balancer { + target_group_arn = aws_lb_target_group.alpha_cluster.arn + container_name = "${var.athens_prefix}-sample-container" + container_port = 80 + } + + network_configuration { + assign_public_ip = true + subnets = [ + aws_subnet.delphi.id, + aws_subnet.crete_subnet.id + ] + security_groups = [ + aws_security_group.ecs_web_ingress.id, + aws_security_group.base_ecs.id + ] + } } - - - diff --git a/infra/atlas.tf b/infra/atlas.tf index 3798b69..c0216fb 100644 --- a/infra/atlas.tf +++ b/infra/atlas.tf @@ -1,3 +1,6 @@ +# NOTE: this will no longer be used and is getting removed once we seutp the +# new alpha cluster correctly + # This is the continuation of the old alpha host but with much cleaner code # and less manual infra setup involved. Key differences are that block storage # is now completely kept in this module instead of yolo'd out like before. @@ -29,38 +32,3 @@ resource "aws_ebs_volume" "clips-shockrah-xyz" { Description = "Used for the clippable instance" } } - -######################### ATTACHMENT FOR files.leftcoast.space ################# -resource "aws_volume_attachment" "files-leftcoast-space" { - device_name = "/dev/sdf" - volume_id = aws_ebs_volume.files-leftcoast-space.id - instance_id = aws_instance.atlas.id -} - - -######################### ATTACHMENT FOR clips.shockrah.xyz #################### -resource "aws_volume_attachment" "clips-shockrah-xyz" { - device_name = "/dev/sdg" - volume_id = aws_ebs_volume.clips-shockrah-xyz.id - instance_id = aws_instance.atlas.id -} - -######################### INSTANCE CONFIGURATION ############################### -resource "aws_instance" "atlas" { - ami = var.atlas_ami_id - instance_type = var.atlas_instance_type - - key_name = var.atlas_ssh_key_name - - private_ip = "10.0.1.20" - vpc_security_group_ids = [ - aws_security_group.general_web_req.id, - aws_security_group.remote_ssh_rec.id - ] - subnet_id = aws_subnet.crete_subnet.id - tags = { - Name = "Atlas Host" - Description = "Simple Docker host for some personal stuff" - } - -} diff --git a/infra/cert.tf b/infra/cert.tf new file mode 100644 index 0000000..b18761f --- /dev/null +++ b/infra/cert.tf @@ -0,0 +1,15 @@ +# Here is the TLS cert that we create for the alpha cluster + +resource "aws_acm_certificate" "sample" { + domain_name = "*.project-athens.xyz" + validation_method = "DNS" + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_acm_certificate_validation" "sample" { + certificate_arn = aws_acm_certificate.sample.arn + validation_record_fqdns = [ aws_route53_record.project-athens-record["2"].fqdn ] +} diff --git a/infra/cluster-logging.tf b/infra/cluster-logging.tf new file mode 100644 index 0000000..f06ed82 --- /dev/null +++ b/infra/cluster-logging.tf @@ -0,0 +1,28 @@ +# Logging Configuration for services inside the cluster +####################################################### + +# Alpha Cloudwatch logging configuration +######################################## +resource "aws_cloudwatch_log_group" "alpha" { + name = "${var.athens_prefix}-alpha-log" + retention_in_days = 7 +} + +# Alpha logging role +##################### +resource "aws_iam_role" "alpha_iam_role" { + name = "${var.athens_prefix}-alpha-iam-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Principal = { + Service = [ "ecs-tasks.amazonaws.com" ] + } + Effect = "Allow" + } + ] + }) +} + diff --git a/infra/eip.tf b/infra/eip.tf index c91a760..3a65d6b 100644 --- a/infra/eip.tf +++ b/infra/eip.tf @@ -1,12 +1,3 @@ -resource "aws_eip" "alpha_eip" { - instance = aws_instance.alpha.id - vpc = true - tags = { - Name = "Alpha EIP" - } -} - - resource "aws_eip" "beta_eip" { vpc = true instance = aws_instance.beta.id diff --git a/infra/input-vars.tf b/infra/input-vars.tf index afb9896..9e233ef 100644 --- a/infra/input-vars.tf +++ b/infra/input-vars.tf @@ -103,3 +103,11 @@ variable "athens_cidr" { description = "VPC Subnet CIDR block" type = string } + +######################### Alpha Cluster variables + +variable "athens_prefix" { + description = "Prefix for all things in alpha cluster" + type = string + default = "athens" +} diff --git a/infra/load-balancer.tf b/infra/load-balancer.tf new file mode 100644 index 0000000..b8acc59 --- /dev/null +++ b/infra/load-balancer.tf @@ -0,0 +1,43 @@ +# Here is the application load balancer that we use for services hosted on ECS +############################################################################## + + +# The LB that we'll use to move traffic into our services +######################################################### +resource "aws_lb" "alpha" { + name = "alpha-lb" + internal = false + load_balancer_type = "application" + subnets = [ aws_subnet.delphi.id, aws_subnet.crete_subnet.id ] + security_groups = [ + aws_security_group.ecs_web_ingress.id, + aws_security_group.load_balancer_health_check.id + ] + # TODO: change this to true later + enable_deletion_protection = false +} + +## ECS services manage themselves when it comes to registering to the +## target group so we only need to provide the pool +##################################################################### +resource "aws_lb_target_group" "alpha_cluster" { + name = "${var.athens_prefix}-alpha-cluster" + port = 80 + protocol = "HTTP" + target_type = "ip" + vpc_id = aws_vpc.athens_vpc.id +} + +resource "aws_lb_listener" "https" { + load_balancer_arn = aws_lb.alpha.arn + port = 443 + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-2016-08" + + certificate_arn = aws_acm_certificate_validation.sample.certificate_arn + default_action { + type = "forward" + target_group_arn = aws_lb_target_group.alpha_cluster.arn + } +} + diff --git a/infra/roles.tf b/infra/roles.tf new file mode 100644 index 0000000..a21bd56 --- /dev/null +++ b/infra/roles.tf @@ -0,0 +1,24 @@ +resource "aws_iam_policy" "alpha_iam_policy" { + name = "${var.athens_prefix}-alpha-iam-policy" + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + ] + "Resource" = "*" + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "alpha_logs" { + role = aws_iam_role.alpha_iam_role.name + policy_arn = aws_iam_policy.alpha_iam_policy.arn +} + diff --git a/infra/route-table.tf b/infra/route-table.tf index 36f65ad..8901a67 100644 --- a/infra/route-table.tf +++ b/infra/route-table.tf @@ -10,7 +10,14 @@ resource "aws_route_table" "crete_route_table" { Name = "Crete IGW Route Table" } } + + resource "aws_route_table_association" "crete_gateway_association" { subnet_id = aws_subnet.crete_subnet.id route_table_id = aws_route_table.crete_route_table.id } + +resource "aws_route_table_association" "delphi_gateway_association" { + subnet_id = aws_subnet.delphi.id + route_table_id = aws_route_table.crete_route_table.id +} diff --git a/infra/route53-project-athens-xyz.tf b/infra/route53-project-athens-xyz.tf new file mode 100644 index 0000000..31cf342 --- /dev/null +++ b/infra/route53-project-athens-xyz.tf @@ -0,0 +1,59 @@ +############################# +# project-athens.xyz DNS ZONE +############################# + +# This entry is just for the sample service that is just plain nginx +# No TLS will be placed on this just yet as we need to make sure this +# and the load balancer are setup to receive things properly +resource "aws_route53_zone" "project-athens" { + name = "project-athens.xyz" + comment = "Project Athens domain zone" +} + + +locals { + project-athens-records = [ + { + name = "project-athens.xyz" + type = "NS" + ttl = 172800 + records = [ + "ns-806.awsdns-36.net.", + "ns-1881.awsdns-43.co.uk.", + "ns-1109.awsdns-10.org.", + "ns-11.awsdns-01.com.", + ] + }, + { + name = "project-athens.xyz" + type = "SOA" + ttl = 900 + records = [ + "ns-806.awsdns-36.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400" + ] + }, + { + name = tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_name + type = tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_type + records = [ tolist(aws_acm_certificate.sample.domain_validation_options)[0].resource_record_value ] + }, + { + name = "sample.project-athens.xyz" + type = "CNAME" + records = [ aws_lb.alpha.dns_name ] + } + ] +} + +resource "aws_route53_record" "project-athens-record" { + for_each = { + for index, record in local.project-athens-records: + index => record + } + zone_id = aws_route53_zone.project-athens.id + name = each.value.name + type = lookup(each.value, "type", "A") + ttl = lookup(each.value, "ttl", 300) + records = each.value.records +} + diff --git a/infra/route53-shockrah-xyz.tf b/infra/route53-shockrah-xyz.tf new file mode 100644 index 0000000..f78e653 --- /dev/null +++ b/infra/route53-shockrah-xyz.tf @@ -0,0 +1,56 @@ +############################# +# shockrah.xyz DNS ZONE +############################# + +resource "aws_route53_zone" "shockrah-xyz" { + name = "shockrah.xyz" + comment = "Main shockrah.xyz zone - for personal stuff" +} + +locals { + records = [ + { + name = "shockrah.xyz" + type = "NS" + ttl = 172800 + records = [ + "ns-612.awsdns-12.net.", + "ns-285.awsdns-35.com.", + "ns-1702.awsdns-20.co.uk.", + "ns-1360.awsdns-42.org.", + ] + }, + { + name = "shockrah.xyz" + type = "SOA" + ttl = 900 + records = [ + "ns-612.awsdns-12.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400" + ] + }, + { + name = "shockrah.xyz" + type = "TXT" + ttl = 300 + records = [ "v=spf1 include:_mailcust.gandi.net ?all" ] + }, + { name = "shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] }, + { name = "freechat.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] }, + { name = "resume.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] }, + { name = "www.shockrah.xyz", records = [ aws_eip.beta_eip.public_ip ] }, + ] +} + +resource "aws_route53_record" "shockrah-xyz-record" { + for_each = { + for index, record in local.records: + index => record + } + + zone_id = aws_route53_zone.shockrah-xyz.id + name = each.value.name + type = lookup(each.value, "type", "A") + ttl = lookup(each.value, "ttl", 300) + records = each.value.records +} + diff --git a/infra/security-groups.tf b/infra/security-groups.tf index e8ab64e..41dd63c 100644 --- a/infra/security-groups.tf +++ b/infra/security-groups.tf @@ -1,5 +1,56 @@ # Here are general definitions for security rulesets +resource "aws_security_group" "ecs_web_ingress" { + name = "Alpha-Web-Ingress" + description = "Allow web traffic into the host" + vpc_id = aws_vpc.athens_vpc.id + ingress { + cidr_blocks = ["0.0.0.0/0"] + from_port = 443 + to_port = 443 + protocol = "tcp" + } + ingress { + cidr_blocks = ["0.0.0.0/0"] + from_port = 80 + to_port = 80 + protocol = "tcp" + } +} + +resource "aws_security_group" "base_ecs" { + vpc_id = aws_vpc.athens_vpc.id + egress { + cidr_blocks = ["0.0.0.0/0"] + from_port = 80 + to_port = 80 + protocol = "tcp" + } + egress { + cidr_blocks = ["0.0.0.0/0"] + from_port = 443 + to_port = 443 + protocol = "tcp" + } + egress { + cidr_blocks = ["0.0.0.0/0"] + from_port = 2049 + to_port = 2049 + protocol = "tcp" + } +} + +resource "aws_security_group" "load_balancer_health_check" { + name = "Load Balancer Health check" + vpc_id = aws_vpc.athens_vpc.id + egress { + cidr_blocks = ["10.0.0.0/8"] + from_port = 80 + to_port = 80 + protocol = "tcp" + } +} + resource "aws_security_group" "general_web_req" { name = "Athens General web server ruleset" description = "Allowing strictly web traffic" diff --git a/infra/subnet.tf b/infra/subnet.tf index 682a0d7..7576df2 100644 --- a/infra/subnet.tf +++ b/infra/subnet.tf @@ -1,6 +1,5 @@ # This script represents the subnet structure for Crete(primary subnet) -# Crete will serve as the private subnet with internal services resource "aws_subnet" "crete_subnet" { vpc_id = aws_vpc.athens_vpc.id # 10.0.1.0/24 @@ -8,6 +7,17 @@ resource "aws_subnet" "crete_subnet" { availability_zone = var.athens_availability_zone tags = { - Name = "Crete Subnet - Internal" + Name = "Crete Subnet" + Description = "Main subnet for EC2 and Alpha-LB" + } +} + +resource "aws_subnet" "delphi" { + vpc_id = aws_vpc.athens_vpc.id + cidr_block = "10.0.2.0/24" + availability_zone = "us-west-1c" + tags = { + Name = "Delphi Subnet" + Description = "Secondary subnet for the Alpha-LB mostly" } }