- Published on
GitHub Actions OIDC AWS AssumeRole 1시간 제한 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버리스/인프라 배포 파이프라인을 GitHub Actions로 운영하다 보면, 장시간 실행되는 작업(대형 Docker 이미지 빌드, 멀티 리전 배포, 대규모 Terraform apply 등)에서 AWS 자격 증명이 중간에 만료되어 실패하는 경우가 자주 발생합니다. 특히 OIDC 기반으로 aws-actions/configure-aws-credentials를 쓰면, 체감상 “왜 항상 1시간에서 끊기지?”라는 상황을 만나기 쉽습니다.
이 글에서는 GitHub Actions OIDC로 AWS STS AssumeRoleWithWebIdentity를 사용할 때 세션이 1시간으로 제한되는 대표 원인과, 실무에서 안정적으로 해결하는 방법을 정리합니다. 또한 “세션을 무작정 늘리는 것”이 항상 정답이 아닌 이유와, 장시간 작업을 안전하게 만드는 전략(재발급/Job 분할)까지 함께 다룹니다.
관련해서 OIDC 신뢰 정책/권한 설정이 꼬여 AssumeRole 자체가 실패하는 케이스는 아래 글도 같이 참고하면 디버깅 시간이 크게 줄어듭니다.
문제 증상: 정확히 1시간 근처에서 자격 증명 만료
전형적인 실패 로그는 다음 중 하나로 나타납니다.
ExpiredToken: The security token included in the request is expiredThe provided token has expiredSignatureDoesNotMatch가 후속 요청에서 연쇄적으로 발생(만료된 키로 서명)
GitHub Actions에서 OIDC로 발급받은 STS 세션은 기본적으로 유효기간이 짧고(보통 1시간), 워크플로가 1시간을 넘어가면 AWS API 호출이 끊기면서 배포가 실패합니다.
왜 OIDC AssumeRole은 1시간으로 “고정”되는가
OIDC 기반은 AWS STS의 AssumeRoleWithWebIdentity 경로를 사용합니다. 이 경로는 일반적인 AssumeRole(Access Key로 Assume)과 달리 제약이 더 강하며, 다음 요소들이 1시간 제한을 만들 수 있습니다.
1) MaxSessionDuration을 늘려도 OIDC는 그대로인 경우
IAM Role의 MaxSessionDuration(최대 세션 지속시간)을 2시간, 12시간으로 늘렸는데도 계속 1시간으로 끊기는 경우가 있습니다. 이유는 다음 중 하나입니다.
- 실제로는 Role의
MaxSessionDuration이 변경되지 않았거나(다른 Role을 보고 있음) aws-actions/configure-aws-credentials가role-duration-seconds를 지정하지 않아 기본값으로 발급됨- 조직 정책(SCP) 또는 권한 경계(Permissions Boundary) 등으로 세션 길이가 제한됨
- OIDC 공급자/조건 설정이 보수적으로 되어 있고, 실제 발급 경로가 기대와 다름
핵심은, “Role 쪽 최대 세션”과 “STS 호출 시 요청 duration”이 둘 다 맞아야 합니다.
2) GitHub Actions의 토큰/권한 설정 미흡
OIDC는 GitHub가 워크플로에 발급하는 ID 토큰을 기반으로 합니다. 워크플로에 아래 permission이 빠지면 OIDC 토큰을 제대로 못 받아 다른 경로로 동작하거나, 재시도/재발급이 꼬일 수 있습니다.
permissions: id-token: write
또한 aws-actions/configure-aws-credentials는 내부적으로 토큰을 가져와 STS를 호출합니다. 이 단계가 한 번만 성공하고 이후 장시간 작업 중 세션이 만료되면, 자동으로 갱신되지 않습니다(즉, “한 번 발급하면 끝” 패턴).
3) 장시간 단일 Job 설계 자체가 취약
세션 지속시간을 늘리는 것만으로 해결되는 경우도 있지만, 더 안전한 접근은 “만료되기 전에 다시 발급”하거나 “Job을 쪼개서 짧게 실행”하는 것입니다.
특히 Terraform이나 대형 배포 파이프라인은 실패 시 재시도가 필요하므로, 인증도 재발급 가능한 구조가 운영 안정성 측면에서 유리합니다.
해결 1: Role의 MaxSessionDuration을 먼저 확인/설정
IAM Role의 최대 세션 시간을 1시간에서 더 늘립니다. 콘솔에서 Role 편집 또는 CLI로 확인/변경할 수 있습니다.
CLI로 현재 값 확인
aws iam get-role --role-name MyDeployRole \
--query 'Role.MaxSessionDuration'
최대 세션을 2시간(7200초)로 변경
aws iam update-role --role-name MyDeployRole \
--max-session-duration 7200
주의할 점:
- 이 값은 “최대치”일 뿐이며, 실제 STS 요청에서 더 짧게 요청하면 그 값으로 발급됩니다.
- 조직 단위 제약(SCP)이나 권한 경계가 있으면 더 늘리지 못할 수 있습니다.
해결 2: GitHub Actions에서 role-duration-seconds를 명시
가장 흔한 누락이 role-duration-seconds 미지정입니다. 아래처럼 aws-actions/configure-aws-credentials에 지속시간을 명시하세요.
name: deploy
on:
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/MyDeployRole
aws-region: ap-northeast-2
role-duration-seconds: 7200
- name: Verify caller
run: aws sts get-caller-identity
- name: Long running deploy
run: |
./deploy.sh
체크포인트:
role-duration-seconds는 Role의MaxSessionDuration을 초과할 수 없습니다.permissions에id-token: write가 반드시 있어야 합니다.
해결 3: 신뢰 정책(Trust Policy)에서 OIDC 조건을 정확히
세션 지속시간 이슈와 별개로, OIDC 설정이 조금만 어긋나도 실패/재시도가 꼬이면서 “대충 되는데 가끔 끊김” 같은 불안정 상태가 됩니다.
다음은 GitHub OIDC 공급자를 사용하는 Role 신뢰 정책 예시입니다. 본문에 부등호 문자가 노출되면 MDX에서 문제가 될 수 있으므로, 조건 키/값은 그대로 두되 코드 블록으로만 제공합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012: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:my-org/my-repo:*"
}
}
}
]
}
권장 사항:
sub를 가능한 한 좁게 제한하세요. 예: 특정 브랜치/환경만 허용.aud는 보통sts.amazonaws.com으로 고정합니다.
해결 4: 1시간을 넘는 작업은 “재인증” 또는 “Job 분할”로 설계
세션을 2시간, 4시간으로 늘려도 언젠가 만료는 옵니다. 장시간 작업을 운영 관점에서 안정화하려면 다음 중 하나가 필요합니다.
전략 A) 단계마다 OIDC 재발급(재실행)하기
configure-aws-credentials는 실행 시점에 STS 세션을 발급합니다. 따라서 긴 Job이라도 중간 단계에서 다시 한 번 실행하면 새 세션으로 갱신할 수 있습니다.
- name: Configure AWS credentials (phase 1)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/MyDeployRole
aws-region: ap-northeast-2
role-duration-seconds: 3600
- name: Build artifacts
run: ./build.sh
- name: Configure AWS credentials (phase 2 refresh)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/MyDeployRole
aws-region: ap-northeast-2
role-duration-seconds: 3600
- name: Deploy
run: ./deploy.sh
이 방식은 “세션을 길게” 가져가는 대신 “짧게 자주” 갱신하는 모델이라, 보안/운영 모두에서 장점이 큽니다.
전략 B) Job을 쪼개고 아티팩트로 전달
빌드와 배포를 분리하면 각 Job이 독립적으로 OIDC를 발급받습니다. 빌드 Job에서는 AWS 인증이 필요 없을 수도 있고, 배포 Job만 짧게 인증을 쓰게 만들 수 있습니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./build.sh
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/MyDeployRole
aws-region: ap-northeast-2
role-duration-seconds: 3600
- run: ./deploy.sh
디버깅 체크리스트: “늘렸는데도 1시간”일 때
아래를 순서대로 확인하면 대부분 원인이 좁혀집니다.
- Role의
MaxSessionDuration확인
aws iam get-role로 실제 값이 바뀌었는지 확인
- 워크플로에서
role-duration-seconds명시 여부
- 지정하지 않으면 기본값으로 발급될 수 있습니다.
- 워크플로
permissions에id-token: write존재 여부
- 없으면 OIDC 토큰 발급 자체가 불가능합니다.
- 실제로 Assume한 Role이 맞는지 확인
aws sts get-caller-identity출력의 ARN 확인
- 조직 정책(SCP) 또는 권한 경계로 제한되는지
- 특히 멀티 계정/Organizations 환경에서 흔합니다.
- 장시간 단일 Job인지, 중간에 재발급 가능한 구조인지
- 세션을 늘려도 “언젠가는” 만료됩니다.
보안 관점 팁: 세션을 무작정 길게 하지 말아야 하는 이유
OIDC의 강점은 “단기 자격 증명”입니다. 세션을 길게 늘리면 편하긴 하지만, 유출/오남용 시 피해 창이 커집니다. 따라서 다음 원칙을 권장합니다.
- 가능한 최소 권한(Role Policy 최소화)
- 가능한 짧은 세션 + 필요 시 재발급
- 신뢰 정책에서
sub를 좁게(특정 repo/branch/environment)
장시간 파이프라인은 “세션 연장”보다 “단계별 재인증/Job 분리”가 더 안전하고, 재시도에도 강합니다.
마무리
GitHub Actions OIDC로 AWS에 배포할 때 1시간 만료 문제는 보통 다음 2가지가 핵심입니다.
- IAM Role의
MaxSessionDuration과 워크플로의role-duration-seconds를 함께 맞춘다. - 장시간 단일 Job을 피하고, 중간 재발급 또는 Job 분할로 만료에 강한 구조를 만든다.
위 설정을 적용하면 “딱 1시간에서 끊기는” 배포 실패를 안정적으로 제거할 수 있고, 동시에 OIDC의 장점인 단기 자격 증명 모델도 유지할 수 있습니다.