Bỏ qua đến nội dung
DevOps Lab

GitHub Actions → AWS qua OIDC

Giải thích từng thành phần · Tại sao cần · Cách hoạt động — không cần lưu AWS access key trên GitHub.

Tại sao không dùng Access Key như cũ?

Tiêu chíStatic AWS Access KeyOIDC (không cần key)
Lưu secret ở đâuGitHub Secrets – tồn tại vĩnh viễnKhông cần lưu – tạo mới mỗi job
Rủi ro bị lộCao – key xài mãi nếu bị leakRất thấp – token hết hạn sau ~15 phút
Rotate credentialPhải làm thủ công định kỳTự động – mỗi job là 1 credential mới
Audit trailKhó truy vết ai, job nào xài keyCloudTrail ghi rõ: repo + branch + job

Các thành phần — chọn để xem chi tiết

▶ GitHub Actions Runner

Ai đang yêu cầu quyền?

Runner là môi trường thực thi workflow của bạn. Khi job bắt đầu, runner không có quyền AWS nào cả — nó chỉ có thể yêu cầu quyền thông qua OIDC.

Runner biết mình là gì: repo nào, branch nào, commit nào, job nào. Toàn bộ context này được đưa vào OIDC token để AWS có thể phán xét "cho phép hay không".

Kiến trúc tổng quan

GitHub Actions OIDC — kiến trúc tổng quanGITHUBGitHub Actions Runnerruns your workflow job▶ workflow.ymlOIDC Token (JWT)repo · branch · job · shaký bởi GitHub, hết hạn ~5mintạoAWSIAM Identity Providerxác thực OIDC tokenURL: token.actions.githubusercontent.comIAM Roletrust policy + permissionschỉ cho repo:org/repo:ref:refs/heads/*AWS STSAssumeRoleWithWebIdentitycấp temp credentials (~15min)AWS ResourcesS3 · ECR · EKS · …① gửi JWT token② trust OK③ assume role④ trả về temp creds (15min)⑤ gọi API với temp creds

Luồng hoạt động từng bước

Một lần duy nhất: cấu hình AWS phía trước

Bạn tạo IAM Identity Provider + IAM Role trên AWS. Đây là bước setup, không phải runtime.

# Terraform / AWS Console
resource "aws_iam_openid_connect_provider" "github" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}

resource "aws_iam_role" "github_actions" {
  name               = "github-actions-deploy"
  assume_role_policy = jsonencode({
    Statement = [{
      Effect    = "Allow"
      Principal = { Federated = aws_iam_openid_connect_provider.github.arn }
      Action    = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringLike = {
          # Chỉ cho phép repo cụ thể + branch main
          "token.actions.githubusercontent.com:sub":
            "repo:my-org/my-repo:ref:refs/heads/main"
        }
      }
    }]
  })
}
Tại sao Condition quan trọng? Nếu bỏ Condition, mọi repo trên GitHub đều có thể assume role này. StringLike với wildcard (*) cho phép bạn giới hạn theo org, repo, branch, hoặc tag.

Checklist setup nhanh

AWS (1 lần)
GitHub Workflow