AWS Secrets Manager 활용하여 QueryPie 설치하기

AWS Secrets Manager 활용하여 QueryPie 설치하기

소개

QueryPie 는 KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD 등 값을 환경변수에서 정의하여 Docker Container 를 실행할 때 사용합니다. 이러한 정보는 민감 정보로 분류할 수 있으며, 이 값이 외부에 유출되지 않도록 주의하여야 합니다.

기본 설치 가이드의 방식을 따르게 되면, KEY_ENCRYPTION_KEY 등 환경변수를 QueryPie 가 설치된 서버 내 compose-env 라는 환경변수 설정파일에 보관합니다. QueryPie 가 설치된 서버 내의 계정과 설치에 사용된 환경변수 설정파일은 안전하게 보호할 필요가 있으며, 여러 사내 이용자가 이 서버 내부의 계정에 접근하는 것을 허용하지 않아야 합니다.

이 설치 가이드에서는, KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD 등 값을 환경변수 설정파일에 두지 않고, 더욱 안전하게 보관하기 위하여, AWS Secrets Manager 에 보관하여 사용하는 방법을 안내합니다.

KEY_ENCRYPTION_KEY 이란?

QueryPie 는 Data Encryption Key 를 사용하여, QueryPie Meta DB 에 저장하는 DB_PASSWORD 같은 정보를 암호화합니다. 이 Data Encryption Key 는 QueryPie 를 설치하는 시점에 Random value 로 생성되며, KEY_ENCRYPTION_KEY 를 이용해 한번 더 암호화되어 저장됩니다. 이와 같은 이중의 암호화 방식을 통하여, 대상 시스템에 접근하기 위한 Credential 등 민감 정보를 안전하게 보관하고 있습니다.

KEY_ENCRYPTION_KEY 를 알아내지 못하면, QueryPie Meta DB 에 저장된 Data Encryption Key 를 복호화하지 못합니다. QueryPie 를 설치할 때 사용한 KEY_ENCRYPTION_KEY 는 안전하게 보관하시기 바랍니다.

KEY_ENCRYPTION_KEY 를 이용해, QueryPie Meta DB 에서 Data Encryption Key 를 복호화하는 구체적인 방법은 비공개이며, 간단한 방법으로 복호화할 수 없습니다. 파트너사, 고객사에서 Data Encryption Key 가 어떠한 암호화 기술을 적용하여 안전하게 보관되는지 저희 제조사에 질의하는 경우, Data Encryption Key 가 AES 알고리즘을 이용하여 암호화되어 있다는 사실을 파트너사, 고객사에 알려드리고 있습니다.

준비 사항

  • QueryPie 를 설치할 AWS 계정과 EC2 Instance 를 준비합니다.

설정 과정의 개요

  1. AWS Secrets Manager에 KEY_ENCRYPTION_KEY 등을 보관합니다.

    1. Secret Name: QueryPie-Env-Variables (예시)

    2. 저장할 민감 정보: KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD (일부 환경변수만 Secrets Manager 에 저장하여도 됩니다.)

  2. Secret 에 접근하기 위한 Permission Policy 를 생성합니다.

    1. 앞의 단계에서 저장한 Secret 에 접근을 허용하는 Policy 를 querypie-secrets-access-policy 라는 이름으로 저장합니다. 최소 권한 원칙을 적용하는 Policy 를 생성하며, 이를 위해 GetSecretValue 액션만 허용합니다.

  3. Secret 에 접근하기 위한 IAM Role 을 설정합니다.

    1. querypie-secrets-access-role 이라는 IAM Role 을 생성합니다.

    2. Role 에서 권한을 부여할 신뢰받는 개체, 다시 말해 Trusted Entity 를 EC2 로 설정합니다.

    3. Role 에서 접근할 대상을 querypie-secrets-access-policy 로 설정합니다.

  4. EC2 인스턴스에 IAM Role 을 부여합니다.

    1. EC2 인스턴스에 IAM Role 을 부여하고, Secret 을 조회할 수 있는지 검증합니다.

  5. docker container 를 실행하는 wrapper script 를 구현합니다.

    1. docker-compose-with-secrets : 이 스크립트는 aws CLI 명령을 이용해 Secrets Manager 의 Secret 값을 읽어오고, 환경변수의 값으로 설정한 후, docker-compose 명령을 실행해 주는 기능을 수행합니다.

  6. QueryPie 설치 과정을 진행합니다.

    1. docker-compose 대신 docker-compose-with-secrets 스크립트를 이용합니다.

 

위의 절차를 각 단계별로 아래에서 상세히 살펴보겠습니다.

이 문서에서 제시하는 환경변수의 값, Secrets Manager 설정값은 예시입니다. 고객사의 보안정책에 따라, 다른 값을 사용하여 적용하시기 바랍니다.

AWS Secrets Manager 에 KEY_ENCRYPTION_KEY 등을 보관합니다.

AWS Secrets Manager 에 QueryPie 설치, 운영에 사용되는 환경변수 가운데, 일부를 저장합니다. 이 예시에서는, KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD, 3개 값을 Secrets Manager 에 저장합니다. 고객사의 보안 정책에 따라, 3개 환경변수 가운데 일부만 Secrets Manager 에 저장하여도 됩니다.

Step 1: Choose secret type

Key/value pairs 에 다음과 같이 저장합니다.

  • KEY_ENCRYPTION_KEY = example-key-encryption-key

  • DB_PASSWORD = example-db-password

  • REDIS_PASSWORD = example-redis-password

Encryption key 는 aws/secretsmanager 를 사용하도록 설정하였습니다.

secrets-manager-step1.png
Step 1: Choose secret type

Step 2: Configure secret

“Secret name” and “description” 을 다음과 같이 설정합니다. 다른 문구를 사용하여도 무방합니다. 이 비밀값이 QueryPie 설치/운영을 위해 사용하는 값이라는 것을 쉽게 알 수 있도록, 이름과 설명을 적어주세요.

  • Secret name : QueryPie-Env-Variables

  • Description : Sensitive environment variables to run the QueryPie docker container

Resource permissions 부분은 편집하지 않고, 기본값을 그대로 둡니다.

secrets-manager-step2.png

Step 3: Configure rotation - optional

Configure automatic rotation 설정을 적용하지 않습니다. QueryPie 설치/운영을 위해 사용되는 이 환경변수 값들은 초기에 설정된 값을 계속 유지하여야 합니다.

secrets-manager-step3.png

Step 4: Review

마지막 단계에서는 앞에서 설정한 값의 현황을 확인합니다. 자세한 설명은 생략합니다.

secrets-manager-step4-1.png
secrets-manager-step4-2.png

생성한 Secret 의 ARN 을 확인합니다.

다음 단계에서 Permission 설정을 위해서, 생성한 Secret 의 ARN 을 확인하여야 합니다.

예시 과정에서 생성한 Secret 의 ARN 은 arn:aws:secretsmanager:ap-northeast-1:142605707876:secret:QueryPie-Env-Variables-EdYkBX 입니다.

secret-arn.png

Secret 에 접근하기 위한 Permission Policy 를 생성합니다.

AWS IAM 웹콘솔에서 앞에서 생성한 Secret 에 접근하기 위한 Permission Policy 를 생성하는 방법을 설명합니다. 특정 Secret 만 접근 가능한, 최소 권한을 가진 Permission Policy 를 생성합니다.

먼저, IAM → Access Management → Policies 메뉴로 이동합니다. “Create policy” 버튼을 눌러, Policy 를 생성하기 시작합니다.

Step 1: Specify permissions

Select a service 항목에서, Secrets Manager 를 선택합니다.

Actions allowed 항목에서, ReadGetSecretValue 를 선택합니다.

Resources 항목에서, Add ARNs 를 선택하고, 앞의 섹션에서 확인한 ARN, arn:aws:secretsmanager:ap-northeast-1:142605707876:secret:QueryPie-Env-Variables-EdYkBX 를 Resource ARN 의 값으로 입력합니다. Resource ARN 이외의 값인, Resource region, Resource secret 이 자동으로 채워집니다.

policy-step1.png

“Next” 버튼을 눌러, 다음 단계로 넘어갑니다.

Step 2: Review and create

Policy details 의 항목을 채웁니다.

  • Policy name : querypie-secrets-access-policy

  • Description : Allows reading secret values for QueryPie environment variables

“Create policy” 버튼을 눌러, Policy 를 생성합니다.

Secret 에 접근하기 위한 IAM Role 을 설정합니다.

AWS IAM 웹콘솔에서 Role 을 생성하는 방법을 설명합니다. 앞의 단계에서 생성한 Permission Policy 를 활용해 Role 을 생성합니다.

먼저, IAM → Access Management → Roles 메뉴로 이동합니다. “Create Role” 버튼을 눌러, Role 을 생성하기 시작합니다.

Step 1: Select trusted entity

  1. Trusted entity type 항목의 값으로, “AWS service - Allow AWS services like EC2, Lambda, or others to perform actions in this account.” 를 선택합니다.

  2. Use case 항목의 값으로 “EC2” 를 선택합니다. 특정 EC2 Instance 가 운영자를 대신하여, AWS Service 를 호출하도록 권한을 부여하는 설정이기 때문입니다.

  3. Next 버튼을 눌러, 다음 단계로 이동합니다.

role-step1.png

Step 2: Add permissions

앞의 단계에서 생성한 querypie-secrets-access-policy 를 선택하여 추가합니다.

role-step2.png

Step 3: Name, review, and create

Role name, description 을 적절히 입력합니다.

  • Role name: querypie-secrets-access-role

  • description: IAM role for EC2 instances to securely access QueryPie environment secrets in AWS Secrets Manager

 

이후 “Create” 버튼을 눌러, Role 을 생성합니다.

 

EC2 인스턴스에 IAM Role 을 부여합니다.

QueryPie 가 설치된 EC2 Instance 의 linux shell 에서 다음의 명령을 실행하여, Secret 값을 접근할 수 있는지 확인합니다. 이 문서의 예시에서는 <secret-id> 에는 QueryPie-Env-Variables 를 사용하며, 이 값은 이용자의 설정에 따라 달라집니다. “AWS Secrets Manager 에 KEY_ENCRYPTION_KEY 등을 보관합니다” 섹션에서 저장한 Secret name 을 사용하여야 합니다.

aws secretsmanager get-secret-value \ --secret-id <secret-id> \ --query SecretString \ --output text

Secret 값에 접근할 수 있는 권한을 부여하지 않은 경우, 다음과 같은 오류 메시지를 만나게 됩니다.

[ec2-user@ip-172-31-43-95 10.2.5]$ aws secretsmanager get-secret-value \ --secret-id QueryPie-Env-Variables \ --query SecretString \ --output text An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::142605707876:assumed-role/AmazonSSMRoleForInstancesQuickSetup/i-0abd8e54fa1a88211 is not authorized to perform: secretsmanager:GetSecretValue on resource: QueryPie-Env-Variables because no identity-based policy allows the secretsmanager:GetSecretValue action [ec2-user@ip-172-31-43-95 10.2.5]$

AWS EC2 Web Console 에서, Actions → Security → Modify IAM Role 메뉴를 선택하여, EC2 Instance 의 IAM Role 을 변경합니다.

ec2-modify-iam.png
EC2 Instance → Actions → Security → Modify IAM Role

 

EC2 Instance 의 IAM Role 을 기본 설정값이 아닌, querypie-secrets-access-role 을 지정합니다. Role 을 저장한 시점에서 얼마 지나지 않은 경우, 목록에서 querypie-secrets-access-role 가 보이지 않을 수 있습니다. 목록에서 Role 이 보이지 않는 경우, querypie-secrets-access-role 를 입력칸에 직접 입력하는 방법을 사용하면 좋습니다.

IAM Role 을 변경할 때, EC2 Instance 를 Stop 하거나, Restart 하지 않고, Running 상태에서 변경하여도 됩니다. “Update IAM Role” 버튼을 누른 후, 거의 즉시, 효과가 발생합니다.

Linux shell 에서 다음의 명령을 실행하여, Secret 값을 접근할 수 있는지 확인합니다. 아래와 같이 Secret 값이 나타나면, IAM 권한 설정이 올바르게 완료된 것입니다.

[ec2-user@ip-172-31-43-95 ~]$ aws secretsmanager get-secret-value \ --secret-id QueryPie-Env-Variables \ --query SecretString \ --output text {"KEY_ENCRYPTION_KEY":"example-key-encryption-key","DB_PASSWORD":"example-db-password","REDIS_PASSWORD":"example-redis-password"} [ec2-user@ip-172-31-43-95 ~]$

--secret-id 파라미터의 값은 ARN 에 표시되는 QueryPie-Env-Variables-EdYkBX 가 아니고, 이용자가 입력한 Secret Name 인 QueryPie-Env-Variables 라는 것에 유의하여 주세요.

docker container 를 실행하는 wrapper script 를 구현합니다.

docker-compose 는 --env-file, -e 옵션 등을 통해 Container 의 환경변수 값을 지정할 수 있습니다. 이 가운데, 우선순위가 높은 것은, docker-compose 명령을 실행하는 시점에 환경변수로 정의되어 있는 값입니다.

  1. Runetime 환경변수 (최우선 순위) - docker-compose 를 실행하는 시점에 환경변수로 정의된 값

  2. docker-compose.yml 의 environment 섹션

  3. docker-compose.yml 의 env_file

이러한 docker-compose 의 특성을 활용하여, docker-compose 명령을 감싸는 wrapper script 를 구현하겠습니다.

docker-compose-with-secrets

이 스크립트는 aws CLI 명령을 이용해 Secrets Manager 의 Secret 값을 읽어오고, 환경변수의 값으로 설정한 후, docker-compose 명령을 실행해 주는 기능을 수행합니다. 실행하는 시점에 환경변수로 정의된 값, Runtime Environment Variable 은 우선순위가 가장 높으며, compose-env 파일에 설정된 값을 대체하게 됩니다.

이 스크립트는 aws CLI 명령을 필요로 합니다. JSON 문자열을 처리하기 위해, jq 를 필요로 합니다.

이 스크립트를 설치할 때 다음의 방법 중 하나를 적용하는 것을 권장합니다.

  1. 스크립트 이름을 docker-compose-with-secrets 로 사용하면, 헷갈림을 줄이고 사용할 수 있습니다. PATH 로 참조되는 경로에 이 스크립트를 두기 위해, ~/bin/ 에 스크립트를 설치합니다. 스크립트에 실행 권한을 줍니다.

    • vi 또는 다른 파일 편집 명령을 이용해, 아래의 스크립트를 docker-compose-with-secrets 라는 이름으로 저장합니다.

    • install -m 755 -D docker-compose-with-secrets ~/bin/docker-compose-with-secrets

  2. 위와 마찬가지이나, /usr/local/bin/ 에 스크립트를 설치합니다. 이 경우는 sudo 권한이 필요합니다.

    • vi 또는 다른 파일 편집 명령을 이용해, 아래의 스크립트를 docker-compose-with-secrets 라는 이름으로 저장합니다.

    • sudo install -m 755 docker-compose-with-secrets /usr/local/bin/docker-compose-with-secrets

 

#!/usr/bin/env bash # Retrieve Secret values from AWS Secrets Manager # TODO: Modify <secret-id> to your secret name. secrets=$( aws secretsmanager get-secret-value \ --secret-id <secret-id> \ --query SecretString \ --output text ) # Extract individual environment variables from JSON KEY_ENCRYPTION_KEY=$(echo ${secrets} | jq -r .KEY_ENCRYPTION_KEY) KEK=$(echo ${secrets} | jq -r .KEY_ENCRYPTION_KEY) DB_PASSWORD=$(echo ${secrets} | jq -r .DB_PASSWORD) REDIS_PASSWORD=$(echo ${secrets} | jq -r .REDIS_PASSWORD) export KEY_ENCRYPTION_KEY KEK DB_PASSWORD REDIS_PASSWORD set -o xtrace exec docker-compose "$@"

QueryPie 설치 과정을 진행합니다.

만일, 이전에 QueryPie 설치 과정을 진행하였다면, KEY_ENCRYPTION_KEY 는 설치 이후에 변경할 수 없다는 것에 주의하여 주세요.

기존 설치에 적용하였던 KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD 값을, AWS Secrets Manager 에 그대로 적용하는 것을 권장합니다. 이 값을 변경하는 경우에 필요한 변경사항은, 이 문서에서 다루지 않습니다.

기존 설치를 삭제하고, 새로 설치하는 경우, 환경변수 값을 다른 값으로 설정할 수 있습니다. 기존 설치 내용을 삭제하는 과정은 다음과 같습니다.

  • docker container 를 모두 종료하고, 삭제합니다.

  • docker volume prune 명령으로 volume 을 모두 삭제합니다.

  • mysql 을 같은 Linux machine 에서 실행하였다면, ~/querypie/{version}/mysql 디렉토리를 삭제합니다.

이미 QueryPie 설치 매뉴얼의 과정 가운데, compose-env 파일을 설정하는 단계부터는, 이 문서의 설치 과정을 참조하여 진행합니다.

주의할 것은, docker-compose 라는 명령을 사용하지 않고, 이전 단계에서 구현한 docker-compose-with-secrets 라는 wrapper script 를 호출하여, Container 를 실행하여야 한다는 것입니다. 이를 통해, Secrets Manager 에 저장된 Secret 을 참조하여, Docker Container 에 적절한 환경변수를 지정할 수 있게 됩니다.

compose-env 파일을 설정하기 단계 이후를 요약하면 다음과 같습니다.

  • compose-env 파일을 설정하기

    • 아래에 설명된 “compose-env 설정 과정의 유의사항” 섹션을 참고하세요.

  • MySQL / Redis 를 실행하기

    • docker-compose-with-secrets --env-file compose-env --profile database up -d

  • Tools Container 를 실행하기

    • Tools 실행

      • docker-compose-with-secrets --env-file compose-env --profile tools up -d

    • Migration 실행

      • docker exec -it querypie-tools-1 /app/script/migrate.sh runall

    • License 실행

      • curl -XPOST 127.0.0.1:8050/license/upload -F file=@license.crt

    • Tools 종료

      • docker-compose-with-secrets --env-file compose-env --profile tools down

  • QueryPie Container 실행하기

    • docker-compose-with-secrets --env-file compose-env --profile querypie up -d

compose-env 설정 과정의 유의사항

위와 같이 3개 환경변수를 정의하는 경우, compose-env 파일에서 해당 환경변수 값을 Comment 처리합니다. compose-env 에서 해당 환경변수를 막지 않은 경우, docker-compose wrapper 를 통하지 않고 container 를 직접 실행하는 경우, Container 에 엉뚱한 값이 환경변수로 적용될 가능성이 있습니다.

# ..... ## Secret key used to encrypt sensitive information, such as database connection strings and SSH private keys. ## This key can be any string but is immutable once set. # KEY_ENCRYPTION_KEY= # ..... # DB_PASSWORD= # ..... # REDIS_PASSWORD=

 

주의할 점

AWS EC2 Instance 는 하나의 Role 을 가질 수 있습니다. 둘 이상의 Role 을 지정하지 못합니다.

이 문서에서는 querypie-secrets-access-role 라는 이름의 Role 을 정의하고, 하나의 Permission Policy 를 연결하였습니다. 그러나, Cloud Provider 기능을 활용하는 경우, 추가적인 Permission Policy 를 Role 에 추가하여야 합니다.

AWS EC2 Instance 는 하나의 Role 만을 가질 수 있습니다. 이에 따라, 이 Role 을 EC2 Instance 에게 1:1 로 할당하는 방식으로 이름 짓는 것이 일반적으로 더 적절합니다. EC2 Instance 가 2개 이상의 Role 을 가질 수 있다는 것을 전제로 이름 짓지 않는 것이 좋습니다.

 

마무리

AWS Secrets Manager 에 KEY_ENCRYPTION_KEY 등 민감한 설정값을 저장해 두고, Runtime 에 이 값을 참조하여 사용하는 방법을 살펴보았습니다. AWS IAM 의 Permission Policy, Role 을 생성하고, 이 Role 을 EC2 Instance 에 부여하는 방법으로, EC2 Instance 의 Linux shell 에서, 이 값을 참조할 수 있습니다.

여기에 더해, docker-compose-with-secrets 라는 wrapper script 를 도입하여, aws CLI 명령으로 읽어온 Secret 값을 Container 의 환경변수로 사용하는 과정을, 실제 사례와 함께 상세하게 살펴보았습니다.