Cấu hình Cosign sử dụng Sigstore Fulcio và Rekor
Bước đầu tiên là cấu hình Cosign để sử dụng dịch vụ Sigstore Fulcio làm CA (Certificate Authority) và Rekor làm log công khai. Cách này loại bỏ hoàn toàn nhu cầu quản lý private key, vì Cosign sẽ tạo key ephemeral (tạm thời) cho mỗi lần ký, lấy chứng chỉ từ Fulcio và ghi log chữ ký vào Rekor.
Chúng ta sẽ thiết lập biến môi trường để Cosign biết địa chỉ endpoint của Fulcio và Rekor. Trong môi trường production, bạn nên dùng endpoint public của Sigstore. Trong môi trường dev, bạn có thể dùng endpoint nội bộ đã triển khai ở Phần 2.
Thực thi lệnh để xuất biến môi trường:
export COSIGN_EXPERIMENTAL=1
export SIGSTORE_FULCIO_URL="https://fulcio.sigstore.dev"
export SIGSTORE_REKOR_URL="https://rekor.sigstore.dev"
Kết quả mong đợi: Không có lỗi output, terminal sẵn sàng nhận lệnh Cosign. Biến COSIGN_EXPERIMENTAL=1 được bật để hỗ trợ các tính năng mới như ký dựa trên chứng chỉ (certificate-based signing).
Xác thực và lấy chứng chỉ từ Fulcio
Trước khi ký, Cosign cần xác thực danh tính của người ký (signer) thông qua OIDC (OpenID Connect) với một provider như GitHub, Google, hoặc GitLab. Cosign sẽ dùng token này để yêu cầu Fulcio cấp chứng chỉ số.
Thực hiện lệnh xác thực (thay thế your-github-username bằng username GitHub của bạn):
cosign login --keyless --identity-provider https://token.actions.githubusercontent.com
Kết quả mong đợi: Terminal sẽ mở trình duyệt hoặc yêu cầu bạn nhập token. Sau khi nhập thành công, bạn sẽ thấy thông báo: Login Succeeded!. Lúc này, Cosign đã có token OIDC hợp lệ để trao đổi với Fulcio.
Ký image Docker
Sau khi đăng nhập, chúng ta tiến hành ký một image Docker cụ thể. Giả sử image cần ký là nginx:latest. Lệnh ký sẽ thực hiện quá trình: tạo keypair tạm thời -> hash image -> ký hash -> gửi lên Fulcio để cấp cert -> gửi cert và chữ ký lên Rekor.
Thực thi lệnh ký image (bắt buộc phải có cờ --keyless và --oidc-client-id):
cosign sign --keyless --oidc-client-id your-github-username@github.com:signing --yes nginx:latest
Lưu ý: Nếu bạn đang chạy trong CI/CD (GitHub Actions), biến OIDC_IDENTITY sẽ tự động được set, bạn có thể bỏ qua phần --oidc-client-id và --identity nếu môi trường đã cấu hình đúng.
Kết quả mong đợi: Terminal in ra dòng Successfully signed kèm theo digest của image (ví dụ: sha256:abc123...). Đồng thời, bạn có thể thấy thông báo Successfully pushed to Rekor.
Triển khai Cosign trong quy trình CI/CD
Để tự động hóa việc ký image trong pipeline CI/CD (ví dụ GitHub Actions), chúng ta cần cấu hình workflow để Cosign chạy tự động sau bước build image. Điều này đảm bảo mọi image được push lên registry đều đã được ký xác thực.
Cấu hình GitHub Actions Workflow
Tạo file workflow để build image, đẩy lên registry (như Docker Hub hoặc GHCR), và sau đó gọi Cosign để ký. Chúng ta sử dụng action sigstore/cosign-action để đơn giản hóa quy trình, hoặc dùng lệnh cosign trực tiếp nếu cần tùy biến cao.
Tạo file .github/workflows/cosign-sign.yml với nội dung hoàn chỉnh:
name: Cosign Sign
on:
push:
branches:
- main
jobs:
build-and-sign:
runs-on: ubuntu-latest
permissions:
id-token: write # Bắt buộc để lấy OIDC token từ GitHub
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: your-docker-username/your-image:latest
- name: Install Cosign
uses: sigstore/cosign-installer@v3.4.0
- name: Sign the image
run: |
cosign sign --keyless --yes \
--identity "your-github-username@github.com:signing" \
your-docker-username/your-image:latest
Trong file trên, permissions: id-token: write là cực kỳ quan trọng. Nếu thiếu dòng này, GitHub sẽ không cấp token OIDC, và lệnh cosign sign sẽ bị lỗi failed to get identity token.
Kết quả mong đợi: Khi code được push vào nhánh main, GitHub Actions sẽ tự động chạy workflow. Log của bước "Sign the image" sẽ hiển thị thành công và đẩy chữ ký lên Rekor công cộng.
Kiểm tra chữ ký và tính toàn vẹn
Sau khi image đã được ký, bước quan trọng nhất là xác minh (verify) chữ ký trước khi deploy. Lệnh verify của Cosign sẽ thực hiện 3 việc: tải chữ ký từ registry -> tải chứng chỉ từ Rekor -> kiểm tra tính toàn vẹn của image và xác thực chữ ký dựa trên danh tính người ký.
Xác minh chữ ký cơ bản
Để kiểm tra nhanh xem image đã được ký hợp lệ hay chưa, ta sử dụng lệnh cosign verify với chế độ keyless.
Thực thi lệnh kiểm tra (thay thế image tag bằng image đã ký ở trên):
cosign verify --keyless --certificate-identity-regexp ".*" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" your-docker-username/your-image:latest
Trong đó:
- --keyless: Chỉ định sử dụng chứng chỉ công khai thay vì public key file.
- --certificate-identity-regexp: Regex để khớp với danh tính người ký (ở đây là
.* để chấp nhận mọi người ký, trong production nên đặt cụ thể).
- --certificate-oidc-issuer: Địa chỉ của OIDC provider (GitHub trong trường hợp này) để xác minh chứng chỉ.
Kết quả mong đợi: Nếu image hợp lệ, terminal sẽ in ra một JSON chứa thông tin chứng chỉ, bao gồm Issuer, Subject và NotBefore/NotAfter. Nếu image bị giả mạo hoặc chưa được ký, Cosign sẽ trả về lỗi verification failed hoặc no signatures found.
Xác minh với danh tính cụ thể
Trong môi trường production, bạn không nên dùng regex .* vì nó chấp nhận bất kỳ ai cũng ký. Thay vào đó, hãy chỉ định chính xác identity của CI/CD hoặc người phát triển.
Thực thi lệnh xác minh chặt chẽ (chỉ chấp nhận image do pipeline GitHub Actions ký):
cosign verify --keyless --certificate-identity "your-github-username@github.com:signing" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" your-docker-username/your-image:latest
Kết quả mong đợi: Lệnh sẽ chỉ thành công nếu chữ ký trong image khớp chính xác với danh tính your-github-username@github.com:signing. Nếu bạn cố gắng chạy lệnh này với một image được ký bởi một tài khoản khác, Cosign sẽ báo lỗi failed to verify signature.
Kiểm tra log chữ ký trên Rekor
Để xác minh tính không thể chối bỏ (non-repudiation), bạn có thể kiểm tra trực tiếp trên log công khai Rekor. Điều này chứng minh rằng chữ ký đã được ghi lại tại một thời điểm cụ thể và không thể bị thay đổi sau đó.
Sử dụng lệnh cosign attestation inspect hoặc truy cập trực tiếp API Rekor. Tuy nhiên, cách nhanh nhất là dùng lệnh cosign verify-attestation nếu có attestation, hoặc đơn giản là check signature đã tồn tại trong Rekor:
curl -s https://rekor.sigstore.dev/api/v1/log/entries?hash=$(echo -n "sha256:$(cosign digest your-docker-username/your-image:latest | cut -d' ' -f2)" | sha256sum | cut -d' ' -f1) | jq '.entries[]'
Lưu ý: Lệnh trên là ví dụ minh họa cách tra cứu. Trong thực tế, lệnh cosign verify đã tự động thực hiện bước này bên trong. Nếu bạn muốn xem chi tiết chứng chỉ đã được lưu trên Rekor, hãy dùng:
cosign verify --keyless --output public-key your-docker-username/your-image:latest > public-key.pem
Kết quả mong đợi: Bạn sẽ nhận được file public-key.pem chứa chứng chỉ công khai đã được sử dụng để ký image, xác nhận rằng chữ ký này có nguồn gốc từ Fulcio và đã được ghi nhận trong Rekor.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Secure Software Supply Chain với Sigstore, Cosign, Tekton và OPA Gatekeeper trên Kubernetes để đảm bảo an toàn vòng đời phần mềm
« Phần 2: Xây dựng hạ tầng bảo mật nền tảng với Sigstore và Fulcio
Phần 4: Tự động hóa quy trình ký image với Tekton Pipeline »