Cách cũ: IAM user → access key → GitHub Secrets. Vấn đề: key không expire. Nếu lộ (Uber 2016 — $148M settlement), attacker có full access vô hạn. Cách mới: OIDC federation — GitHub Actions nhận STS token từ AWS, không lưu access key, token expire 1h.
flowchart LR
GHA["GitHub Actions"] -->|"1. OIDC JWT"| OIDC["token.actions.githubusercontent.com"]
OIDC -->|"2. JWT"| GHA
GHA -->|"3. AssumeRoleWithWebIdentity"| STS["AWS STS"]
STS -->|"4. Temp credential (1h)"| GHA
Setup
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list a031c46782e6e6c662c2c87c76da9aa62ccabd8e
Trust policy — scope càng hẹp càng an toàn:
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::...: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:myorg/myapp:ref:refs/heads/main"
}
}
}
# .github/workflows/deploy.yml
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: ap-southeast-1
- run: npm ci && npm run build && npx cdk deploy --require-approval never
Multi-environment + Protection
jobs:
deploy:
strategy:
matrix:
environment: [staging, production]
environment:
name: ${{ matrix.environment }}
# Production: required reviewers (2), wait timer (5 min)
OIDC > IAM user access key: token expire 1h, không lưu credential. Trust policy scope hẹp: repo + branch + environment. Deploy role least privilege: chỉ quyền cần, không AdministratorAccess. Environment protection: required reviewers cho production.
Bài sau: Phần 25: SQS — Standard, FIFO, DLQ, visibility timeout