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 를 준비합니다.
설정 과정의 개요
AWS Secrets Manager에 KEY_ENCRYPTION_KEY 등을 보관합니다.
Secret Name: QueryPie-Env-Variables (예시)
저장할 민감 정보: KEY_ENCRYPTION_KEY, DB_PASSWORD, REDIS_PASSWORD (일부 환경변수만 Secrets Manager 에 저장하여도 됩니다.)
Secret 에 접근하기 위한 Permission Policy 를 생성합니다.
앞의 단계에서 저장한 Secret 에 접근을 허용하는 Policy 를
querypie-secrets-access-policy라는 이름으로 저장합니다. 최소 권한 원칙을 적용하는 Policy 를 생성하며, 이를 위해 GetSecretValue 액션만 허용합니다.
Secret 에 접근하기 위한 IAM Role 을 설정합니다.
querypie-secrets-access-role이라는 IAM Role 을 생성합니다.Role 에서 권한을 부여할 신뢰받는 개체, 다시 말해 Trusted Entity 를 EC2 로 설정합니다.
Role 에서 접근할 대상을
querypie-secrets-access-policy로 설정합니다.
EC2 인스턴스에 IAM Role 을 부여합니다.
EC2 인스턴스에 IAM Role 을 부여하고, Secret 을 조회할 수 있는지 검증합니다.
docker container 를 실행하는 wrapper script 를 구현합니다.
docker-compose-with-secrets: 이 스크립트는 aws CLI 명령을 이용해 Secrets Manager 의 Secret 값을 읽어오고, 환경변수의 값으로 설정한 후, docker-compose 명령을 실행해 주는 기능을 수행합니다.
QueryPie 설치 과정을 진행합니다.
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-keyDB_PASSWORD =
example-db-passwordREDIS_PASSWORD =
example-redis-password
Encryption key 는 aws/secretsmanager 를 사용하도록 설정하였습니다.
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 부분은 편집하지 않고, 기본값을 그대로 둡니다.
Step 3: Configure rotation - optional
Configure automatic rotation 설정을 적용하지 않습니다. QueryPie 설치/운영을 위해 사용되는 이 환경변수 값들은 초기에 설정된 값을 계속 유지하여야 합니다.
Step 4: Review
마지막 단계에서는 앞에서 설정한 값의 현황을 확인합니다. 자세한 설명은 생략합니다.
생성한 Secret 의 ARN 을 확인합니다.
다음 단계에서 Permission 설정을 위해서, 생성한 Secret 의 ARN 을 확인하여야 합니다.
예시 과정에서 생성한 Secret 의 ARN 은 arn:aws:secretsmanager:ap-northeast-1:142605707876:secret:QueryPie-Env-Variables-EdYkBX 입니다.
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 항목에서, Read → GetSecretValue 를 선택합니다.
Resources 항목에서, Add ARNs 를 선택하고, 앞의 섹션에서 확인한 ARN, arn:aws:secretsmanager:ap-northeast-1:142605707876:secret:QueryPie-Env-Variables-EdYkBX 를 Resource ARN 의 값으로 입력합니다. Resource ARN 이외의 값인, Resource region, Resource secret 이 자동으로 채워집니다.
“Next” 버튼을 눌러, 다음 단계로 넘어갑니다.
Step 2: Review and create
Policy details 의 항목을 채웁니다.
Policy name :
querypie-secrets-access-policyDescription :
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
Trusted entity type 항목의 값으로, “AWS service - Allow AWS services like EC2, Lambda, or others to perform actions in this account.” 를 선택합니다.
Use case 항목의 값으로 “EC2” 를 선택합니다. 특정 EC2 Instance 가 운영자를 대신하여, AWS Service 를 호출하도록 권한을 부여하는 설정이기 때문입니다.
Next 버튼을 눌러, 다음 단계로 이동합니다.
Step 2: Add permissions
앞의 단계에서 생성한 querypie-secrets-access-policy 를 선택하여 추가합니다.
Step 3: Name, review, and create
Role name, description 을 적절히 입력합니다.
Role name:
querypie-secrets-access-roledescription:
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 textSecret 값에 접근할 수 있는 권한을 부여하지 않은 경우, 다음과 같은 오류 메시지를 만나게 됩니다.
[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 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 명령을 실행하는 시점에 환경변수로 정의되어 있는 값입니다.
Runetime 환경변수 (최우선 순위) - docker-compose 를 실행하는 시점에 환경변수로 정의된 값
docker-compose.yml 의 environment 섹션
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 를 필요로 합니다.
이 스크립트를 설치할 때 다음의 방법 중 하나를 적용하는 것을 권장합니다.
스크립트 이름을
docker-compose-with-secrets로 사용하면, 헷갈림을 줄이고 사용할 수 있습니다. PATH 로 참조되는 경로에 이 스크립트를 두기 위해,~/bin/에 스크립트를 설치합니다. 스크립트에 실행 권한을 줍니다.vi또는 다른 파일 편집 명령을 이용해, 아래의 스크립트를docker-compose-with-secrets라는 이름으로 저장합니다.install -m 755 -D docker-compose-with-secrets ~/bin/docker-compose-with-secrets
위와 마찬가지이나,
/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 의 환경변수로 사용하는 과정을, 실제 사례와 함께 상세하게 살펴보았습니다.