도입: OIDC로 장기 시크릿을 없애는 목표와 한 줄 답
GitHub Actions에서 AWS, Azure, GCP 같은 클라우드에 배포할 때 Access Key나 Service Account 키를 Repository Secret에 저장하는 방식은 보안 위험이 크다. 키가 유출되면 공격자가 클라우드 리소스를 자유롭게 조작할 수 있고, 키 교체·감사 추적이 어렵다.
OIDC(OpenID Connect)를 사용하면 장기 시크릿 없이 GitHub Actions 워크플로우가 임시 토큰을 받아 클라우드 인증을 수행한다. 클라우드 제공자가 GitHub의 신원 증명을 검증하고 단기 자격증명을 발급하므로, 저장된 키를 관리할 필요가 없다.
GitHub Actions OIDC로 장기 클라우드 시크릿을 없애는 방법 핵심 항목
1. 클라우드 제공자에서 OIDC 신뢰 관계 설정
준비
- 클라우드 계정과 필요한 권한 확인
- AWS: IAM 역할 생성·수정 권한
- Azure: App Registration 생성·Federated Credential 추가 권한
- GCP: Workload Identity Pool·Provider 생성 권한
- GitHub repository 이름, branch/tag/environment 같은 조건 목록 작성
단계
-
클라우드 콘솔에서 Identity Provider 등록
- AWS: IAM → Identity providers → Add provider → OpenID Connect
- Provider URL:
https://token.actions.githubusercontent.com - Audience:
sts.amazonaws.com
- Provider URL:
- Azure: App registrations → Certificates & secrets → Federated credentials → Add credential
- Issuer:
https://token.actions.githubusercontent.com - Subject identifier:
repo:organization/repository:ref:refs/heads/main
- Issuer:
- GCP: IAM & Admin → Workload Identity Pools → Create Pool
- Provider: OIDC, Issuer URL
https://token.actions.githubusercontent.com - Attribute mapping:
google.subject=assertion.sub,attribute.repository=assertion.repository
- Provider: OIDC, Issuer URL
- AWS: IAM → Identity providers → Add provider → OpenID Connect
-
역할 또는 서비스 계정 생성 및 신뢰 정책 작성
- AWS 예시 Trust Policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"Federated": "arn:aws:iam::<account-id>:oidc-provider/token.actions.githubusercontent.com"}, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": {"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"}, "StringLike": {"token.actions.githubusercontent.com:sub": "repo:<org>/<repo>:ref:refs/heads/main"} } } ] } - Azure: Federated credential에서 Subject identifier를
repo:<org>/<repo>:environment:<env-name>형식으로 지정 - GCP: Workload Identity Pool에 Service Account 바인딩 추가,
principalSet://iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/<pool-id>/attribute.repository/<org>/<repo>
- AWS 예시 Trust Policy:
-
역할에 필요한 최소 권한 부여
- 배포 대상 리소스에만 접근 가능하도록 정책 범위 제한
주의점
- Subject identifier 조건을 너무 느슨하게 설정하면 다른 repository나 branch에서 토큰을 받을 수 있다.
repo:<org>/<repo>:ref:refs/heads/<branch>또는environment:<env-name>같은 세밀한 조건 추가 필요 - AWS의 경우
audclaim이sts.amazonaws.com인지 반드시 확인 - Azure는 Subject identifier 형식이 정확히 일치해야 하므로 오타 주의
완료 기준
- 클라우드 콘솔에서 Identity Provider와 역할이 등록되고, Trust Policy에 GitHub OIDC issuer URL과 repository 조건이 명시되어 있음
- 역할 ARN(AWS), Application(client) ID(Azure), Workload Identity Provider 리소스 이름(GCP)을 기록
2. GitHub Actions 워크플로우에 OIDC 권한 및 인증 단계 추가
준비
- 클라우드 제공자별 공식 GitHub Action 확인
- AWS:
aws-actions/configure-aws-credentials - Azure:
azure/login - GCP:
google-github-actions/auth
- AWS:
- 워크플로우 파일(
.github/workflows/*.yml) 편집 권한
단계
-
워크플로우 상단에
permissions블록 추가permissions: id-token: write contents: readid-token: write는 OIDC 토큰 요청에 필수
-
인증 단계 추가
- AWS:
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::<account-id>:role/<role-name> aws-region: us-east-1 - Azure:
(client-id, tenant-id, subscription-id는 민감하지 않은 식별자이므로 Secret 대신 변수로 관리 가능)- name: Azure login uses: azure/login@v1 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - GCP:
- name: Authenticate to Google Cloud uses: google-github-actions/auth@v2 with: workload_identity_provider: projects/<project-number>/locations/global/workloadIdentityPools/<pool-id>/providers/<provider-id> service_account: <service-account-email>
- AWS:
-
이후 단계에서 클라우드 CLI(aws, az, gcloud) 또는 SDK 사용
- 인증 단계가 완료되면 환경 변수나 credential helper가 자동 설정됨
주의점
permissions블록이 없으면id-token: write권한이 부여되지 않아 OIDC 토큰 요청 실패- 역할 ARN, Workload Identity Provider 리소스 이름 등을 정확히 입력
- Azure는
client-id,tenant-id,subscription-id를 모두 제공해야 함
완료 기준
- 워크플로우 실행 로그에서 인증 단계가 성공하고, 이후 클라우드 명령어가 권한 오류 없이 실행됨
- Repository Secret에 장기 Access Key나 Service Account 키가 남아 있지 않음
3. 기존 장기 시크릿 제거 및 권한 검증
준비
- 모든 워크플로우가 OIDC 인증으로 전환되었는지 확인
- 기존 시크릿 목록과 사용처 기록
단계
-
GitHub Repository Settings → Secrets and variables → Actions에서 기존 클라우드 키 삭제
- AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
- AZURE_CREDENTIALS(JSON 형식 Service Principal 키)
- GCP_SA_KEY(JSON 형식 Service Account 키)
-
클라우드 콘솔에서 해당 키 비활성화 또는 삭제
- AWS: IAM → Users → Security credentials → Access keys → Deactivate/Delete
- Azure: App registrations → Certificates & secrets → Client secrets → Delete
- GCP: IAM & Admin → Service Accounts → Keys → Delete
-
워크플로우 재실행하여 OIDC 인증만으로 작동하는지 확인
- 배포, 리소스 조회, 로그 업로드 등 모든 단계가 정상 완료되어야 함
주의점
- 일부 워크플로우가 여전히 장기 키를 참조하면 실행 실패
- 키 삭제 전에 모든 환경(production, staging)에서 OIDC 전환 완료 확인 필요
- 다른 CI/CD 도구나 로컬 환경에서 동일한 키를 사용 중이라면 별도 대응 필요
완료 기준
- GitHub Repository Secret에 클라우드 장기 키가 존재하지 않음
- 클라우드 콘솔에서 해당 키가 삭제되거나 비활성화됨
- 최소 한 번의 워크플로우 실행이 OIDC 인증으로 성공
전체 실행 순서
- 클라우드 제공자 콘솔에서 OIDC Identity Provider 등록
- GitHub repository 조건을 포함한 신뢰 정책으로 역할(Role) 또는 서비스 계정 생성
- 역할에 최소 권한 정책 부여
- GitHub Actions 워크플로우 파일에
permissions: id-token: write추가 - 인증 단계에 클라우드 제공자별 공식 Action 사용, 역할 ARN 또는 Workload Identity Provider 지정
- 워크플로우 실행하여 OIDC 인증 성공 확인
- 기존 장기 시크릿을 GitHub Repository와 클라우드 콘솔에서 삭제
- 모든 환경에서 재실행하여 장기 키 없이 작동하는지 검증
주의점과 실패하기 쉬운 지점
Subject identifier 조건 설정 오류
AWS Trust Policy나 Azure Federated Credential에서 sub claim 조건이 너무 광범위하면 의도하지 않은 repository나 branch에서 토큰을 받을 수 있다. repo:<org>/<repo>:ref:refs/heads/<branch> 또는 environment:<env-name> 형식으로 명확히 제한해야 한다.
permissions 블록 누락
워크플로우에 permissions: id-token: write가 없으면 OIDC 토큰 요청이 거부된다. 조직 수준에서 기본 권한을 제한한 경우 반드시 명시해야 한다.
역할 ARN이나 리소스 이름 오타
AWS role-to-assume, GCP workload_identity_provider 값에 오타가 있으면 인증 단계가 실패한다. 클라우드 콘솔에서 복사한 값을 그대로 붙여넣고, 로그에서 오류 메시지를 확인한다.
클라우드 제공자별 Audience claim 불일치
AWS는 aud: sts.amazonaws.com, Azure는 api://AzureADTokenExchange, GCP는 기본적으로 Workload Identity Provider URL을 사용한다. GitHub Actions OIDC 토큰의 aud claim을 클라우드 제공자 요구사항에 맞게 설정해야 한다.
기존 키 삭제 시점
모든 워크플로우와 환경에서 OIDC 전환을 완료하기 전에 장기 키를 삭제하면 배포가 중단된다. 단계적으로 전환하고, 마지막에 키를 제거하는 순서를 지킨다.
완료 확인 체크리스트
- [ ] 클라우드 콘솔에 OIDC Identity Provider가 등록되어 있고, Issuer URL이
https://token.actions.githubusercontent.com임 - [ ] 신뢰 정책에 GitHub repository 조건(
subclaim)이 명시되어 있음 - [ ] 역할 또는 서비스 계정에 필요한 최소 권한만 부여됨
- [ ] 워크플로우 파일에
permissions: id-token: write, contents: read블록이 있음 - [ ] 인증 단계에서 클라우드 제공자별 공식 Action을 사용하고, 역할 ARN 또는 Workload Identity Provider를 정확히 지정함
- [ ] 워크플로우 실행 로그에서 인증 단계가 성공하고, 이후 클라우드 명령어가 정상 실행됨
- [ ] GitHub Repository Secret에 클라우드 장기 키(Access Key, Service Principal 키, Service Account 키)가 남아 있지 않음
- [ ] 클라우드 콘솔에서 해당 키가 삭제되거나 비활성화됨
- [ ] 모든 환경(production, staging 등)에서 최소 한 번씩 워크플로우가 OIDC 인증으로 성공함
