OIDC GitHub Actions ke AWS memungkinkan workflow memperoleh kredensial AWS sementara tanpa menyimpan AWS_ACCESS_KEY_ID dan AWS_SECRET_ACCESS_KEY sebagai GitHub Secrets. GitHub menerbitkan JSON Web Token (JWT) untuk workflow, lalu AWS Security Token Service (STS) memvalidasi token tersebut dan mengembalikan kredensial sementara untuk IAM role yang telah dibatasi.
Keamanan pendekatan ini bergantung pada dua lapisan: trust policy menentukan workflow GitHub mana yang boleh mengambil role, sedangkan permissions policy menentukan tindakan AWS yang boleh dilakukan setelah role diperoleh. Keduanya harus dibuat sesempit mungkin.
Alur autentikasi OIDC GitHub Actions ke AWS
- Workflow memiliki permission
id-token: write. - GitHub menerbitkan OIDC token berumur pendek yang memuat claim seperti
aud,sub, repository, ref, dan nama Environment. aws-actions/configure-aws-credentialsmengirim token tersebut ke operasi STSAssumeRoleWithWebIdentity.- AWS memvalidasi tanda tangan token melalui IAM OIDC provider, lalu mengevaluasi claim terhadap trust policy role.
- Jika cocok, STS memberikan access key, secret key, dan session token sementara kepada job.
- AWS CLI atau SDK dalam job menggunakan kredensial sementara tersebut sampai sesi berakhir.
Permission id-token: write tidak langsung memberikan akses ke AWS. Permission itu hanya mengizinkan job meminta token OIDC. Akses AWS tetap ditentukan oleh provider, trust policy, permissions policy, resource policy, permission boundary, dan Service Control Policy jika digunakan.
Menyiapkan IAM OIDC provider dan deployment role
Konfigurasi provider
Buat IAM OIDC provider dengan nilai berikut untuk partisi AWS standar:
- Provider URL:
https://token.actions.githubusercontent.com - Audience:
sts.amazonaws.com
Satu provider dapat dipakai oleh beberapa role dalam akun AWS yang sama. Jangan membuat provider duplikat jika provider GitHub sudah tersedia. Contoh CloudFormation berikut membuat provider sekaligus role untuk deployment ke satu bucket S3:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
GitHubOrganization:
Type: String
GitHubRepository:
Type: String
DeploymentBucket:
Type: String
Resources:
GitHubOidcProvider:
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
DeploymentRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Ref GitHubOidcProvider
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
'token.actions.githubusercontent.com:aud': sts.amazonaws.com
'token.actions.githubusercontent.com:sub':
!Sub 'repo:${GitHubOrganization}/${GitHubRepository}:environment:production'
Policies:
- PolicyName: DeployStaticSite
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: ListDeploymentBucket
Effect: Allow
Action:
- s3:ListBucket
- s3:GetBucketLocation
Resource: !Sub 'arn:aws:s3:::${DeploymentBucket}'
- Sid: WriteDeploymentObjects
Effect: Allow
Action:
- s3:PutObject
- s3:DeleteObject
Resource: !Sub 'arn:aws:s3:::${DeploymentBucket}/*'
Outputs:
DeploymentRoleArn:
Value: !GetAtt DeploymentRole.ArnIsi parameter organisasi, repository, dan bucket dengan nilai milik Anda. Jika provider sudah ada, hapus resource GitHubOidcProvider dari template dan referensikan ARN provider yang sudah tersedia.
Mengapa aud dan sub harus dibatasi?
Claim aud memastikan token ditujukan untuk AWS STS. Claim sub mengidentifikasi konteks workflow yang meminta token. Memeriksa keduanya mencegah role menerima sembarang token yang diterbitkan GitHub.
Hindari trust policy yang hanya memeriksa
audatau memakai polarepo:ORGANIZATION/*tanpa alasan yang jelas. Pola terlalu luas dapat membuat repository atau workflow lain dalam organisasi ikut memenuhi trust policy.
Menerapkan least privilege pada deployment role
Contoh di atas hanya mengizinkan sinkronisasi objek ke satu bucket. Sesuaikan policy dengan mekanisme deployment sebenarnya. Misalnya, deployment ECS membutuhkan izin terhadap service dan task definition tertentu; deployment Lambda membutuhkan izin pembaruan fungsi tertentu; penggunaan KMS juga memerlukan izin key policy dan IAM yang sesuai.
Jangan memberikan AdministratorAccess hanya untuk mengatasi kegagalan awal. Mulailah dari resource dan operasi yang diketahui, uji deployment, lalu tambahkan izin yang memang terlihat diperlukan. Pisahkan role produksi dan nonproduksi agar kompromi workflow staging tidak otomatis membuka akses produksi.
Membatasi repository, branch, tag, dan GitHub Environment
Format claim sub berubah sesuai konteks workflow. Trust policy harus memakai format yang sama dengan token aktual.
Branch tertentu
Untuk mengizinkan hanya branch main dari satu repository:
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:ORGANIZATION/REPOSITORY:ref:refs/heads/main"
}Tag rilis
Untuk mengizinkan tag dengan awalan v, gunakan StringLike secara hati-hati:
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:ORGANIZATION/REPOSITORY:ref:refs/tags/v*"
}Pola ini cocok untuk tag seperti v1.4.0, tetapi siapa pun yang dapat membuat tag yang cocok dapat mencoba menjalankan deployment. Lindungi pembuatan tag dan workflow rilis melalui aturan repository yang sesuai.
GitHub Environment
Jika job menggunakan GitHub Environment bernama production, subject menjadi:
repo:ORGANIZATION/REPOSITORY:environment:productionDalam kondisi ini, subject tidak lagi memuat branch atau tag. Pembatasan branch, tag, dan persetujuan manual harus dikonfigurasi melalui deployment protection rules pada Environment tersebut. Kombinasi yang umum adalah:
- Trust policy IAM hanya menerima subject Environment
production. - Environment
productionhanya menerima deployment dari branch atau tag yang disetujui. - Required reviewers digunakan jika deployment produksi memerlukan persetujuan.
- Workflow tetap membatasi event melalui
on.push.branchesatauon.push.tags.
Jangan memakai subject branch di IAM sementara job mendeklarasikan environment: production. Perbedaan format tersebut akan menghasilkan kegagalan AssumeRoleWithWebIdentity.
Workflow GitHub Actions tanpa access key statis
Workflow berikut berjalan ketika ada push ke main atau ketika dijalankan manual. Job menggunakan Environment production, sehingga trust policy CloudFormation sebelumnya harus menerima subject Environment tersebut.
name: Deploy to AWS
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Configure temporary AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
role-session-name: gha-${{ github.run_id }}-${{ github.run_attempt }}
- name: Verify AWS identity
run: aws sts get-caller-identity
- name: Deploy static files
run: aws s3 sync ./dist "s3://${{ vars.DEPLOYMENT_BUCKET }}" --deleteAWS_DEPLOY_ROLE_ARN, AWS_REGION, dan DEPLOYMENT_BUCKET bukan kredensial sehingga dapat disimpan sebagai GitHub Actions Variables. Tidak ada access key yang perlu disimpan sebagai secret.
Contoh menggunakan tag versi mayor agar mudah dibaca. Untuk mengurangi risiko supply-chain pada workflow produksi, pertimbangkan mematok action pihak ketiga ke commit SHA penuh dan gunakan proses pembaruan dependensi yang terkontrol.
Risiko pull request dari fork
Kode dari pull request eksternal harus dianggap tidak tepercaya. Jika trust policy menggunakan pola luas seperti repo:ORGANIZATION/REPOSITORY:*, subject untuk konteks pull request dapat ikut cocok dan membuka kemungkinan job meminta role AWS.
Gunakan langkah pengamanan berikut:
- Jangan izinkan subject
pull_requestpada role deployment. - Batasi trust policy ke branch, tag, atau Environment tertentu.
- Jangan menjalankan deployment pada event
pull_request. - Gunakan Environment dengan required reviewers untuk produksi.
- Hindari mengeksekusi kode pull request yang tidak tepercaya dalam job yang memiliki akses OIDC ke AWS.
- Berhati-hatilah dengan
pull_request_target. Event ini berjalan dalam konteks repository dasar dan dapat berbahaya jika workflow mengambil lalu menjalankan kode dari fork. - Pisahkan job build kode tidak tepercaya dari job deployment. Artefak yang diteruskan ke deployment juga perlu divalidasi.
Pembatasan event dalam YAML saja bukan pengganti trust policy. Orang yang dapat mengubah workflow mungkin dapat menambah pemicu baru, sedangkan pemeriksaan sub di IAM tetap diberlakukan oleh AWS.
Verifikasi akses melalui AWS dan CloudTrail
Langkah aws sts get-caller-identity menunjukkan account, user ID sesi, dan ARN role yang sedang digunakan. Pastikan hasilnya menunjuk ke deployment role, bukan IAM user lama.
AWS CloudTrail mencatat panggilan STS AssumeRoleWithWebIdentity. Untuk mencari event melalui event history:
aws cloudtrail lookup-events \
--lookup-attributes \
AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity \
--max-results 20Periksa waktu event, role ARN, identity provider, nama sesi, akun tujuan, dan event deployment berikutnya. Nama sesi yang menyertakan github.run_id memudahkan korelasi dengan eksekusi GitHub Actions. Event history dapat memerlukan waktu sebelum muncul; untuk pencarian jangka panjang dan lintas akun, gunakan CloudTrail trail atau event data store yang dikirim ke penyimpanan terpusat.
CloudTrail juga membantu membedakan dua kelas kegagalan:
- Gagal mengambil role: periksa event
AssumeRoleWithWebIdentity, provider, audience, subject, dan trust policy. - Role berhasil diperoleh tetapi deployment ditolak: periksa event API layanan tujuan, permissions policy, resource policy, KMS key policy, permission boundary, atau SCP.
Masalah umum dan cara memperbaikinya
AccessDenied saat AssumeRoleWithWebIdentity
- Pastikan ARN pada
role-to-assumemenunjuk ke akun dan role yang benar. - Pastikan provider
token.actions.githubusercontent.comada di akun tempat role berada. - Periksa bahwa audience provider dan condition
audbernilaists.amazonaws.com. - Bandingkan claim
subaktual dengan trust policy secara persis. - Pastikan principal federated pada trust policy menunjuk ke ARN OIDC provider yang benar.
- Periksa apakah permission boundary atau SCP membatasi penggunaan STS.
Subject tidak cocok
Penyebab paling umum adalah workflow menambahkan environment, sedangkan trust policy masih mengharapkan subject branch. Penyebab lain meliputi nama organisasi atau repository yang berbeda, branch selain main, tag yang tidak cocok dengan pola, atau perubahan nama Environment.
Jika perlu memeriksa token saat debugging, dekode hanya payload JWT di lingkungan yang terkendali dan jangan pernah mencetak token lengkap ke log. OIDC token adalah bearer token berumur pendek. Hapus langkah debugging setelah claim terverifikasi.
Unable to get ACTIONS_ID_TOKEN_REQUEST_URL
Biasanya job belum memiliki permissions: id-token: write. Pastikan permission ditempatkan pada workflow atau job yang menjalankan configure-aws-credentials. Jika permissions didefinisikan ulang pada level job, sertakan kembali id-token: write di level tersebut.
Role berhasil diperoleh, tetapi operasi AWS tetap ditolak
Ini bukan masalah OIDC. Baca nama action dan resource pada pesan AccessDenied, lalu periksa policy deployment role. Untuk S3, misalnya, ListBucket berlaku pada ARN bucket, sedangkan PutObject dan DeleteObject berlaku pada ARN objek dengan akhiran /*. Bucket policy atau KMS key policy juga dapat menolak operasi meskipun IAM role mengizinkannya.
Langkah migrasi dan pencabutan access key lama
- Inventarisasi kredensial lama. Catat IAM user, access key, repository, Environment, dan workflow yang masih menggunakannya.
- Buat OIDC provider dan role nonproduksi. Terapkan trust policy ketat dan permissions policy sesuai deployment nyata.
- Ubah workflow. Tambahkan
id-token: write, gunakanconfigure-aws-credentials, dan hapus referensi ke access key dari YAML. - Uji identitas dan deployment. Jalankan
get-caller-identity, verifikasi hasil deployment, lalu cocokkan sesi dengan CloudTrail. - Terapkan ke produksi. Gunakan role terpisah dan Environment yang dilindungi untuk deployment produksi.
- Hapus GitHub Secrets lama. Hapus access key dari level repository, Environment, dan organization jika tidak lagi digunakan workflow lain.
- Nonaktifkan access key di IAM. Nonaktifkan lebih dahulu untuk mendeteksi dependensi tersembunyi tanpa langsung menghilangkan opsi pemulihan.
- Pantau kegagalan. Periksa workflow, CloudTrail, dan sistem lain yang mungkin masih memakai key tersebut.
- Hapus access key dan IAM user. Setelah dipastikan tidak digunakan, hapus key, policy, dan IAM user khusus CI yang sudah tidak diperlukan.
Jangan mempertahankan access key lama sebagai cadangan tanpa batas waktu. Kredensial yang tetap aktif menghilangkan manfaat utama migrasi OIDC. Jika prosedur darurat diperlukan, dokumentasikan mekanisme akses sementara yang diaudit dan memiliki proses kedaluwarsa yang jelas.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!