TIL

GitHub Actions와 AWS OIDC 기반 CI/CD 구축 및 인증 오류 해결

디버거러너 2026. 8. 1. 23:45

배경

Spring Boot 프로젝트에 GitHub Actions로 CI 파이프라인을 구축하고, AWS OIDC 인증으로 ECR에 Docker 이미지를 Push하는 자동화를 실습했다.

Workflow 파일을 작성하는 것 자체보다, 실제로 파이프라인을 돌리면서 마주친 인증·권한 문제를 해결하는 과정이 이번 실습의 핵심이었다.

구축한 흐름은 다음과 같다.

Git Push
  ↓
GitHub Actions 실행
  ↓
Gradle Test
  ↓
Spring Boot JAR Build
  ↓
AWS OIDC 인증
  ↓
ECR Login
  ↓
Docker Image Build & Push

1. GitHub Actions Workflow 파일 Push 실패

.github/workflows/ci.yml을 작성하고 Push하는데 다음 오류가 발생했다.

remote: refusing to allow a Personal Access Token to create or update workflow
'.github/workflows/ci.yml' without 'workflow' scope

처음엔 YAML 문법 문제인 줄 알았지만, 원인은 Git 인증 방식이었다. HTTPS로 Push하면서 Mac Keychain에 저장된 Personal Access Token(PAT)을 쓰고 있었는데, 이 PAT에는 .github/workflows 경로를 수정할 수 있는 workflow scope가 없었다. GitHub는 보안상 워크플로 파일 변경 시 이 scope를 별도로 요구한다.

 

해결: HTTPS 대신 SSH로 전환했다.

# SSH 인증 상태 확인
ssh -T git@github.com
# → Hi trex1004! You've successfully authenticated

# remote를 SSH 방식으로 변경
git remote set-url origin git@github.com:trex1004/ci-demo.git

git push origin main  # 성공

Git Push 오류가 나면 코드나 파일 문제만 의심하기 쉬운데, 인증 방식(HTTPS/SSH)이나 Token scope도 원인이 될 수 있다는 걸 확인했다. (섬세한 GitHub 개발자들…;;)


2. AWS OIDC AssumeRole 인증 실패

Could not assume role with OIDC:
Not authorized to perform sts:AssumeRoleWithWebIdentity

OIDC 인증 구조

이 프로젝트는 처음부터 Access Key 대신 OIDC 방식을 쓰고 있었다. GitHub Actions가 발급받은 OIDC Token으로 AWS STS의 AssumeRoleWithWebIdentity를 호출해 IAM Role을 임시로 획득하는 구조라, Access Key를 GitHub Secrets에 저장할 필요가 없다.

GitHub Actions → OIDC Token 발급 → AWS STS AssumeRoleWithWebIdentity → IAM Role 획득 → AWS 서비스 접근

원인

IAM Role의 Trust Policy를 확인했다.

"StringLike": {
  "token.actions.githubusercontent.com:sub": [
    "repo:trex1004/ci-demo:*"
  ]
}

기존 Trust Policy는 repo:trex1004/ci-demo:* 형식의 subject만 허용하고 있었다.

 

그런데 GitHub OIDC 정책 변경으로, 새로 만든 저장소는 owner ID와 repository ID를 포함한 immutable subject claim 형식을 쓰고 있었다.

현재 GitHub가 전달하는 subject 값과 Trust Policy 조건이 일치하지 않아 AssumeRole이 실패한 것이었다.

 

해결: Trust Policy 조건에 새 형식을 추가했다.

"StringLike": {
  "token.actions.githubusercontent.com:sub": [
    "repo:trex1004/ci-demo:*",
    "repo:trex1004@*/ci-demo@*:*"
  ]
}

수정 후 재실행하니 AWS OIDC 인증에 성공했다.


회고 — 다른 개발자의 트러블슈팅 기록으로 문제를 푼 경험

이번 문제를 풀면서 처음으로, 다른 팀원이 공유한 트러블슈팅 기록이 실제 문제 해결에 직접 도움이 되는 경험을 했다.

지금까지는 오류가 나면 메시지를 검색하고 직접 원인을 찾아가는 방식으로 해결해왔다.

이번에도 처음엔 같은 방식으로 접근했는데, OIDC·Trust Policy·Subject Claim 같은 개념이 아직 낯설어서 정확히 뭘 고쳐야 하는지 바로 감이 오지 않았다.

Trust Policy(신뢰 관계)를 들여다보던 중

 

예전에 팀원 mo가 공유해준 "뭔가" 떠올랐다.(짧은 내용이지만 정독해도 이해조차 안 되었었다,,;;)

당시엔 "뭔가 공유해 주셨구나" 정도로만 받아들였다. 그런데 막상 같은 문제를 마주하니,,

"혹시 이게 그때 mo가 공유해준 그 “뭔가” 때문인가?" 라는 생각이,,,

 

다시 찾아본 끝에 기존 Trust Policy가 바뀐 subject 형식을 허용하지 않고 있다는 걸 확인할 수 있었다.

mo님의 공유가 없었다면 IAM Role, OIDC Provider, Trust Policy를 하나씩 다시 확인하며 훨씬 오래 걸렸을 것이다.

처음엔 이해하지 못했던 정보가 실제 문제 상황과 만나면서 쓸모 있는 지식으로 연결된 경험이기도 했다.

 

앞으로 나도 문제를 해결하면 개인 기록으로만 남기지 않고, 다른 사람이 같은 문제를 만났을 때 도움이 될 수 있도록 원인과 해결 과정을 정리해서 공유하는 개발자가 되고 싶다는 생각이 들었다.

 

마지막으로 이번 오류 해결에 도움을 준 mo님에게 감사드립니데이,,