
이번 주에 우리 팀 IAM trust policy 점검하다가 좀 놀란 게 있어서 짧게 적어둔다. 이거 모르는 분 꽤 많을 것 같다.
익숙한 그 패턴
GitHub Actions에서 AWS 붙일 때 OIDC federation 쓰는 건 이제 거의 표준이다. 그런데 trust policy 보다 보면 이런 게 자주 나온다.
{
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
}
}
}
좋다, 우리 repo로 한정은 했다. 근데 *이 너무 넓다. PR에서 돌아가는 워크플로우든, 누가 임시로 만든 브랜치에서 돌리는 거든, 환경 보호 없는 워크플로우든 — 전부 이 role을 가져갈 수 있다. fork PR에 누가 aws-actions/configure-aws-credentials 슬쩍 끼워넣으면 끝이다.
Datadog Security Labs가 작년에 공개한 조사에서, 아예 sub 조건 자체가 빠진 케이스도 꽤 발견됐다고 한다. 그러면 지구상 어느 GitHub Actions 워크플로우든 이 role 가져갈 수 있다는 뜻이다. 농담 아니고.
2026년 2월부터 더 잘 잠글 수 있게 됐다
원래 AWS STS는 OIDC 표준 클레임(sub, aud, amr)만 condition key로 노출했다. GitHub Actions OIDC 토큰은 30개 넘는 클레임을 담고 있는데 정작 쓸 수 있는 건 셋뿐이었던 거다.
2026년 2월에 AWS STS에 provider-specific claim validation이 추가되면서 이게 바뀌었다. 이제 token.actions.githubusercontent.com:repository, :environment, :workflow_ref, :job_workflow_ref 같은 클레임을 직접 condition key로 쓸 수 있다.
그래서 prod 배포용 role이라면 이렇게 잠근다.
{
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:repository": "my-org/my-repo",
"token.actions.githubusercontent.com:environment": "production"
},
"StringLike": {
"token.actions.githubusercontent.com:job_workflow_ref": "my-org/my-repo/.github/workflows/deploy.yml@*"
}
}
}
environment를 박아두면 GitHub Environments에 등록된 reviewer approval 없이는 토큰이 그 클레임을 못 얻는다. job_workflow_ref로 워크플로우 파일까지 못 박으면, 다른 워크플로우에서 이 role 못 들고 간다. 훨씬 좁다.
하나 더, 6월 18일 이후 만든 repo 주의
이건 덤. 2026년 4월 23일 GitHub 공지에 따르면 6월 18일 이후 생성된 repo는 OIDC sub claim에 owner ID와 repository ID가 자동으로 붙는다. repo 이름 재사용 공격 방어용인데, 기존 wildcard pattern은 매칭이 안 될 수 있다. trust policy를 repository_id 기준으로 옮기든가, 아니면 sub 매칭을 좀 더 유연하게 다시 짜야 한다.
정리
sub에*박힌 trust policy 보이면 일단 audit- prod role은
environment+job_workflow_ref조합으로 잠그자 - 신규 repo부터는 immutable ID 변경 영향 확인
다른 팀들은 이거 어떻게 잠그시는지 궁금하다. 우리는 일단 환경별로 role 쪼개고 environment claim 강제하는 방향으로 가고 있는데, 좀 더 깔끔한 패턴 있으면 공유 부탁드린다.
'IT > DevSecOps' 카테고리의 다른 글
| Vault Agent Injector annotation 충돌로 새벽에 일어난 이야기 (0) | 2026.05.31 |
|---|---|
| Trivy Operator vs Kubescape, 6개월 굴려보고 내린 결정 (0) | 2026.05.30 |
| Falco vs Tetragon, 둘 다 6개월 써본 결정 (0) | 2026.05.28 |
| Kyverno cluster policy 하나 올렸다가 API 서버가 죽은 새벽 (0) | 2026.05.27 |
| cert-manager로 Wildcard 인증서 자동화하기 (운영하며 만난 함정들) (0) | 2026.05.24 |