Bản dựng bảo mật & Triển khai bằng Cloud Build, Artifact Registry và GKE

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

  1. Đă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.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 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.
  1. 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:

  1. truy cập vào dự án của bạn trên Google tại https://console.cloud.google.com.
  2. Ở 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

8560cc8d45e8c112.png

  1. 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_IDPROJECT_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.

  1. Mở Registry Artifact (Cơ sở lưu trữ cấu phần phần mềm) trong Cloud Console
  2. Nhấp vào kho lưu trữ quét cấu phần phần mềm để xem nội dung
  3. Nhấp vào thông tin chi tiết về hình ảnh
  4. Nhấp vào bản tóm tắt mới nhất về hình ảnh của bạn
  5. 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.

361be7b3bf293fca.png

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ý

  1. Mở Registry Artifact (Cơ sở lưu trữ cấu phần phần mềm) trong Cloud Console
  2. Nhấp vào kho lưu trữ quét cấu phần phần mềm để xem nội dung
  3. Nhấp vào thông tin chi tiết về hình ảnh
  4. Nhấp vào bản tóm tắt mới nhất về hình ảnh của bạn
  5. 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-attestorbuilt-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 đó.

  1. 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'
  1. 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ỳ

  1. Xem lại chính sách hiện hành
gcloud container binauthz policy export
  1. Lưu ý rằng chính sách thực thi được đặt thành ALWAYS_ALLOW

evaluationMode: ALWAYS_ALLOW

  1. 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
  1. Xác minh quá trình triển khai đã hoạt động
kubectl get pods

Bạn sẽ thấy kết quả sau

161db370d99ffb13.png

  1. 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.

  1. 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
  1. 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
  1. 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
  1. 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
  1. 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

  1. 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
  1. Á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.

d5c41bb89e22fd61.png

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:

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.