1. Giới thiệu
Công cụ Phân tích vùng chứa 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 sẽ quét lỗ hổng bảo mật trên hình ảnh trong Cấu phần phần mềm và Kho lưu trữ vùng chứa, sau đó lưu trữ siêu dữ liệu thu được và cung cấp siêu dữ liệu đó để sử dụng thông qua 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.
Quá trình quét lỗ hổng có thể diễn ra tự động hoặc theo yêu cầu:
- Khi bạn bật tính năng tự động quét, tính năng quét sẽ tự động kích hoạt mỗi khi bạn đẩy hình ảnh mới vào Kho lưu trữ cấu phần phần mềm hoặc Kho lưu trữ vùng chứa. Thông tin về lỗ hổng được cập nhật liên tục khi phát hiện lỗ hổng 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 Cấu phần phần mềm hoặc Kho lưu trữ vùng chứa. Tính năng Quét theo yêu cầu giúp bạn linh hoạt trong việc quét các vùng chứa. Ví dụ: bạn có thể qué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 hình ảnh đó vào sổ đăng ký. Bạn có thể xem kết quả quét 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 tính năng Uỷ quyền tệp nhị phân để tạo các chính sách triển khai chỉ cho phép triển khai các 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 tính năng Quét theo yêu cầu
- Cách tích hợp tính năng quét trong quy trình xây dựng
- Cách ký hình ảnh đã được phê duyệt
- Cách sử dụng trình điều khiển kiểm soát truy cập GKE để chặn hình ảnh
- Cách định cấu hình GKE để chỉ cho phép hình ảnh đã phê duyệt và được ký
2. Cách thiết lập và các 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ị cho người tham gia dự án này. Đây là một chuỗi ký tự không được API của Google 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à duy nhất trên tất cả các dự án Google Cloud và không thể thay đổi (không thể thay đổi 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ã được tạo, bạn có thể tạo một mã ngẫu nhiên khác. Ngoài ra, bạn có thể thử dùng tên của riêng mình để xem tên đó có được chấp nhận 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ẽ được giữ nguyên trong suốt thời gian diễn ra dự án. - Xin lưu ý rằng có một giá trị thứ ba là Mã dự án mà một số API sử dụng. Tìm hiểu thêm về cả ba 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 tham gia lớp học lập trình này sẽ không tốn kém nhiều chi phí, nếu có. Để tắt các tài nguyên để không bị tính phí sau khi hoàn tất 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í 300 USD.
Khởi động Trình chỉnh sửa Cloudshell
Lớp học này được thiết kế và kiểm thử để sử dụng với Trình chỉnh sửa Google Cloud Shell. Cách 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 shell trên đám mây
- 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 biến 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 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 lớp học này, bạn sẽ sử dụng Cấu phần phần mềm để 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 xác thực gcloud khi truy cập vào CSDL cấu phần phần mềm.
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 đẩy hình ảnh mới vào Cấu phần phần mềm đăng ký hoặc Kho lưu trữ vùng chứa. Thông tin về lỗ hổng được cập nhật liên tục khi phát hiện lỗ hổng mới. Trong phần này, bạn sẽ đẩy một hình ảnh vào Cấu phần phần mềm đăng ký 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 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 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 vào AR
Sử dụng Cloud Build để tạo và tự động đẩy vùng chứa của bạn vào Artifact Registry. Lưu ý thẻ bad
trên hình ảnh. Việc này sẽ giúp bạn xác định ứng dụng đó cho các bước sau.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Xem lại thông tin chi tiết về hình ảnh
Sau khi quá trình tạo bản dựng hoàn tất, hãy xem lại hình ảnh và kết quả về lỗ hổng trong trang tổng quan của CSDL cấu phần phần mềm.
- Mở Registry Artifact (Cơ sở lưu trữ cấu phần phần mềm) trong Cloud Console
- Nhấp vào kho lưu trữ quét cấu phần phần mềm để xem nội dung
- Nhấp vào thông tin chi tiết về 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ả của quá trình quét tự động cho hình ảnh mà bạn vừa tạo.
Tính năng tự động quét được bật theo mặc định. Khám phá phần Cài đặt kho lưu trữ cấu phần phần mềm để xem cách 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 kho lưu trữ. Ví dụ: nhà phát triển vùng chứa có thể quét hình ảnh và khắc phục vấn đề trước khi đẩy mã vào công cụ 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 trên máy trước khi xử lý kết quả.
Tạo hình ảnh
Ở bước này, bạn sẽ sử dụng docker cục bộ để tạo hình ảnh vào 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 hình ảnh được tạo, hãy yêu cầu quét hình ảnh. Kết quả quét được lưu trữ trong 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 lại tệp đầu ra
Hãy dành chút thời gian để xem lại kết quả 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 sử dụng lệnh list-vulnerabilities
trên vị trí báo cáo được ghi chú trong tệp đầu ra.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
Kết quả chứa một lượng lớn 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 trực tiếp sử dụng dữ liệu được lưu trữ trong báo cáo. Thông thường, kết quả sẽ được một quy trình tự động sử dụng. Sử dụng các lệnh dưới đây để đọc thông tin chi tiết về báo cáo và ghi lại nếu phát hiện thấy lỗ hổng CRITICAL
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 xây dựng
Trong phần này, bạn sẽ tạo một quy trình xây dựng 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 CRITICAL, công cụ này sẽ đẩy hình ảnh vào kho lưu trữ. Nếu phát hiện thấy lỗ hổng CRITICAL, 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 tạo 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 về 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 các điểm ngắt bản dựng khi phát hiện lỗ hổng có mức độ nghiêm trọng CRITICAL.
gcloud builds submit
Không vượt qua quy trình xem xét bản dựng
Bản dựng bạn vừa gửi sẽ không thành công vì hình ảnh chứa các lỗ hổng CRITICAL.
Xem lại lỗi bản dựng trong trang Nhật ký bản dựng trên Cloud Build
Khắc phục lỗ hổng
Cập nhật Dockerfile để sử dụng hình ảnh cơ sở không chứa các lỗ hổng CRITICAL.
Ghi đè Dockerfile để sử 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 bằng hình ảnh tốt
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 phát hiện thấy lỗ hổng có mức độ nghiêm trọng CRITICAL.
gcloud builds submit
Xem lại bản dựng thành cô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 CRITICAL.
Xem lại quá trình xây dựng thành công trên trang Nhật ký bản dựng trên đám mây
Xem lại kết quả quét
Xem lại hình ảnh tốt trong Cấu phần phần mềm đăng ký
- Mở Registry Artifact (Cơ sở lưu trữ cấu phần phần mềm) trong Cloud Console
- Nhấp vào kho lưu trữ quét cấu phần phần mềm để xem nội dung
- Nhấp vào thông tin chi tiết về 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 của hình ảnh
6. Ký hình ảnh
Tạo Ghi chú của người chứng thực
Ghi chú của người chứng thực chỉ là một lượng 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 việc quét lỗ hổng bảo mật, trong khi một ghi chú khác có thể được dùng để ký xác nhận chất lượng. 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 trình chứng thực
Trình chứng thực đượ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 trình chứng thực để sử dụng sau.
Tạo trình chứng thực
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 người chứng thực
gcloud container binauthz attestors list
Lưu ý dòng cuối cùng cho biết NUM_PUBLIC_KEYS: 0
mà bạn sẽ cung cấp khoá trong bước sau
Ngoài ra, xin lưu ý rằng Cloud Build sẽ tự động tạo trình chứng thực built-by-cloud-build
trong dự án của bạn khi bạn chạy một bản dựng tạo hình ảnh. Vì vậy, lệnh trên sẽ trả về hai trình chứng thực là vulnz-attestor
và built-by-cloud-build
. Sau khi tạo thành công 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 tệp nhị phân sẽ cần có quyền xem ghi chú chứng thực. 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
Bên xác thực cần có khoá mã hoá để đí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.
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 khoá để chứa một tập hợp 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 trình 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.
Bây giờ, hãy liên kết khoá với trình chứng thực 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á đã được đăng ký:
gcloud container binauthz attestors list
Tạo chứng thực đã ký
Tại thời điểm này, bạn đã định cấu hình các tính năng cho phép ký hình ảnh. Sử dụng Trình chứng thực 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)')
Bây giờ, bạn có thể sử dụng gcloud để tạo chứng thực. Lệnh này chỉ 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}"
Trong thuật ngữ của Container Analysis, 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ư mong đợi, 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à sử dụng Trình chứng thực theo cách thủ công để ký hình ảnh mẫu. Trong thực tế, bạn nên áp dụng Chứng thực trong các quy trình tự động, chẳng hạn như quy trình CI/CD.
Trong phần này, bạn sẽ định cấu hình Cloud Build để tự động Chứng thực hình ảnh
Vai trò
Thêm vai trò Người xem chứng thực uỷ quyền tệp 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ò Người ký/Người xác thực khoá mã hoá Cloud KMS 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ò Người đính kèm ghi chú Container Analysis 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 trên Google 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, bạn phải tạo mã cho bước tạo bản dựng tuỳ chỉnh vào một vùng chứa và đẩy vào 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 lại. 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 lại bản dựng trong phần Nhật ký Cloud Build
Mở Cloud Console đến trang Nhật ký bản dựng trên đám mây và xem lại bản dựng mới nhất đó cũng như quá trình thực thi thành công các bước tạo bản dựng.
8. Chính sách kiểm soát việc vào cổng
Uỷ quyền tệp 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 cho phép chạy hình ảnh vùng chứa. 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ừ 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. Tính năng này cho phép bạn bảo mật môi trường thời gian chạy hiệu quả hơn so với việc chỉ kiểm tra quy trình CI/CD.
Để hiểu được chức năng này, bạn sẽ sửa đổi chính sách GKE mặc định để 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 hình ảnh bất kỳ
- 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 quá trình triển khai đã hoạt độ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 của 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 và áp dụng chính sách mới, sau đó đợ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
- Không triển khai được kèm theo thông báo sau
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ớ huỷ 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 của 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 đã huỷ bỏ
gcloud container binauthz policy import policy.yaml
9. Chặn 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 quy trình CI/CD bằng Cloud Build để quét hình ảnh, sau đó kiểm tra lỗ hổng trước khi ký hình ảnh và thử triển khai. GKE sẽ sử dụng tính năng Uỷ quyền tệp nhị phân để xác thực hình ảnh có chữ ký từ quy trình 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 về GKE để yêu cầu chứng thực
Yêu cầu hình ảnh được chữ ký của Trình chứng thực 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 đã 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
Thử triển khai hình ảnh chưa ký
Tạo một nội dung 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 sử dụng ở đây là hình ảnh bạn đã tạo trướ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 cần 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 hàm băm hình ảnh thay vì một thẻ đơn giản.
Lấy thông tin tóm tắt 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 chuỗi đại diện 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 cho GKE
kubectl apply -f deploy.yaml
Xem lại mức 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 thông tin tóm tắt 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 chuỗi đại diện 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 lại mức tải trong bảng điều khiển và lưu ý việc triển khai hình ảnh thành công.
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ội dung chúng ta đã đề cập:
- Cách bật tính năng tự động quét
- Cách thực hiện tính năng Quét theo yêu cầu
- Cách tích hợp tính năng quét trong quy trình xây dựng
- Cách ký hình ảnh đã được phê duyệt
- Cách sử dụng trình điều khiển kiểm soát truy cập GKE để chặn hình ảnh
- Cách định cấu hình GKE để chỉ cho phép hình ảnh đã phê duyệt và được ký
Bước tiếp theo:
- Bảo mật các bản triển khai hình ảnh cho Cloud Run và Google Kubernetes Engine | Tài liệu về Cloud Build
- Bắt đầu nhanh: Định cấu hình chính sách Uỷ quyền tệp nhị phân bằng GKE | Google Cloud
Dọn dẹp
Để tránh bị tính phí cho tài khoản Google Cloud của bạn đối với các tài nguyên được sử 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 và xoá từng tài nguyên.
Xoá dự án
Cách dễ nhất để loại bỏ tính năng thanh toán là xoá dự án mà bạn đã tạo cho hướng dẫn này.