AWS 깃허브(GitHub) 키 유출 사고 완벽 방어: IAM Role 및 OIDC 아키텍처
[Troubleshooting] AWS 깃허브(GitHub) 키 유출 사고 완벽 방어: OIDC 아키텍처
"GitHub Actions로 AWS S3에 프론트엔드를 자동 배포하려고 리포지토리 Secrets에 AWS_ACCESS_KEY_ID와 SECRET_ACCESS_KEY를 등록했습니다. 그런데 개발 도중 실수로 키값이 코드에 섞여 퍼블릭 레포지토리에 커밋되었고, 불과 10분 만에 해커들이 내 계정으로 코인 채굴용 서버를 수백 개 띄워 5천만 원의 요금 폭탄 청구서를 받았습니다."
클라우드 환경에서 데브옵스 CI/CD를 세팅하는 전 세계 주니어 개발자들이 매일같이 겪는 가장 참혹하고 파멸적인 보안 사고입니다. AWS의 액세스 키는 당신의 신용카드 비밀번호와 같습니다. 한 번 유출되면 AWS의 무한한 확장성을 악용하여 5분 만에 수천만 원의 과금을 발생시킵니다.
초보자들은 깃허브 Secrets에 잘 숨기면 안전할 것이라 착각하며 수명이 영원한(Long-lived) 액세스 키를 무심코 발급받아 복사해 둡니다. 본 가이드에서는 어딘가에 키를 저장한다는 행위 자체의 보안적 취약성을 해체하고, 애초에 '유출될 키를 만들지 않는' GitHub OIDC (OpenID Connect) 기반 무접점 보안 아키텍처를 단호하게 제시합니다.
📌 이 글의 핵심 포인트
- 영구 키의 덫: 한 번 발급받으면 수동으로 삭제하기 전까지 영원히 권한을 갖는 IAM 사용자(User) Access Key의 치명적 위험성
- 패러다임 전환: 비밀번호를 깃허브에 저장하는 것이 아니라, AWS가 깃허브 플랫폼 자체를 신뢰하여 15분짜리 임시 출입증을 발급하는 OIDC 연동
- 안전한 파이프라인:
configure-aws-credentials액션을 활용한 단기 자격 증명(Assume Role) 아키텍처 구축법
1단계: 핵심 원인 분석 - 유출될 수밖에 없는 영구 키
일반적으로 CI/CD를 짤 때, 개발자는 AWS IAM에서 프로그래밍 방식 접근(User)을 생성하고 얻은 키를 GitHub Secrets에 등록합니다. 만약 GitHub Actions의 로그를 잘못 찍거나, 팀원이 스크립트를 잘못 짜서 키가 화면에 노출되면 그대로 끝입니다. 이 키는 유통기한이 없는 마스터 키이기 때문에 해커가 가로채면 무한정 사용할 수 있습니다.
진정한 엔터프라이즈 보안은 키를 잘 숨기는 것이 아니라, '해커가 탈취해도 15분 뒤면 썩어서 못 쓰게 되는 일회용 토큰'을 사용하는 데 있습니다.
2단계: 완벽한 트러블슈팅 - OIDC 자격 증명 공급자 등록
AWS에게 "앞으로 깃허브(GitHub Actions)가 내 레포지토리에서 요청을 보내면, 믿을 만한 놈이니까 잠깐 쓸 수 있는 임시 열쇠(Role)를 내어줘라"라고 세팅해야 합니다.
- AWS IAM 콘솔의 좌측 메뉴에서 [자격 증명 공급자(Identity providers)]로 이동하여 [공급자 추가]를 누릅니다.
- OpenID Connect를 선택합니다.
- 공급자 URL:
https://token.actions.githubusercontent.com(지문 가져오기 클릭) - 대상(Audience):
sts.amazonaws.com입력 후 저장합니다. - 이제 IAM 역할(Role)을 하나 만들고, 신뢰 관계(Trust relationships)에 방금 만든 OIDC 공급자와 당신의 깃허브 레포지토리 이름(
repo:my-org/my-repo:*)을 명시하여 권한(S3 업로드 등)을 연결합니다.
3단계: GitHub Actions 무결점 아키텍처 적용
이제 깃허브 Secrets에는 더 이상 무서운 액세스 키를 저장할 필요가 없습니다. 오직 방금 만든 IAM Role의 ARN 주소 하나만 있으면 됩니다. (ARN 주소는 유출되어도 해커가 깃허브 서버를 해킹하지 않는 이상 절대 쓸 수 없는 껍데기 주소입니다.)
name: Deploy to AWS
on:
push:
branches: [ "main" ]
# OIDC 토큰 발급을 위해 permissions 명시 필수
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 소스코드 체크아웃
uses: actions/checkout@v3
# ✅ 무결점 아키텍처: OIDC를 통해 임시 자격 증명(STS) 획득
- name: AWS 권한 획득 (OIDC)
uses: aws-actions/configure-aws-credentials@v3
with:
# Secrets에 Access Key가 아닌 Role ARN 주소만 저장해 둠
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-2
# 이제부터 실행되는 모든 AWS 명령어(S3 업로드 등)는
# 15분짜리 안전한 임시 토큰을 통해 완벽하게 수행됨
- name: S3로 배포
run: aws s3 sync ./build s3://my-frontend-bucket
🙋♂️ 자주 묻는 질문 (FAQ)
Q. 이미 실수로 Access Key를 깃허브 퍼블릭에 올려버렸어요! 어떡하나요?
A. 지금 당장, 1초도 지체하지 말고 AWS IAM 콘솔로 접속해서 해당 Access Key를 [비활성화(Make inactive)] 한 뒤 [삭제(Delete)] 하십시오. 커밋 히스토리를 덮어쓰고 깃허브에서 지워도, 해커들의 봇은 이미 0.1초 만에 키를 크롤링해서 복사해 갔습니다. 무조건 AWS 서버에서 키를 파기하는 것만이 유일한 생존법입니다.
💡 핵심 정리 및 마무리
비밀번호는 숨기는 것이 아니라 폐기하는 것입니다. 클라우드 보안의 패러다임은 영구적인 인증(Credential)에서 단기적인 역할 위임(Assume Role)으로 완전히 진화했습니다. OIDC 기반의 인증 연동 아키텍처를 도입하여, 소스 코드가 털려도 클라우드 인프라만큼은 절대로 뚫리지 않는 제로 트러스트(Zero Trust) 배포 파이프라인을 완성하시기 바랍니다.
댓글
댓글 쓰기