문제 상황
슬랙에 뜬 공지 하나..
띠용? 서버 배포가 안돼요!
현재 까비는 서비스 배포 및 업데이트 시 access key를 사용하고 있고, 이를 이용하여 github action이 AWS로부터 자격 증명을 받고, code deploy로 자동배포를 진행중이다.
공지와 함께 며칠 뒤 access key가 강제로 삭제되었고, 진짜에요? 하는 마음으로 dev 브런치에 push해보니 오류가 난다. 지금 당장 dev나 prod에 올릴 작업은 없지만, 빠르게 고치지 않는다면 남은건 직접 EC2 서버에 들어가 git pull, 서버 구동.. 그 사이에 누가 또 push하면 다시 또.. 만약 충돌나면 하나씩 로그 보면서 눈알 빠지고..
절대 싫어~를 외치며 대안을 찾아보자.
우리는 github action에서 access key 없이 AWS 자격증명 받기 가 목적이다.
기존에도 최소한의 권한만 주긴 했지만 서드파티에 서비스 관련 보안정보를 보관하는건 권장사항이 아니라고도 하고, access key와 관련한 보안 문제는 이전부터 꾸준히 제기되어 왔으니 거인들이 대안을 이미 찾아놨을 것이라 믿고 검색하자.
해결 방안
github action - aws 간의 OIDC 인증 전체 과정
당연히, 대안은 있었다. 바로 Open ID Connect(OIDC) 방식으로, 해당 방식을 사용하면 Github Actions 워크플로우가 AWS 자격 증명을 수명이 긴 Github Secret으로 저장할 필요 없이, 임시자격증명을 통해 AWS의 리소스에 엑세스 할 수 있다.
OIDC는 OpenID Foundation에서 정의한 개방형 인증 표준으로, OAuth 2.0 프로토콜 기반 상위 계층에서 인증 처리를 마치고, Identity Provider(IdP)를 통해 사용자 정보를 제공하는 방식이다.
적용 과정
1.
AWS에 OIDC IdP 등록
2.
IAM role 생성
3.
Github Actions 워크플로우 파일 수정
떼밋.. github에서 진행 과정 또한 매우 상세하게! 적어뒀다. 읽고, 이해하고, 따라하면 끝이다
AWS에 OIDC IdP 등록하기
AWS 콘솔 리뉴얼 후인 2025.1.9일자로 작성되었으나, 이후 콘솔 내용이 또 바뀌어도 뭐 유사한 과정을 거칠 것으로 예상된다.
AWS 콘솔 → IAM → ID 제공업체 → 공급자 추가
문서에 나온대로, 공급자 url에는 github actions를, 대상에는 aws를 넣어주자
IAM Role 생성
사진에 다 담기진 않았지만, 해당 페이지 아래부분에 조직명(필수), repository 이름, branch도 명시할 수 있다.
이후에 권한 정책 부분에서 AWS 자격 증명이 필요한게 있다면, 이것도 넣어줘야한다(까비의 경우, S3, CodeDeploy, Lambda 관련 정책을 추가해줬다)
우리는 dev, main 브랜치에 푸시할 경우 배포를 진행하고 있기 때문에 저 페이지에선 일단 dev로 브랜치를 지정했다. 그러믄 신뢰 관계 기본 틀이 잘 작성되어 나오고, main 브랜치도 추가해줘야하니 다음과 같이 조금만 변경하면 완성이다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn~/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com" // aud -> 토큰 공급자
},
// 단일 -> StringEquals, dev, main 둘 다 포함해야해서 StringLike로 변경
"StringLike": {
"token.actions.githubusercontent.com:sub": [
"repo:조직명/레포명:ref:refs/heads/dev",
"repo:조직명/레포명:ref:refs/heads/main"
]
}
}
}
]
}
JSON
복사
Github Actions 워크플로우 파일 수정
진짜 다왔다.. 이전 기수 분들이 깎아놓은 마스터피스에 추가된 부분만 얹으면 된다
# job 보다 상단에 위치한다.
permissions:
id-token: write # GitHub의 OIDC 공급자에서 JWT를 요청 -> Github Actions 도구 키트에서 getIDToken() 사용
contents: read # 워크플로우에서 리포지토리의 콘텐츠를 읽을 수 있는 권한을 설정
....
- name: Configure AWS credentials
if: ${{ format('refs/heads/{0}', env.ENVIRONMENT) == github.ref }}
uses: aws-actions/configure-aws-credentials@v2 # 버전 1 -> 2 업데이트
with: # 기존 access, secret key들을 지우고 IAM role로 대체한다
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}
YAML
복사
문제 없이 성공!
마무리
근데 OIDC 방식이 AWS의 access, secret key를 Github Secrets에 저장하는 방식보다 나은게 뭐임?
1.
비밀 키 저장 필요 없음
a.
key 저장 방식 : 자격 증명을 위해 Github Secrets에 저장해야하므로, 혹~시라도 휴먼 에러로 유출이 된다면 AWS 리소스에 대해 무단 액세스 위험이 존재한다. 유출 시 직접 키 교체 및 재배포도 번거로움
b.
OIDC : 자격증명을 저장할 필요 없이 JWT를 통해 임시 인증을 수행하고, IAM 역할을 활용해 최소 권한만 부여받게 된다. 또한 해당 단기 자격증명은 워크플로우 실행 동안만 유효하며, 만료 시 자동 폐기된다.
2.
권한 제어
a.
key : 고정 권한을 갖기 때문에, 브랜치 및 워크플로우에 따라 다른 권한 적용하기 어려움
b.
OIDC : 세부 권한을 설정해 특정 레포, 브랜치, 워크플로우가 AWS의 어느 리소스까지만 접근할 수 있는지 세부 제어 가능.
간략하게 하면, 보안 및 관리의 용이성이 돋보이는거같다.
여튼 위와 같은 과정을 거쳐 까비는 조금 더 건강한 보안을 갖게 되었다!