diff --git a/dlp-terraform/ecs/ecs.tf b/dlp-terraform/ecs/ecs.tf index d9851788..a0a11245 100644 --- a/dlp-terraform/ecs/ecs.tf +++ b/dlp-terraform/ecs/ecs.tf @@ -44,24 +44,7 @@ data "aws_iam_policy_document" "ecs_task_doc" { } } -resource "aws_iam_role" "ecs_task_role" { - name_prefix = "backend-ecs-task-role" - assume_role_policy = data.aws_iam_policy_document.ecs_task_doc.json -} - -resource "aws_iam_role_policy_attachment" "ecs_task_role_policy" { - for_each = toset([ - "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess", - "arn:aws:iam::aws:policy/SecretsManagerReadWrite", - "arn:aws:iam::aws:policy/AmazonSQSFullAccess", - "arn:aws:iam::aws:policy/AmazonS3FullAccess" - ]) - - role = aws_iam_role.ecs_task_role.name - policy_arn = each.value -} - - +# --- ECS Exec Role --- resource "aws_iam_role" "ecs_exec_role" { name_prefix = "backend-ecs-exec-role" assume_role_policy = data.aws_iam_policy_document.ecs_task_doc.json diff --git a/dlp-terraform/ecs/ecs_django_service.tf b/dlp-terraform/ecs/ecs_django_service.tf index 6a2168d7..910bfb45 100644 --- a/dlp-terraform/ecs/ecs_django_service.tf +++ b/dlp-terraform/ecs/ecs_django_service.tf @@ -1,20 +1,38 @@ +# --- ECS Task Role --- # +resource "aws_iam_role" "django_ecs_task_role" { + name_prefix = "django-ecs-task-role" + assume_role_policy = data.aws_iam_policy_document.ecs_task_doc.json + + inline_policy { + name = "django-inline-policy" + policy = data.aws_iam_policy_document.django_inline_policy.json + } +} + +data "aws_iam_policy_document" "django_inline_policy" { + statement { + actions = ["secretsmanager:GetSecretValue"] + resources = ["arn:aws:secretsmanager:us-east-1:521654603461:secret:DLP/Firebase/Admin_SDK-8g8IDn"] + } +} + resource "aws_ecs_task_definition" "django" { - family = "django" - task_role_arn = aws_iam_role.ecs_task_role.arn - execution_role_arn = aws_iam_role.ecs_exec_role.arn - network_mode = "awsvpc" + family = "django" + task_role_arn = aws_iam_role.django_ecs_task_role.arn + execution_role_arn = aws_iam_role.ecs_exec_role.arn + network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] - cpu = 1024 - memory = 2048 + cpu = 1024 + memory = 2048 container_definitions = jsonencode([ { - "name": "django", + "name" : "django", "image" : "${aws_ecr_repository.django.repository_url}:latest", - "cpu": 1024, - "memory": 2048, - "essential": true, - "portMappings": [ + "cpu" : 1024, + "memory" : 2048, + "essential" : true, + "portMappings" : [ { "name" : "gunicorn-port", "containerPort" : 8000, @@ -31,10 +49,10 @@ resource "aws_ecs_task_definition" "django" { "awslogs-stream-prefix" : "ecs" } }, - "environment": [ + "environment" : [ { - "name": "ALLOWED_HOST", - "value": "${aws_lb.main.dns_name}" + "name" : "ALLOWED_HOST", + "value" : "${aws_lb.main.dns_name}" } ] } @@ -50,27 +68,27 @@ resource "aws_security_group" "ecs_django_sg" { resource "aws_vpc_security_group_ingress_rule" "ecs_django_sg_ingress" { security_group_id = aws_security_group.ecs_django_sg.id - ip_protocol = "-1" + ip_protocol = "-1" referenced_security_group_id = aws_security_group.http.id -} +} resource "aws_vpc_security_group_egress_rule" "ecs_django_sg_egress" { security_group_id = aws_security_group.ecs_django_sg.id - ip_protocol = "-1" - cidr_ipv4 = "0.0.0.0/0" -} + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} resource "aws_ecs_service" "django" { name = "django" cluster = aws_ecs_cluster.main.id task_definition = aws_ecs_task_definition.django.arn - desired_count = 2 - launch_type = "FARGATE" + desired_count = 1 + launch_type = "FARGATE" network_configuration { - security_groups = [ aws_security_group.ecs_django_sg.id] - subnets = aws_subnet.public[*].id + security_groups = [aws_security_group.ecs_django_sg.id] + subnets = aws_subnet.public[*].id assign_public_ip = true } @@ -80,9 +98,9 @@ resource "aws_ecs_service" "django" { load_balancer { target_group_arn = aws_lb_target_group.app.arn - container_name = "django" - container_port = 8000 + container_name = "django" + container_port = 8000 } depends_on = [aws_lb_target_group.app] -} \ No newline at end of file +} diff --git a/dlp-terraform/ecs/ecs_training_service.tf b/dlp-terraform/ecs/ecs_training_service.tf index 02ebb059..d10d8662 100644 --- a/dlp-terraform/ecs/ecs_training_service.tf +++ b/dlp-terraform/ecs/ecs_training_service.tf @@ -1,6 +1,30 @@ +# --- ECS Task Role --- # +resource "aws_iam_role" "training_ecs_task_role" { + name_prefix = "training-ecs-task-role" + assume_role_policy = data.aws_iam_policy_document.ecs_task_doc.json + + inline_policy { + name = "training-inline-policy" + policy = data.aws_iam_policy_document.training_inline_policy.json + } +} + +data "aws_iam_policy_document" "training_inline_policy" { + statement { + actions = ["sqs:ReceiveMessage"] + resources = [aws_sqs_queue.training_queue.arn] + } + + statement { + actions = ["s3:ListBucket", "s3:GetObject"] + resources = [aws_s3_bucket.s3bucket_executions.arn] + } +} + +# --- ECS Task Definition --- # resource "aws_ecs_task_definition" "training" { family = "training" - task_role_arn = aws_iam_role.ecs_task_role.arn + task_role_arn = aws_iam_role.training_ecs_task_role.arn execution_role_arn = aws_iam_role.ecs_exec_role.arn network_mode = "bridge" cpu = 1024 @@ -10,15 +34,6 @@ resource "aws_ecs_task_definition" "training" { { "name" : "training", "image" : "${aws_ecr_repository.training.repository_url}:latest", - "portMappings" : [ - { - "name" : "gunicorn-port", - "containerPort" : 8000, - "hostPort" : 0, - "protocol" : "tcp", - "appProtocol" : "http" - } - ], "essential" : true, "environment" : [], "mountPoints" : [], @@ -69,18 +84,18 @@ resource "aws_ecs_service" "training" { # --- ECS Service Auto Scaling --- resource "aws_appautoscaling_target" "training_ecs_target" { - service_namespace = "ecs" + service_namespace = "ecs" scalable_dimension = "ecs:service:DesiredCount" - resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.training.name}" - min_capacity = 0 - max_capacity = 2 + resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.training.name}" + min_capacity = 0 + max_capacity = 2 } resource "aws_appautoscaling_policy" "training_ecs_target_cpu" { - name = "training-application-scaling-policy-cpu" - policy_type = "TargetTrackingScaling" - service_namespace = aws_appautoscaling_target.training_ecs_target.service_namespace - resource_id = aws_appautoscaling_target.training_ecs_target.resource_id + name = "training-application-scaling-policy-cpu" + policy_type = "TargetTrackingScaling" + service_namespace = aws_appautoscaling_target.training_ecs_target.service_namespace + resource_id = aws_appautoscaling_target.training_ecs_target.resource_id scalable_dimension = aws_appautoscaling_target.training_ecs_target.scalable_dimension target_tracking_scaling_policy_configuration { @@ -88,17 +103,17 @@ resource "aws_appautoscaling_policy" "training_ecs_target_cpu" { predefined_metric_type = "ECSServiceAverageCPUUtilization" } - target_value = 80 - scale_in_cooldown = 300 + target_value = 80 + scale_in_cooldown = 300 scale_out_cooldown = 300 } } resource "aws_appautoscaling_policy" "training_ecs_target_memory" { - name = "training-application-scaling-policy-memory" - policy_type = "TargetTrackingScaling" - service_namespace = aws_appautoscaling_target.training_ecs_target.service_namespace - resource_id = aws_appautoscaling_target.training_ecs_target.resource_id + name = "training-application-scaling-policy-memory" + policy_type = "TargetTrackingScaling" + service_namespace = aws_appautoscaling_target.training_ecs_target.service_namespace + resource_id = aws_appautoscaling_target.training_ecs_target.resource_id scalable_dimension = aws_appautoscaling_target.training_ecs_target.scalable_dimension target_tracking_scaling_policy_configuration { @@ -106,8 +121,8 @@ resource "aws_appautoscaling_policy" "training_ecs_target_memory" { predefined_metric_type = "ECSServiceAverageMemoryUtilization" } - target_value = 80 - scale_in_cooldown = 300 + target_value = 80 + scale_in_cooldown = 300 scale_out_cooldown = 300 } } @@ -121,17 +136,17 @@ resource "aws_security_group" "ecs_training_sg" { resource "aws_vpc_security_group_ingress_rule" "ecs_training_sg_ingress" { security_group_id = aws_security_group.ecs_training_sg.id - ip_protocol = "-1" + ip_protocol = "-1" # cidr_blocks = [aws_vpc.main.cidr_block] referenced_security_group_id = aws_security_group.ecs_django_sg.id -} +} resource "aws_vpc_security_group_egress_rule" "ecs_training_sg_egress" { security_group_id = aws_security_group.ecs_training_sg.id - ip_protocol = "-1" - cidr_ipv4 = "0.0.0.0/0" -} + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} # --- ECS Launch Template --- resource "aws_launch_template" "ecs_lt_training" { @@ -209,4 +224,4 @@ resource "aws_ecs_cluster_capacity_providers" "main" { base = 1 weight = 100 } -} \ No newline at end of file +} diff --git a/frontend/next.config.js b/frontend/next.config.js index 180c1257..2e1609f6 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -23,7 +23,10 @@ const nextConfig = { }, { source: "/api/training/:path*", - destination: "http://127.0.0.1:8000/api/:path*", + destination: + process.env.ENVIRONMENT === "production" + ? "http://alb-785155211.us-east-1.elb.amazonaws.com/api/:path*" // note, this url changes every time you destroy/apply Terraform + : "http://127.0.0.1:8000/api/:path*", }, ], };