Secrets Manager 사용, 쓰지못한 이유

문한성·2023년 6월 19일
0

부트캠프

목록 보기
112/123
post-thumbnail

Secrets Manager 사용 이유

git actions yml 파일

name: Deploy to Amazon ECR

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
env:
  AWS_REGION: ap-northeast-2
  ECR_REPOSITORY: users
  ECS_SERVICE: race-user-sv
  ECS_CLUSTER: race-cluster
  ECS_TASK_DEFINITION: ./aws/task-definition.json
  CONTAINER_NAME: race-user
  
  
jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ github.sha }}
      working-directory: ./backend/user-backend
      run: |
        # Build a docker container and
        # push it to ECR so that it can
        # be deployed to ECS.
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . || true
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG || true
        echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
    
    - name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }}
  
    - name: Deploy Amazon ECS task definition
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.task-def.outputs.task-definition }}
        service: ${{ env.ECS_SERVICE }}
        cluster: ${{ env.ECS_CLUSTER }}
        wait-for-service-stability: true

위의 git actions yml을 이용해서 CI/CD 파이프라인을 구축하려면 아래의 task-definition 파일이 필요했다.
하지만 taskDefinition에 환경변수로 access key가 필요한 상황이였는데 json에 해당 값이 그대로 노출이 됐었다.
git action을 사용하기 위해서 해당 파일을 gitignore에 추가할 수도 없어서 Secrets Manager 사용이 필요했다.

{
    "taskDefinitionArn": "arn:aws:ecs:ap-northeast-2:648098991845:task-definition/race-user-task:11",
    "containerDefinitions": [
        {
            "name": "race-user",
            "image": "IMAGE_URL",
            "cpu": 0,
            "portMappings": [
                {
                    "name": "race-user-3000-tcp",
                    "containerPort": 3000,
                    "hostPort": 3000,
                    "protocol": "tcp",
                    "appProtocol": "http"
                }
            ],
            "essential": true,
            "environment": [
                {
                    "name": "AWS_ACCESS_KEY",
                    "value": "AWS_ACCESS_KEY_VALUE"
                },
                {
                    "name": "AWS_SECRET_ACCESS_KEY",
                    "value": "AWS_SECRET_ACCESS_KEY_VALUE"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "/ecs/race-user-task",
                    "awslogs-region": "ap-northeast-2",
                    "awslogs-stream-prefix": "ecs"
                }
            }
        }
    ],
    "family": "race-user-task",
    "taskRoleArn": "arn:aws:iam::648098991845:role/ecsTaskExecutionRole",
    "executionRoleArn": "arn:aws:iam::648098991845:role/ecsTaskExecutionRole",
    "networkMode": "awsvpc",
    "revision": 11,
    "volumes": [],
    "status": "ACTIVE",
    "requiresAttributes": [
        {
            "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
        },
        {
            "name": "ecs.capability.execution-role-awslogs"
        },
        {
            "name": "com.amazonaws.ecs.capability.ecr-auth"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
        },
        {
            "name": "com.amazonaws.ecs.capability.task-iam-role"
        },
        {
            "name": "ecs.capability.execution-role-ecr-pull"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
        },
        {
            "name": "ecs.capability.task-eni"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
        }
    ],
    "placementConstraints": [],
    "compatibilities": [
        "EC2",
        "FARGATE"
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "1024",
    "memory": "3072",
    "runtimePlatform": {
        "cpuArchitecture": "X86_64",
        "operatingSystemFamily": "LINUX"
    },
    "registeredAt": "2023-06-19T06:54:22.345Z",
    "registeredBy": "arn:aws:iam::648098991845:root",
    "tags": []
}

Secrets Manager 보안 암호 생성 및 적용

보안 암호 생성

ECS 테스크 정의 수정

  • 환경 변수의 값 유형을 ValueFrom으로 지정한다.
  • 값 부분에 (보안 암호 ARN):(보안 암호 키):: 으로 작성 해준다.

이제 테스크 정의 JSON에서 access key값의 노출을 방지할 수 있게 되었다.
Secrets Manager의 보안암호는 그밖에 DB의 username과 password값을 숨기거나 코드에 노출될 수 있는 중요한 정보들을 가리는데 사용할 수 있다.

Secrets Manager의 요금계산


위의 사진은 한달간 사용하면서 100만건의 요청을 처리했을 때의 예상 비용이다.
5.40 USD로 매우 저렴하게 사용가능 하다

Secrets Manager 사용 실패

Screts Manager, terraform, git action

Secrets Manager은 분명 간편하고 요금도 적게나오는 좋은 서비스라고 위에서 설명한대로 생각하고있다.
하지만 이걸 terraform과 git action을 같이 사용하는곳에서 문제를 직면했다.

resource "aws_ecs_task_definition" "app_task" {
  family                   = "tf-race-user-task" # Name your task
  container_definitions    = <<DEFINITION
  [
    {
      "name": "race-user-task",
      "image": "648098991845.dkr.ecr.ap-northeast-2.amazonaws.com/users:4775dbd4b152757ad366d4dc23f57b00904eabdd",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "hostPort": 3000
        }
      ],
      "cpu": 0,
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-region": "ap-northeast-2",
          "awslogs-stream-prefix": "app-logstream",
          "awslogs-group": "${aws_cloudwatch_log_group.my_ecs_service_log_group.name}"
        }
      },
      "environment": [
        {
          "name": "AWS_ACCESS_KEY_ID",
          "value": "${var.AWS_ACCESS_KEY}"
        },
        {
          "name": "AWS_SECRET_ACCESS_KEY",
          "value": "${var.AWS_SECRET_ACCESS_KEY}"
        }
      ]
    }
  ]
  DEFINITION
  requires_compatibilities = ["FARGATE"] # use Fargate as the launch type
  network_mode             = "awsvpc"    # add the AWS VPN network mode as this is required for Fargate
  memory                   = 3072        # Specify the memory the container requires
  cpu                      = 1024        # Specify the CPU the container requires
  execution_role_arn       = aws_iam_role.ecsTaskExecutionRole.arn
}

위의 코드는 terraform 코드중에 task definition부분이다.
environment 부분을 보면 value라고 되어있는곳을 Secrets manager를 사용하기 위해서 valueFrom이라고 변경해서 terraform을 실행시키면 환경변수가 테스크 정의에서 없어진채로 배포가 된다.

terraform 공식문서chatGPT등 여러 방면으로 검색해 보았지만 해당 valueFrom을 사용하는 부분은 지원해주지 않는것 같았다.

해서 결국 목적은 코드에 access key 값을 숨기기 위함이니 git action yml 부분에서 환경변수를 숨겨서 추가해기로 결정했다.

해결 방법

  • terraform 코드는 위의 코드 그대로 사용한다.
  • git action이 읽을 yml을 수정한다.
- name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }}
        environment-variables: |
            AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}
            AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}

environment-variables 부분을 추가해서 테스크 정의 json 파일에 환경변수를 github secret을 활용하여 숨겨서 추가해준다.

  • test-difinition.json 파일을 수정한다.

    위의 캡쳐처럼 환경변수부분을 아예 비워준다.
profile
기록하고 공유하려고 노력하는 DevOps 엔지니어

0개의 댓글