Bảo mật CI/CD: Loại bỏ Long-lived Secret bằng GitHub Actions OIDC

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Cơn ác mộng mang tên “Lộ Secret Key” trong CI/CD

Nhiều DevOps Engineer vẫn giữ thói quen tạo IAM User, cấp quyền Admin rồi dán thẳng cặp AWS_ACCESS_KEY_ID vào GitHub Secrets. Cách làm này giúp workflow chạy ngay lập tức nhưng lại đặt hệ thống vào tình thế cực kỳ nguy hiểm. Chỉ cần một phút sơ suất để lộ log hoặc mất quyền truy cập GitHub, toàn bộ hạ tầng Cloud của bạn sẽ nằm gọn trong tay kẻ xấu.

Thực tế đã có những công ty nhận hóa đơn AWS hàng chục nghìn USD chỉ sau một đêm. Hacker thường dùng các Key bị lộ để tạo hàng loạt instance EC2 p3.16xlarge đào tiền ảo. Thay vì dùng “chìa khóa vạn năng” cố định, OIDC (OpenID Connect) cho phép bạn xác thực với Cloud provider bằng niềm tin (trust relationship) mà không cần lưu bất kỳ mã bí mật nào.

Tại sao OIDC lại an toàn hơn cách truyền thống?

Cách cũ: Static Credentials

Bạn tạo một User, lấy Key và lưu vào GitHub. Phương pháp này đơn giản nhưng cực kỳ rủi ro.

  • Rủi ro: Key có thời hạn vĩnh viễn cho đến khi bạn chủ động xóa.
  • Quản lý: Việc xoay vòng (rotation) key thủ công rất mất thời gian và dễ gây gián đoạn hệ thống.

Cách hiện đại: OIDC (OpenID Connect)

GitHub Actions đóng vai trò là Identity Provider. Khi workflow bắt đầu, GitHub cấp một token tạm thời (short-lived token) có hiệu lực trong vài phút cho AWS hoặc GCP. Cloud provider sẽ đối chiếu token này và chỉ cho phép thực thi các lệnh trong phạm vi hẹp.

  • Lợi ích: Token tự hủy sau khi workflow kết thúc.
  • Kiểm soát: Bạn có thể giới hạn chính xác repo nào, branch nào mới được phép mượn quyền (Assume Role).

Lý do mình ưu tiên OIDC cho mọi dự án Production

Sự an tâm là giá trị lớn nhất. Bạn không còn phải lo lắng về việc vô tình in log chứa secret hay quên đổi mật khẩu định kỳ cho Service Account. Đối với các tác vụ quản trị thủ công cần mật khẩu siêu mạnh, mình thường dùng công cụ tạo mật khẩu tại toolcraft.app. Sau đó, mình cấu hình OIDC để CI/CD tự vận hành hoàn toàn tự động, loại bỏ hoàn toàn yếu tố con người khỏi quy trình quản lý key.

3 bước triển khai OIDC với AWS và GitHub Actions

Bước 1: Thiết lập Identity Provider trên AWS

Đầu tiên, bạn cần khai báo với AWS rằng GitHub là một nguồn xác thực đáng tin cậy. Hãy truy cập IAM Console -> Identity Providers -> Add provider.

  • Provider type: OpenID Connect
  • Provider URL: https://token.actions.githubusercontent.com
  • Audience: sts.amazonaws.com

Bước 2: Cấu hình IAM Role và Trust Policy

Đây là bước then chốt để bảo vệ tài nguyên. Bạn tạo một Role để GitHub Actions “mượn”. Đoạn Trust Policy dưới đây đảm bảo chỉ đúng repo của bạn mới có quyền sử dụng Role này:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
        },
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}

Đừng quên thay 123456789012 bằng Account ID thật và my-org/my-repo bằng thông tin repo của bạn.

Bước 3: Cập nhật Workflow YAML

Trong file workflow, bạn bắt buộc phải thêm quyền id-token: write. Nếu thiếu dòng này, GitHub sẽ không thể tạo token OIDC để gửi sang AWS.

permissions:
  id-token: write
  contents: read

jobs:
  Deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionRole
          aws-region: ap-southeast-1
      - run: aws s3 ls

Nguyên tắc bảo mật không thể bỏ qua

Dù OIDC rất mạnh mẽ, bạn vẫn cần tuân thủ nguyên tắc “Quyền tối thiểu” (Least Privilege). Tuyệt đối không gán AdministratorAccess cho Role CI/CD. Nếu chỉ deploy ứng dụng lên S3, hãy chỉ cấp quyền s3:PutObjects3:ListBucket.

Hãy thắt chặt điều kiện trong Trust Policy bằng cách chỉ định rõ branch. Ví dụ: repo:username/repo-name:ref:refs/heads/main. Điều này ngăn chặn việc ai đó tạo branch phụ để chạy workflow trái phép và can thiệp vào tài nguyên Cloud. Chúc các bạn xây dựng hệ thống CI/CD an toàn!

Share: