1. Giới thiệu
Container Analysis cung cấp tính năng quét lỗ hổng bảo mật và lưu trữ siêu dữ liệu cho các vùng chứa. Dịch vụ quét thực hiện quét lỗ hổng bảo mật trên hình ảnh trong Artifact Registry và Container Registry, sau đó lưu trữ siêu dữ liệu thu được và cung cấp để sử dụng thông qua một API. Bộ nhớ siêu dữ liệu cho phép bạn lưu trữ thông tin từ nhiều nguồn, bao gồm cả tính năng quét lỗ hổng bảo mật, các dịch vụ của Google Cloud và nhà cung cấp bên thứ ba.
Bạn có thể quét lỗ hổng bảo mật tự động hoặc theo yêu cầu:
- Khi bạn bật tính năng quét tự động, quá trình quét sẽ tự động kích hoạt mỗi khi bạn chuyển một hình ảnh mới sang Artifact Registry hoặc Container Registry. Thông tin về lỗ hổng bảo mật được cập nhật liên tục khi phát hiện thấy lỗ hổng bảo mật mới.
- Khi bật tính năng Quét theo yêu cầu, bạn phải chạy một lệnh để quét hình ảnh cục bộ hoặc hình ảnh trong Artifact Registry hoặc Container Registry. Tính năng Quét theo yêu cầu giúp bạn linh hoạt hơn về thời điểm quét các vùng chứa. Ví dụ: bạn có thể quét một hình ảnh được tạo cục bộ và khắc phục các lỗ hổng trước khi lưu trữ hình ảnh đó trong một sổ đăng ký. Kết quả quét có hiệu lực trong tối đa 48 giờ sau khi quá trình quét hoàn tất và thông tin về lỗ hổng bảo mật sẽ không được cập nhật sau khi quét.
Khi tích hợp Container Analysis vào quy trình CI/CD, bạn có thể đưa ra quyết định dựa trên siêu dữ liệu đó. Ví dụ: bạn có thể sử dụng Uỷ quyền nhị phân để tạo các chính sách triển khai chỉ cho phép triển khai cho những hình ảnh tuân thủ từ các sổ đăng ký đáng tin cậy.
Kiến thức bạn sẽ học được
- Cách bật tính năng tự động quét
- Cách thực hiện quét theo yêu cầu
- Cách tích hợp tính năng quét vào quy trình tạo
- Cách ký hình ảnh đã được phê duyệt
- Cách sử dụng bộ điều khiển truy cập GKE để chặn hình ảnh
- Cách định cấu hình GKE để chỉ cho phép các hình ảnh đã ký được phê duyệt
2. Thiết lập và yêu cầu
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



- Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn có thể cập nhật thông tin này bất cứ lúc nào.
- Mã dự án là giá trị duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là
PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có dùng được hay không. Bạn không thể thay đổi thông tin này sau bước này và thông tin này sẽ giữ nguyên trong suốt thời gian diễn ra dự án. - Để bạn biết, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên Cloud. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh phát sinh phí thanh toán ngoài hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá toàn bộ dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.
Khởi động Trình chỉnh sửa Cloud Shell
Phòng thí nghiệm này được thiết kế và kiểm thử để sử dụng với Trình chỉnh sửa Google Cloud Shell. Để truy cập vào trình chỉnh sửa,
- truy cập vào dự án của bạn trên Google tại https://console.cloud.google.com.
- Ở góc trên cùng bên phải, hãy nhấp vào biểu tượng trình chỉnh sửa Cloud Shell

- Một ngăn mới sẽ mở ra ở cuối cửa sổ
Thiết lập môi trường
Trong Cloud Shell, hãy đặt mã dự án và số dự án cho dự án của bạn. Lưu các giá trị này dưới dạng biến PROJECT_ID và PROJECT_ID.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
Bật các dịch vụ
Bật tất cả các dịch vụ cần thiết:
gcloud services enable \
cloudkms.googleapis.com \
cloudbuild.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
artifactregistry.googleapis.com \
containerscanning.googleapis.com \
ondemandscanning.googleapis.com \
binaryauthorization.googleapis.com
Tạo kho lưu trữ Artifact Registry
Trong phòng thí nghiệm này, bạn sẽ sử dụng Artifact Registry để lưu trữ và quét hình ảnh. Tạo kho lưu trữ bằng lệnh sau.
gcloud artifacts repositories create artifact-scanning-repo \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository"
Định cấu hình Docker để sử dụng thông tin đăng nhập gcloud khi truy cập vào Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Quét tự động
Tính năng quét cấu phần phần mềm sẽ tự động kích hoạt mỗi khi bạn chuyển một hình ảnh mới sang Artifact Registry hoặc Container Registry. Thông tin về lỗ hổng bảo mật được cập nhật liên tục khi phát hiện thấy lỗ hổng bảo mật mới. Trong phần này, bạn sẽ đẩy một hình ảnh vào Artifact Registry và khám phá kết quả.
Tạo và thay đổi thành thư mục công việc
mkdir vuln-scan && cd vuln-scan
Xác định hình ảnh mẫu
Tạo một tệp có tên là Dockerfile với nội dung sau.
cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a
# System
RUN apt update && apt install python3-pip -y
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
EOF
Tạo một tệp có tên là main.py với nội dung sau
cat > ./main.py << EOF
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
name = os.environ.get("NAME", "Worlds")
return "Hello {}!".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
Tạo và đẩy hình ảnh lên AR
Sử dụng Cloud Build để tạo và tự động chuyển vùng chứa của bạn sang Artifact Registry. Hãy lưu ý thẻ bad trên hình ảnh. Điều này sẽ giúp bạn xác định được vị trí của nút cho các bước sau.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Xem thông tin chi tiết về hình ảnh
Sau khi quy trình xây dựng hoàn tất, hãy xem xét hình ảnh và kết quả về lỗ hổng bảo mật trong trang tổng quan Artifact Registry.
- Mở Artifact Registry trong Cloud Console
- Nhấp vào artifact-scanning-repo để xem nội dung
- Nhấp vào phần chi tiết hình ảnh
- Nhấp vào bản tóm tắt mới nhất về hình ảnh của bạn
- Sau khi quét xong, hãy nhấp vào thẻ lỗ hổng bảo mật cho hình ảnh
Trong thẻ lỗ hổng bảo mật, bạn sẽ thấy kết quả quét tự động cho hình ảnh mà bạn vừa tạo.

Tính năng tự động hoá quy trình quét được bật theo mặc định. Khám phá phần Cài đặt Artifact Registry để xem cách bạn có thể tắt/bật tính năng tự động quét.
4. Quét theo yêu cầu
Có nhiều trường hợp bạn có thể cần chạy quy trình quét trước khi đẩy hình ảnh vào một kho lưu trữ. Ví dụ: nhà phát triển vùng chứa có thể quét một hình ảnh và khắc phục các vấn đề trước khi đẩy mã vào tính năng kiểm soát nguồn. Trong ví dụ bên dưới, bạn sẽ tạo và phân tích hình ảnh cục bộ trước khi thực hiện hành động dựa trên kết quả.
Tạo hình ảnh
Trong bước này, bạn sẽ dùng docker cục bộ để tạo hình ảnh cho bộ nhớ đệm cục bộ.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Quét hình ảnh
Sau khi tạo hình ảnh, hãy yêu cầu quét hình ảnh đó. Kết quả quét được lưu trữ trong một máy chủ siêu dữ liệu. Công việc hoàn tất với vị trí của kết quả trong máy chủ siêu dữ liệu.
gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--format="value(response.scan)" > scan_id.txt
Xem tệp đầu ra
Dành chút thời gian để xem xét đầu ra của bước trước được lưu trữ trong tệp scan_id.txt. Lưu ý vị trí báo cáo của kết quả quét trong máy chủ siêu dữ liệu.
cat scan_id.txt
Xem kết quả quét chi tiết
Để xem kết quả thực tế của quá trình quét, hãy dùng lệnh list-vulnerabilities tại vị trí báo cáo được ghi trong tệp đầu ra.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
Kết quả đầu ra chứa một lượng đáng kể dữ liệu về tất cả các lỗ hổng trong hình ảnh.
Gắn cờ vấn đề nghiêm trọng
Con người hiếm khi sử dụng trực tiếp dữ liệu được lưu trữ trong báo cáo. Thông thường, kết quả được dùng trong một quy trình tự động. Sử dụng các lệnh bên dưới để đọc thông tin chi tiết về báo cáo và ghi nhật ký nếu tìm thấy lỗ hổng BẢO MẬT NGHIÊM TRỌNG
export SEVERITY=CRITICAL
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi
Kết quả của lệnh này sẽ là
Failed vulnerability check for CRITICAL level
5. Quét quy trình tạo
Trong phần này, bạn sẽ tạo một quy trình tạo tự động để tạo hình ảnh vùng chứa, quét hình ảnh đó rồi đánh giá kết quả. Nếu không tìm thấy lỗ hổng NGHIÊM TRỌNG, thì công cụ này sẽ đẩy hình ảnh vào kho lưu trữ. Nếu phát hiện thấy các lỗ hổng NGHIÊM TRỌNG, bản dựng sẽ không thành công và thoát.
Cấp quyền truy cập cho Tài khoản dịch vụ Cloud Build
Cloud Build sẽ cần có quyền truy cập vào API quét theo yêu cầu. Cấp quyền truy cập bằng các lệnh sau.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/ondemandscanning.admin"
Tạo quy trình Cloud Build
Lệnh sau đây sẽ tạo một tệp cloudbuild.yaml trong thư mục của bạn. Tệp này sẽ được dùng cho quy trình tự động. Đối với ví dụ này, các bước chỉ giới hạn ở quy trình xây dựng vùng chứa. Tuy nhiên, trong thực tế, bạn sẽ thêm các hướng dẫn và kiểm thử dành riêng cho ứng dụng ngoài các bước của vùng chứa.
Tạo tệp bằng lệnh sau.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF
Chạy quy trình CI
Gửi bản dựng để xử lý nhằm xác minh bản dựng bị lỗi khi phát hiện thấy một lỗ hổng có mức độ nghiêm trọng là CRITICAL.
gcloud builds submit
Xem lại lỗi khi tạo
Bản dựng mà bạn vừa gửi sẽ không thành công vì hình ảnh chứa các lỗ hổng NGHIÊM TRỌNG.
Xem lại lỗi bản dựng trên trang Nhật ký Cloud Build
Khắc phục lỗ hổng
Cập nhật Dockerfile để sử dụng một hình ảnh cơ sở không chứa các lỗ hổng NGHIÊM TRỌNG.
Ghi đè Dockerfile để dùng hình ảnh Debian 10 bằng lệnh sau
cat > ./Dockerfile << EOF
from python:3.8-slim
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==2.1.0
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app
EOF
Chạy quy trình CI với hình ảnh phù hợp
Gửi bản dựng để xử lý nhằm xác minh rằng bản dựng sẽ thành công khi không tìm thấy lỗ hổng bảo mật nào ở mức NGHIÊM TRỌNG.
gcloud builds submit
Xem lại kết quả của bản dựng
Bản dựng bạn vừa gửi sẽ thành công vì hình ảnh đã cập nhật không chứa lỗ hổng NGHIÊM TRỌNG.
Xem lại trạng thái thành công của bản dựng trên trang Nhật ký Cloud Build
Xem kết quả quét
Xem lại hình ảnh hợp lệ trong Artifact Registry
- Mở Artifact Registry trong Cloud Console
- Nhấp vào artifact-scanning-repo để xem nội dung
- Nhấp vào phần chi tiết hình ảnh
- Nhấp vào bản tóm tắt mới nhất về hình ảnh của bạn
- Nhấp vào thẻ lỗ hổng bảo mật cho hình ảnh
6. Ký hình ảnh
Tạo Ghi chú của người chứng thực
Attestor Note (Ghi chú của người chứng thực) chỉ là một phần nhỏ dữ liệu đóng vai trò là nhãn cho loại chữ ký đang được áp dụng. Ví dụ: một ghi chú có thể cho biết thông tin quét lỗ hổng bảo mật, trong khi một ghi chú khác có thể được dùng để phê duyệt QA. Ghi chú sẽ được tham chiếu trong quá trình ký.
Tạo ghi chú
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Lưu trữ ghi chú
NOTE_ID=vulnz_note
curl -vvv -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./vulnz_note.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
Xác minh ghi chú
curl -vvv \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
Tạo một Attestor
Các chứng thực viên được dùng để thực hiện quy trình ký hình ảnh thực tế và sẽ đính kèm một lần xuất hiện của ghi chú vào hình ảnh để xác minh sau này. Tạo người chứng thực để sử dụng sau này.
Tạo Attestor
ATTESTOR_ID=vulnz-attestor
gcloud container binauthz attestors create $ATTESTOR_ID \
--attestation-authority-note=$NOTE_ID \
--attestation-authority-note-project=${PROJECT_ID}
Xác minh Attestor
gcloud container binauthz attestors list
Lưu ý rằng dòng cuối cùng cho biết NUM_PUBLIC_KEYS: 0 bạn sẽ cung cấp các khoá ở bước sau
Ngoài ra, hãy lưu ý rằng Cloud Build sẽ tự động tạo chứng thực viên built-by-cloud-build trong dự án của bạn khi bạn chạy một bản dựng tạo ra hình ảnh. Vì vậy, lệnh trên sẽ trả về 2 chứng thực viên, vulnz-attestor và built-by-cloud-build. Sau khi tạo thành công các hình ảnh, Cloud Build sẽ tự động ký và tạo chứng thực cho các hình ảnh đó.
Thêm vai trò IAM
Tài khoản dịch vụ Uỷ quyền nhị phân sẽ cần có quyền xem các ghi chú chứng thực. Cung cấp quyền truy cập bằng lệnh gọi API sau
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
cat > ./iam_request.json << EOM
{
'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
'policy': {
'bindings': [
{
'role': 'roles/containeranalysis.notes.occurrences.viewer',
'members': [
'serviceAccount:${BINAUTHZ_SA_EMAIL}'
]
}
]
}
}
EOM
Sử dụng tệp này để tạo Chính sách IAM
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./iam_request.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"
Thêm khoá KMS
Attestor cần các khoá mật mã để đính kèm ghi chú và cung cấp chữ ký có thể xác minh. Trong bước này, bạn sẽ tạo và lưu trữ các khoá trong KMS để Cloud Build truy cập sau này.
Trước tiên, hãy thêm một số biến môi trường để mô tả khoá mới
KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1
Tạo một chuỗi khoá để lưu trữ một bộ khoá
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Tạo một cặp khoá ký bất đối xứng mới cho người chứng thực
gcloud kms keys create "${KEY_NAME}" \
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
--purpose asymmetric-signing \
--default-algorithm="ec-sign-p256-sha256"
Bạn sẽ thấy khoá của mình xuất hiện trên trang KMS của Google Cloud Console.
Giờ đây, hãy liên kết khoá với chứng thực viên thông qua lệnh gcloud binauthz:
gcloud beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
Nếu in lại danh sách các cơ quan, bạn sẽ thấy một khoá đã đăng ký:
gcloud container binauthz attestors list
Tạo Chứng thực đã ký
Đến đây, bạn đã thiết lập các tính năng cho phép bạn ký hình ảnh. Sử dụng Attestor mà bạn đã tạo trước đó để ký Hình ảnh vùng chứa mà bạn đang làm việc
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
--format='get(image_summary.digest)')
Giờ đây, bạn có thể dùng gcloud để tạo chứng thực. Lệnh này chỉ cần lấy thông tin chi tiết về khoá mà bạn muốn dùng để ký và hình ảnh vùng chứa cụ thể mà bạn muốn phê duyệt
gcloud beta container binauthz attestations sign-and-create \
--artifact-url="${CONTAINER_PATH}@${DIGEST}" \
--attestor="${ATTESTOR_ID}" \
--attestor-project="${PROJECT_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
Theo thuật ngữ Phân tích vùng chứa, thao tác này sẽ tạo một lần xuất hiện mới và đính kèm lần xuất hiện đó vào ghi chú của người chứng thực. Để đảm bảo mọi thứ hoạt động như dự kiến, bạn có thể liệt kê các chứng thực của mình
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. Ký bằng Cloud Build
Bạn đã bật tính năng Ký hình ảnh và dùng Attestor theo cách thủ công để ký hình ảnh mẫu. Trong thực tế, bạn sẽ muốn áp dụng Chứng thực trong các quy trình tự động như quy trình CI/CD.
Trong phần này, bạn sẽ định cấu hình Cloud Build để Chứng thực hình ảnh một cách tự động
Vai trò
Thêm vai trò Người xem chứng thực uỷ quyền nhị phân vào Tài khoản dịch vụ Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
Thêm vai trò Trình ký/Trình xác minh Cloud KMS CryptoKey vào Tài khoản dịch vụ Cloud Build (Ký dựa trên KMS):
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
Thêm vai trò Trình đính kèm ghi chú phân tích vùng chứa vào Tài khoản dịch vụ Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
Chuẩn bị bước tạo bản dựng tuỳ chỉnh của Cloud Build
Bạn sẽ sử dụng bước Bản dựng tuỳ chỉnh trong Cloud Build để đơn giản hoá quy trình chứng thực. Google cung cấp bước Bản dựng tuỳ chỉnh này, trong đó có các hàm trợ giúp để đơn giản hoá quy trình. Trước khi sử dụng, mã cho bước tạo tuỳ chỉnh phải được tạo thành một vùng chứa và được chuyển đến Cloud Build. Để thực hiện việc này, hãy chạy các lệnh sau:
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community
Thêm bước ký vào cloudbuild.yaml
Trong bước này, bạn sẽ thêm bước chứng thực vào quy trình Cloud Build mà bạn đã tạo trước đó.
- Xem lại bước mới mà bạn sẽ thêm.
Chỉ xem xét. Không sao chép
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
- Ghi đè tệp cloudbuild.yaml bằng quy trình hoàn chỉnh đã cập nhật.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF
Chạy bản dựng
gcloud builds submit
Xem bản dựng trong Nhật ký Cloud Build
Mở Cloud Console để xem trang Nhật ký Cloud Build, sau đó xem bản dựng mới nhất và quá trình thực thi thành công các bước của bản dựng.
8. Chính sách kiểm soát quyền truy cập
Uỷ quyền nhị phân là một tính năng trong GKE và Cloud Run, cho phép xác thực các quy tắc trước khi một hình ảnh vùng chứa được phép chạy. Quy trình xác thực sẽ thực thi trên mọi yêu cầu chạy hình ảnh, cho dù đó là từ một quy trình CI/CD đáng tin cậy hay người dùng đang cố gắng triển khai hình ảnh theo cách thủ công. Khả năng này giúp bạn bảo mật môi trường thời gian chạy hiệu quả hơn so với chỉ kiểm tra quy trình CI/CD.
Để hiểu rõ khả năng này, bạn sẽ sửa đổi chính sách mặc định của GKE để thực thi một quy tắc uỷ quyền nghiêm ngặt.
Tạo cụm GKE
Tạo cụm GKE:
gcloud beta container clusters create binauthz \
--zone us-central1-a \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
Cho phép Cloud Build triển khai vào cụm này:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/container.developer"
Chính sách cho phép tất cả
Trước tiên, hãy xác minh trạng thái chính sách mặc định và khả năng triển khai mọi hình ảnh
- Xem lại chính sách hiện hành
gcloud container binauthz policy export
- Lưu ý rằng chính sách thực thi được đặt thành
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- Triển khai Mẫu để xác minh rằng bạn có thể triển khai mọi thứ
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Xác minh rằng quá trình triển khai đã diễn ra thành công
kubectl get pods
Bạn sẽ thấy kết quả sau

- Xoá loại hình triển khai
kubectl delete pod hello-server
Chính sách từ chối tất cả
Bây giờ, hãy cập nhật chính sách để không cho phép tất cả hình ảnh.
- Xuất chính sách hiện tại sang một tệp có thể chỉnh sửa
gcloud container binauthz policy export > policy.yaml
- Thay đổi chính sách
Trong trình chỉnh sửa văn bản, hãy thay đổi evaluationMode từ ALWAYS_ALLOW thành ALWAYS_DENY.
edit policy.yaml
Tệp YAML chính sách sẽ có dạng như sau:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Mở Terminal, áp dụng chính sách mới và đợi vài giây để thay đổi có hiệu lực
gcloud container binauthz policy import policy.yaml
- Thử triển khai khối lượng công việc mẫu
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Quá trình triển khai không thành công và thông báo sau đây sẽ xuất hiện
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule
Huỷ bỏ chính sách để cho phép tất cả
Trước khi chuyển sang phần tiếp theo, hãy nhớ hủy bỏ các thay đổi về chính sách
- Thay đổi chính sách
Trong trình chỉnh sửa văn bản, hãy thay đổi evaluationMode từ ALWAYS_DENY thành ALWAYS_ALLOW.
edit policy.yaml
Tệp YAML chính sách sẽ có dạng như sau:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Áp dụng chính sách đã được khôi phục
gcloud container binauthz policy import policy.yaml
9. Chặn các lỗ hổng bảo mật trong GKE
Trong phần này, bạn sẽ kết hợp những gì đã học được cho đến nay bằng cách triển khai một quy trình CI/CD với Cloud Build để quét hình ảnh, sau đó kiểm tra các lỗ hổng trước khi ký hình ảnh và cố gắng triển khai. GKE sẽ sử dụng Uỷ quyền nhị phân để xác thực rằng hình ảnh có chữ ký từ tính năng Quét lỗ hổng bảo mật trước khi cho phép hình ảnh chạy.

Cập nhật Chính sách GKE để yêu cầu chứng thực
Yêu cầu Attestor ký hình ảnh bằng cách thêm clusterAdmissionRules vào Chính sách BinAuth của GKE
Ghi đè chính sách bằng cấu hình mới cập nhật bằng lệnh bên dưới.
COMPUTE_ZONE=us-central1-a
cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
${COMPUTE_ZONE}.binauthz:
evaluationMode: REQUIRE_ATTESTATION
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
requireAttestationsBy:
- projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM
Áp dụng chính sách
gcloud beta container binauthz policy import binauth_policy.yaml
Cố gắng triển khai hình ảnh chưa ký
Tạo một bộ mô tả triển khai cho ứng dụng mà bạn đã tạo trước đó bằng lệnh sau. Hình ảnh được dùng ở đây là hình ảnh bạn đã tạo trước đó, có chứa các lỗ hổng nghiêm trọng và KHÔNG chứa chứng thực đã ký.
Bộ điều khiển truy cập GKE cần biết chính xác hình ảnh sẽ được triển khai để xác thực chữ ký một cách nhất quán. Để thực hiện việc này, bạn cần sử dụng bản tóm tắt hình ảnh thay vì một thẻ đơn giản.
Lấy mã nhận dạng hình ảnh cho hình ảnh không hợp lệ
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
--format='get(image_summary.digest)')
Sử dụng nội dung tóm tắt trong cấu hình Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Cố gắng triển khai ứng dụng vào GKE
kubectl apply -f deploy.yaml
Xem xét tải trong bảng điều khiển và lưu ý lỗi cho biết việc triển khai đã bị từ chối:
No attestations found that were valid and signed by a key trusted by the attestor
Triển khai hình ảnh đã ký
Lấy mã nhận dạng hình ảnh cho hình ảnh không hợp lệ
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
--format='get(image_summary.digest)')
Sử dụng nội dung tóm tắt trong cấu hình Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Triển khai ứng dụng trên GKE
kubectl apply -f deploy.yaml
Xem tải trong bảng điều khiển và lưu ý việc triển khai thành công hình ảnh.
10. Xin chúc mừng!
Xin chúc mừng, bạn đã hoàn tất lớp học lập trình này!
Nội dung đã đề cập:
- Cách bật tính năng tự động quét
- Cách thực hiện quét theo yêu cầu
- Cách tích hợp tính năng quét vào quy trình tạo
- Cách ký hình ảnh đã được phê duyệt
- Cách sử dụng bộ điều khiển truy cập GKE để chặn hình ảnh
- Cách định cấu hình GKE để chỉ cho phép các hình ảnh đã ký được phê duyệt
Bước tiếp theo:
- Bảo mật việc triển khai hình ảnh cho Cloud Run và Google Kubernetes Engine | Tài liệu về Cloud Build
- Hướng dẫn nhanh: Định cấu hình chính sách Uỷ quyền nhị phân bằng GKE | Google Cloud
Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud của bạn cho các tài nguyên được dùng trong hướng dẫn này, hãy xoá dự án chứa các tài nguyên đó hoặc giữ lại dự án rồi xoá từng tài nguyên.
Xoá dự án
Cách dễ nhất để không bị tính phí là xoá dự án mà bạn đã tạo cho hướng dẫn này.