Bảo mật Secrets trong GitHub Actions: Đừng để lộ API Key chỉ vì một phút hớ hênh

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

Cái giá nghìn đô của một phút “lỡ tay” commit API Key

Chỉ cần 60 giây sau khi bạn lỡ tay commit file .env lên GitHub, các bot quét mã độc đã có thể lấy được Access Key của bạn. Thực tế, không ít developer đã phải nhận hóa đơn AWS hàng nghìn USD chỉ sau một đêm vì lộ thông tin đăng nhập. Qua quá trình audit security cho hơn 10 hệ thống lớn, mình nhận thấy lỗ hổng phổ biến nhất không nằm ở code, mà ở cách quản lý thông tin nhạy cảm trong pipeline CI/CD.

Khi triển khai tự động, pipeline cần quyền truy cập vào server, Docker Hub hoặc Slack. Nhiều người chọn cách nhanh nhất là hardcode mật khẩu trực tiếp vào file YAML. Đây là một sai lầm chết người. Bất kỳ ai có quyền xem repo đều có thể đánh cắp các thông tin này và xâm nhập vào hệ thống của bạn.

GitHub Actions Secrets: Chiếc két sắt cho Pipeline

GitHub Actions Secrets là giải pháp lưu trữ thông tin nhạy cảm ngay trên repository dưới dạng mã hóa. Các giá trị này chỉ được giải mã khi workflow thực sự chạy.

Điểm cộng lớn nhất là tính ẩn danh tuyệt đối. Sau khi lưu Secret, bạn sẽ không bao giờ xem lại được giá trị gốc trên giao diện GitHub. Nếu bạn vô tình in (print) biến này ra log, hệ thống sẽ tự động che đi bằng dấu *** để bảo vệ dữ liệu.

Ba tầng quản lý Secrets bạn cần biết

  • Repository secrets: Có phạm vi sử dụng trong toàn bộ một dự án cụ thể.
  • Environment secrets: Dành riêng cho từng môi trường như Production hoặc Staging. Đây là cách tốt nhất để tách biệt API Key giữa môi trường test và môi trường thật.
  • Organization secrets: Giải pháp tối ưu cho doanh nghiệp để chia sẻ một Secret (như Docker Hub Token) cho hàng trăm repository cùng lúc.

Thực hành: Triển khai Secrets cho dự án Python

Hãy giả sử bạn có một script Python cần dùng OpenAI API để xử lý dữ liệu tự động mỗi khi push code lên nhánh main.

Bước 1: Thiết lập Secret trên GitHub

  1. Mở repository, chọn tab Settings.
  2. Tại menu bên trái, tìm Secrets and variables -> Actions.
  3. Nhấn New repository secret.
  4. Đặt tên là OPENAI_API_KEY và dán giá trị key vào.
  5. Lưu lại bằng nút Add secret.

Bước 2: Gọi Secret trong file cấu hình YAML

Thay vì viết đè key vào code, chúng ta sẽ truyền nó qua biến môi trường trong file .github/workflows/main.yml.

name: AI Data Processing
on:
  push:
    branches: [ "main" ]

jobs:
  run-script:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install openai

      - name: Run processing script
        env:
          # Ánh xạ Secret từ GitHub vào biến môi trường của máy ảo
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: python process_data.py

Bước 3: Truy xuất giá trị trong mã nguồn

Sử dụng thư viện os để đọc biến môi trường. Cách này giúp code của bạn sạch sẽ và an toàn.

import os
from openai import OpenAI

# Lấy key từ môi trường hệ thống
api_key = os.getenv("OPENAI_API_KEY")

if not api_key:
    raise ValueError("Lỗi: Thiếu API Key trong cấu hình Secrets!")

client = OpenAI(api_key=api_key)
print("Kết nối API thành công...")

Kinh nghiệm thực chiến để tránh rò rỉ dữ liệu

Công cụ tốt là chưa đủ, bạn cần một quy trình làm việc chuẩn để tránh các lỗi ngớ ngẩn sau đây.

1. Đừng cố tình “lách” cơ chế che giấu của GitHub

Tính năng masking của GitHub không phải vạn năng. Nếu bạn encode Secret sang Base64 hoặc đảo ngược chuỗi trước khi in ra log để debug, GitHub sẽ không nhận diện được để che đi. Khi đó, Secret của bạn sẽ hiển thị rõ ràng cho bất kỳ ai có quyền đọc log.

2. Cảnh giác với Pull Requests từ bên ngoài

Mặc định, GitHub không truyền Secret vào workflow khi có ai đó fork repo của bạn và tạo PR. Tuy nhiên, nếu bạn đổi cấu hình sang pull_request_target, hãy cực kỳ cẩn thận. Một kẻ tấn công có thể sửa code trong PR để gửi Secret về server của họ ngay khi workflow chạy.

3. Áp dụng nguyên tắc Đặc quyền tối thiểu

Đừng bao giờ dùng một Token có quyền Admin cho những tác vụ nhỏ. Nếu pipeline chỉ cần upload ảnh lên S3, hãy tạo một IAM User chỉ có quyền s3:PutObject. Nếu key bị lộ, thiệt hại sẽ được giới hạn ở mức thấp nhất.

4. Xoay vòng (Rotate) Secrets định kỳ

Mọi thông tin đều có hạn sử dụng. Hãy đặt lịch thay mới API Key mỗi 90 ngày. Việc này đảm bảo rằng nếu một key cũ vô tình bị lộ trước đó, nó cũng không còn giá trị để hacker khai thác.

Nâng cao: Kiểm soát chặt chẽ với Environment Secrets

Với các dự án lớn, việc deploy lên Production cần được kiểm soát gắt gao hơn. Bạn nên sử dụng tính năng Environments để gán Secret riêng cho từng môi trường.

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy to Server
        env:
          SSH_KEY: ${{ secrets.SSH_KEY }}
        run: ./deploy.sh

Khi cấu hình như vậy, bạn có thể bật thêm tính năng Required reviewers. Workflow sẽ tạm dừng và chỉ tiếp tục truy cập vào Secret khi có leader nhấn nút Approve xác nhận.

Lời kết

Bảo mật CI/CD là một cuộc chiến bền bỉ, không phải việc làm một lần là xong. Quản lý Secrets đúng cách trên GitHub Actions là bước đi cơ bản nhưng quan trọng nhất để bảo vệ uy tín và tài sản của bạn. Hãy dành 5 phút rà soát lại các repository ngay hôm nay: xóa bỏ mọi key đang hardcode và đưa chúng vào “két sắt” an toàn.

Share: