ECS 작업에 S3 권한 부여하기

hyuckhoon.ko·2021년 1월 18일
0

What I learned in first year

목록 보기
61/146

1. s3-write-policy.json.tpl 파일 생성

장고 스토리지 라이브러리를 사용한다. s3 버킷으로 파일 업로더를 가능하게 해주는 라이브러리다.

출처: https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#iam-policy

  • s3-write-policy.json.tpl
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "${bucket_arn}/*",
                "${bucket_arn}"
            ]
        }
    ]
}

deploy > templates > ecs 디렉토리 내부에
s3-write-policy.json.tpl파일을 생성한다.



2. ecs.tf 파일 수정

아래의 내용을 추가한다.

  • ecs의 s3 쓰기 권한 관련 정책을 생성한다.
  • 위에서 정의한 s3 쓰기 권한 정책을 갖는 aws iam 정책을 생성한다.
    첫번재에서는 순수하게 정책을 생성한 것이고(단순 정책 생성),
    두번째에서 위 정책을 적용한 정책을 정의한 것이다.)
  • 세 번째는 실제 task가 실행될 때, 해당 role과 정책을 가져와서 권한을 부여한다.
data "template_file" "ecs_s3_wirte_policy" {
  template = file(".templates/ecs/s3-write-policy.json.tpl")
  
  vars = {
    bucket_arn = aws_s3_bucket.app_public_files.arn
  }
}

resource "aws_iam_policy" "ecs_s3_access" {
  name = "${local.prefix}-AppS3AccessPolicy"
  path = "/"
  description = "Allow access to the recipe app S3 bucket"
  
  policy = data.template_file.ecs_s3_write_policy.rendered    
}

resource "aws_iam_role_policy_attachment" "ecs_s3_access" {
  role = aws_iam_role.app_iam_role.name
  policy_arn = aws_iam_policy.ecs_s3_access.arn 
}




resource "aws_ecs_cluster" "main" {
  name = "${local.prefix}-cluster"

  tags = local.common_tags
}

resource "aws_iam_policy" "task_execution_role_policy" {
  name        = "${local.prefix}-task-exec-role-policy"
  path        = "/"
  description = "Allow retrieving of images and adding logs"
  policy      = file("./templates/ecs/task-exec-role.json")
}

resource "aws_iam_role" "task_execution_role" {
  name               = "${local.prefix}-task-exec-role"
  assume_role_policy = file("./templates/ecs/assume-role-policy.json")

  tags = local.common_tags
}

resource "aws_iam_role_policy_attachment" "task_execution_role" {
  role       = aws_iam_role.task_execution_role.name
  policy_arn = aws_iam_policy.task_execution_role_policy.arn
}

resource "aws_iam_role" "app_iam_role" {
  name               = "${local.prefix}-api-task"
  assume_role_policy = file("./templates/ecs/assume-role-policy.json")

  tags = local.common_tags
}

resource "aws_cloudwatch_log_group" "ecs_task_logs" {
  name = "${local.prefix}-api"

  tags = local.common_tags
}

data "template_file" "api_container_definitions" {
  template = file("./templates/ecs/container-definitions.json.tpl")

  vars = {
    app_image         = var.ecr_image_api
    proxy_image       = var.ecr_image_proxy
    django_secret_key = var.django_secret_key
    db_host           = aws_db_instance.main.address
    db_name           = aws_db_instance.main.name
    db_user           = aws_db_instance.main.username
    db_pass           = aws_db_instance.main.password
    log_group_name    = aws_cloudwatch_log_group.ecs_task_logs.name
    log_group_region  = data.aws_region.current.name
    allowed_hosts     = aws_lb.api.dns_name
    s3_storage_bucket_name = aws_s3_bucket.app_public_files.bucket
    s3_storage_bucket_region = data.aws_region.current.name
  }
}

resource "aws_ecs_task_definition" "api" {
  family                   = "${local.prefix}-api"
  container_definitions    = data.template_file.api_container_definitions.rendered
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = 256
  memory                   = 512
  execution_role_arn       = aws_iam_role.task_execution_role.arn
  task_role_arn            = aws_iam_role.app_iam_role.arn

  volume {
    name = "static"
  }
  tags = local.common_tags
}

resource "aws_security_group" "ecs_service" {
  description = "Access for the ECS Service"
  name        = "${local.prefix}-ecs-service"
  vpc_id      = aws_vpc.main.id

  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port = 5432
    to_port   = 5432
    protocol  = "tcp"
    cidr_blocks = [
      aws_subnet.private_a.cidr_block,
      aws_subnet.private_b.cidr_block
    ]
  }

  ingress {
    from_port = 8000
    to_port   = 8000
    protocol  = "tcp"
    security_groups = [
      aws_security_group.lb.id
    ]
  }

  tags = local.common_tags
}

resource "aws_ecs_service" "api" {
  name            = "${local.prefix}-api"
  cluster         = aws_ecs_cluster.main.name
  task_definition = aws_ecs_task_definition.api.family
  desired_count   = 1
  launch_type     = "FARGATE"

  network_configuration {
    subnets = [
      aws_subnet.private_a.id,
      aws_subnet.private_b.id,
    ]
    security_groups = [aws_security_group.ecs_service.id]
  }
  load_balancer {
    target_group_arn = aws_lb_target_group.api.arn
    container_name   = "proxy"
    container_port   = 8000
  }
}

data "template_file" "ecs_s3_wirte_policy" {
  template = file(".templates/ecs/s3-write-policy.json.tpl")
  
  vars = {
    bucket_arn = aws_s3_bucket.app_public_files.arn
  }
}

resource "aws_iam_policy" "ecs_s3_access" {
  name = "${local.prefix}-AppS3AccessPolicy"
  path = "/"
  description = "Allow access to the recipe app S3 bucket"
  
  policy = data.template_file.ecs_s3_write_policy.rendered    
}

resource "aws_iam_role_policy_attachment" "ecs_s3_access" {
  role = aws_iam_role.app_iam_role.name
  policy_arn = aws_iam_policy.ecs_s3_access.arn 
}

0개의 댓글