GitLab CI/CD에서 AWS Secrets Manager 시크릿 사용하기
GitLab CI/CD에서 AWS Secrets Manager 시크릿 사용하기
AWS Secrets Manager에 저장된 시크릿을 GitLab CI/CD 파이프라인에서 사용하는 방법을 설명하는 문서예요. IAM 역할 인증과 OpenID Connect 인증 두 가지 방식을 모두 지원해요.
간단한 문법부터 시크릿 버전, 계정 간 접근, 시크릿별 설정 재정의까지 다양한 활용법을 코드 예시와 함께 옆에서 설명해 주는 방식으로 정리했어요.
출처: 문서
본문
AWS Secrets Manager에 저장된 시크릿을 GitLab CI/CD 파이프라인에서 사용할 수 있어요.
이력
- GitLab 18.2에서
ci_aws_secrets_manager라는 기능 플래그와 함께 도입됨. 기본적으로 비활성화. - GitLab 18.3에서 일반 제공(Generally available).
전제 조건:
- AWS 계정에서 AWS Secrets Manager에 접근할 수 있어야 해요.
- 다음 방법 중 하나로 인증을 구성하세요.
- IAM Role: GitLab Runner 인스턴스에 할당된 IAM 역할을 사용.
- OpenID Connect: 임시 자격 증명을 가져오려면 AWS에서 OpenID Connect 구성.
- AWS 구성 정보를 제공하기 위해 프로젝트에 CI/CD 변수를 추가하세요.
AWS_REGION: 시크릿이 저장된 AWS 리전.AWS_ROLE_ARN: 가정할 AWS IAM 역할의 ARN (OpenID Connect 사용 시 필수).AWS_ROLE_SESSION_NAME: 선택 사항. 가정된 역할의 사용자 지정 세션 이름.
CI/CD 작업에서 AWS Secrets Manager 시크릿 사용하기
IAM 역할 인증 사용
aws_secrets_manager 키워드로 정의해 AWS Secrets Manager에 저장된 시크릿을 작업에서 사용할 수 있어요.
이 방법은 GitLab Runner 인스턴스에 할당된 IAM 역할을 사용해요. Kubernetes 실행기나 오토스케일링을 사용할 때는 IAM 역할이 여러분의 러너 매니저(runner manager)에 적용되어 있는지 확인하세요.
전제 조건:
- GitLab Runner 18.3 이상.
예를 들어:
variables:
AWS_REGION: us-east-1
database-migration:
secrets:
DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: app-secrets/database
field: 'password'
file: false
stage: deploy
script:
- echo "Running database migration..."
- mysql -h $DB_HOST -u $DB_USER -p$DATABASE_PASSWORD
- echo "Migration completed successfully."
OpenID Connect 인증 사용
보안을 강화하기 위해 OpenID Connect를 사용해 AWS에 인증하고 특정 IAM 역할을 가정할 수 있어요. 기본적으로 러너는 AWS_ID_TOKEN이라는 이름의 ID 토큰을 찾아요. 예를 들어:
variables:
AWS_REGION: us-east-1
AWS_ROLE_ARN: 'arn:aws:iam::123456789012:role/gitlab-secrets-role'
database-migration:
id_tokens:
AWS_ID_TOKEN:
aud: 'sts.amazonaws.com'
secrets:
DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: app-secrets/database
field: 'password'
file: false
stage: deploy
script:
- echo "Connecting to production database..."
- psql postgresql://$DB_USER:***@$DB_HOST:5432/$DB_NAME -c "SELECT version();"
- echo "Database connection successful."
token 옵션으로 사용자 지정 토큰을 지정할 수도 있어요. 예를 들어:
variables:
AWS_REGION: us-east-1
AWS_ROLE_ARN: 'arn:aws:iam::123456789012:role/gitlab-secrets-role'
database-migration:
id_tokens:
CUSTOM_AWS_TOKEN:
aud: 'sts.amazonaws.com'
secrets:
DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: app-secrets/database
field: 'password'
token: $CUSTOM_AWS_TOKEN
file: false
stage: deploy
script:
- echo "Connecting to production database with custom token..."
- psql postgresql://$DB_USER:***@$DB_HOST:5432/$DB_NAME -c "SELECT version();"
- echo "Database connection successful."
짧은 형식 문법
시크릿 ID를 문자열로 지정하는 간단한 문법을 사용할 수 있어요. 선택적으로 # 문자로 구분해 필드를 지정할 수 있어요. 예를 들어:
variables:
AWS_REGION: us-east-1
api-deployment:
secrets:
API_KEY:
aws_secrets_manager: 'app-secrets/api#api_key'
file: false
FULL_SECRET:
aws_secrets_manager: 'app-secrets/api'
file: false
stage: deploy
script:
- echo "Deploying API with specific field..."
- curl --header "Authorization: Bearer ***" https://api.example.com/deploy
- echo "Using full secret..."
- curl --header "Authorization: Bearer *** $FULL_SECRET | jq --raw-output '.api_key')" https://api.example.com/status
시크릿 버전 관리
AWS Secrets Manager는 시크릿의 여러 버전을 지원해요. version_id 또는 version_stage로 특정 버전을 지정할 수 있어요. 예를 들어:
variables:
AWS_REGION: us-east-1
production-deployment:
secrets:
DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: prod-app-secrets/database
field: 'password'
version_stage: 'AWSCURRENT'
file: false
STAGING_DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: prod-app-secrets/database
field: 'password'
version_id: '01234567-89ab-cdef-0123-456789abcdef'
file: false
stage: deploy
script:
- echo "Deploying to production with current secret version..."
- deploy-prod.sh --db-password $DATABASE_PASSWORD
- echo "Testing with specific secret version..."
- test-with-version.sh --db-password $STAGING_DATABASE_PASSWORD
계정 간 시크릿 접근
다른 AWS 계정에서 시크릿을 가져오려면 전체 ARN을 사용해야 해요. 예를 들어:
variables:
AWS_REGION: us-east-1
AWS_ROLE_ARN: 'arn:aws:iam::123456789012:role/cross-account-secrets-role'
cross-account-deployment:
id_tokens:
AWS_ID_TOKEN:
aud: 'sts.amazonaws.com'
secrets:
SHARED_API_KEY:
aws_secrets_manager:
secret_id: 'arn:aws:secretsmanager:us-east-1:987654321098:secret:shared-api-keys-AbCdEf'
field: 'production_key'
file: false
stage: deploy
script:
- echo "Accessing shared secret from another account..."
- curl --header "Authorization: Bearer ***" https://shared-api.example.com/deploy
시크릿별 구성 재정의
전역 AWS 설정을 시크릿 단위로 재정의할 수 있어요. 예를 들어:
variables:
AWS_REGION: us-east-1
AWS_ROLE_ARN: 'arn:aws:iam::123456789012:role/default-role'
multi-region-deployment:
id_tokens:
AWS_ID_TOKEN:
aud: 'sts.amazonaws.com'
EU_AWS_TOKEN:
aud: 'sts.amazonaws.com'
secrets:
EU_DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: eu-app-secrets/database
field: 'password'
region: 'eu-west-1'
role_arn: 'arn:aws:iam::123456789012:role/eu-deployment-role'
role_session_name: 'gitlab-eu-deployment'
token: $EU_AWS_TOKEN
file: false
US_DATABASE_PASSWORD:
aws_secrets_manager:
secret_id: us-app-secrets/database
field: 'password'
file: false
stage: deploy
script:
- echo "Deploying to EU region..."
- deploy-to-eu.sh --db-password $EU_DATABASE_PASSWORD
- echo "Deploying to US region..."
- deploy-to-us.sh --db-password $US_DATABASE_PASSWORD
이 예시들에서:
aud: 연합 자격 증명을 만들 때 사용된 오디언스와 일치해야 하는 오디언스.secret_id: AWS Secrets Manager의 시크릿 이름 또는 ARN. 다른 계정에서 시크릿을 가져오려면 ARN을 사용해야 해요.field: 가져올 JSON 시크릿의 특정 키. 지정하지 않으면 전체 시크릿이 가져와져요. 필드 접근은 평평한(flat) JSON 시크릿(최상위 키만)에서만 지원되며 문자열, 숫자, 불리언 값을 지원해요. 예를 들어:password:password필드에 접근.api_key:api_key필드에 접근.
token: 인증에 사용할 ID 토큰을 지정. 지정하지 않으면 러너는AWS_ID_TOKEN이라는 이름의 토큰을 찾아요.version_id: 시크릿의 특정 버전의 고유 식별자.version_id나version_stage를 지정하지 않으면 AWS Secrets Manager는AWSCURRENT버전을 반환해요.version_stage: 가져올 시크릿 버전의 스테이징 레이블(예:AWSCURRENT또는AWSPENDING). 같은 시크릿에version_id와version_stage를 둘 다 지정할 수는 없어요.region: 이 특정 시크릿에 대해 전역AWS_REGION을 재정의.role_arn: 이 특정 시크릿에 대해 전역AWS_ROLE_ARN을 재정의.role_session_name: 이 특정 시크릿에 대해 전역AWS_ROLE_SESSION_NAME을 재정의.
GitLab은 AWS Secrets Manager에서 시크릿을 가져와 값을 임시 파일에 저장해요. 이 파일의 경로는 파일 형식 CI/CD 변수와 유사하게 CI/CD 변수에 저장돼요.
문제 해결
AWS로 OIDC를 설정할 때 일반적인 문제는 AWS용 OIDC 문제 해결을 참고하세요.
오류: no EC2 IMDS role found
다음 두 조건이 모두 참일 때 이 오류가 발생할 수 있어요.
- CI/CD 작업이 IAM 역할 인증을 사용하도록 구성됨.
- 작업이 AWS EKS에서 호스팅되는 Kubernetes 실행기가 있는 러너에 의해 실행됨.
Resolving secrets
Resolving secret "MY_AWS_SECRET"...
Using "aws_secrets_manager" secret resolver...
ERROR: Job failed (system failure): resolving secrets: operation error Secrets Manager: GetSecretValue, get identity: get credentials: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, canceled, context deadline exceeded
Resolving secrets 단계는 러너 매니저가 처리해요. 이 단계는 EC2 IMDS에 캐시된 IAM 자격 증명에 접근해요. IAM 역할이 러너 매니저에 적용되지 않았다면 Resolving secrets 단계가 실패해요.
이 오류를 해결하려면 올바른 IAM 역할을 러너 매니저에 적용하세요.
러너 매니저가 생성하고 관리하는 러너 파드에 IAM 역할을 적용하는 것으로는 이 문제가 해결되지 않아요.
더 알아보기
AWS와의 OIDC 설정 방법은 AWS용 OIDC 문서에서 자세히 다루고 있어요. GitLab CI/CD에서 다른 시크릿 관리자를 사용하는 방법도 참고하려면 외부 시크릿 사용 문서를 함께 보시면 좋아요.