การสร้างที่ปลอดภัย ทำให้ใช้งานได้ด้วย Cloud Build, Artifact Registry และ GKE

รักษาความปลอดภัยและสร้าง ทำให้ใช้งานได้ด้วย Cloud Build, Artifact Registry และ GKE

เกี่ยวกับ Codelab นี้

subjectอัปเดตล่าสุดเมื่อ มี.ค. 4, 2023
account_circleเขียนโดย Christopher Grant

1 บทนำ

Container Analysis มีการสแกนช่องโหว่และพื้นที่เก็บข้อมูลเมตาสำหรับคอนเทนเนอร์ บริการสแกนจะสแกนช่องโหว่ในอิมเมจใน Artifact Registry และ Container Registry จากนั้นจัดเก็บข้อมูลเมตาที่ได้และทำให้พร้อมใช้งานผ่าน API พื้นที่เก็บข้อมูลเมตาช่วยให้คุณจัดเก็บข้อมูลจากแหล่งที่มาต่างๆ รวมถึงการสแกนช่องโหว่, บริการของ Google Cloud และผู้ให้บริการบุคคลที่สาม

การสแกนช่องโหว่อาจเกิดขึ้นโดยอัตโนมัติหรือแบบออนดีมานด์โดยดำเนินการดังนี้

  • เมื่อเปิดใช้การสแกนอัตโนมัติ การสแกนจะทริกเกอร์โดยอัตโนมัติทุกครั้งที่คุณพุชอิมเมจใหม่ไปยัง Artifact Registry หรือ Container Registry ข้อมูลช่องโหว่จะได้รับการอัปเดตอย่างต่อเนื่องเมื่อพบช่องโหว่ใหม่ๆ
  • เมื่อเปิดใช้การสแกนแบบออนดีมานด์ คุณต้องเรียกใช้คำสั่งเพื่อสแกนอิมเมจในเครื่องหรืออิมเมจใน Artifact Registry หรือ Container Registry การสแกนแบบออนดีมานด์ช่วยให้คุณสแกนคอนเทนเนอร์ได้อย่างยืดหยุ่น เช่น สแกนอิมเมจที่สร้างขึ้นในเครื่องและแก้ไขช่องโหว่ก่อนจัดเก็บไว้ในรีจิสทรี ผลการสแกนจะใช้ได้นานถึง 48 ชั่วโมงหลังจากสแกนเสร็จแล้ว และจะไม่มีการอัปเดตข้อมูลช่องโหว่หลังการสแกน

ด้วย Container Analysis ที่ผสานรวมอยู่ในไปป์ไลน์ CI/CD ของคุณ คุณจึงสามารถตัดสินใจโดยอิงตามข้อมูลเมตานั้นได้ ตัวอย่างเช่น คุณสามารถใช้การให้สิทธิ์แบบไบนารีเพื่อสร้างนโยบายการติดตั้งใช้งานที่อนุญาตให้ติดตั้งใช้งานเฉพาะอิมเมจที่เป็นไปตามข้อกำหนดจากรีจิสทรีที่เชื่อถือได้

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเปิดใช้การสแกนอัตโนมัติ
  • วิธีสแกนแบบออนดีมานด์
  • วิธีผสานรวมการสแกนในไปป์ไลน์บิลด์
  • วิธีเซ็นชื่อกำกับรูปภาพที่ได้รับอนุมัติ
  • วิธีใช้ตัวควบคุมการเข้าร่วม GKE เพื่อบล็อกรูปภาพ
  • วิธีกำหนดค่า GKE เพื่ออนุญาตเฉพาะอิมเมจที่อนุมัติที่ลงนามแล้ว

2 การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมตามเวลาที่สะดวก

  1. ลงชื่อเข้าใช้ Google Cloud Console และสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • ชื่อโครงการคือชื่อที่แสดงของผู้เข้าร่วมโปรเจ็กต์นี้ เป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ โดยคุณจะอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์จะไม่ซ้ำกันในทุกโปรเจ็กต์ของ Google Cloud และจะเปลี่ยนแปลงไม่ได้ (เปลี่ยนแปลงไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ปกติแล้วคุณไม่สนว่าอะไรเป็นอะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยปกติจะระบุเป็น PROJECT_ID) หากคุณไม่ชอบรหัสที่สร้างขึ้น คุณสามารถสร้างรหัสแบบสุ่มอื่นได้ หรือคุณจะลองดำเนินการเองแล้วดูว่าพร้อมให้บริการหรือไม่ และไม่สามารถเปลี่ยนแปลงได้หลังจากขั้นตอนนี้และจะยังคงอยู่ตลอดระยะเวลาของโปรเจ็กต์
  • สำหรับข้อมูลของคุณ ค่าที่ 3 คือหมายเลขโปรเจ็กต์ที่ API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 ค่าได้ในเอกสารประกอบ
  1. ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของระบบคลาวด์ การใช้งาน Codelab นี้น่าจะไม่มีค่าใช้จ่ายใดๆ หากมี หากต้องการปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่คุณสร้างหรือลบทั้งโปรเจ็กต์ได้ ผู้ใช้ใหม่ของ Google Cloud จะมีสิทธิ์เข้าร่วมโปรแกรมทดลองใช้ฟรี$300 USD

เริ่มผู้แก้ไข Cloudshell

ห้องทดลองนี้ออกแบบและทดสอบเพื่อใช้กับ Google Cloud Shell Editor วิธีเข้าถึงเครื่องมือแก้ไข

  1. เข้าถึงโปรเจ็กต์ Google ที่ https://console.cloud.google.com
  2. คลิกไอคอนตัวแก้ไข Cloud Shell ที่มุมขวาบน

8560cc8d45e8c112.png

  1. บานหน้าต่างใหม่จะเปิดขึ้นที่ด้านล่างของหน้าต่าง

การตั้งค่าสภาพแวดล้อม

ใน Cloud Shell ให้ตั้งรหัสโปรเจ็กต์และหมายเลขโปรเจ็กต์ บันทึกเป็นตัวแปร PROJECT_ID และ PROJECT_ID

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

เปิดใช้บริการ

เปิดใช้บริการที่จำเป็นทั้งหมด

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

สร้างที่เก็บ Artifact Registry

ในห้องทดลองนี้ คุณจะใช้ Artifact Registry เพื่อจัดเก็บและสแกนรูปภาพ สร้างที่เก็บด้วยคำสั่งต่อไปนี้

gcloud artifacts repositories create artifact-scanning-repo \
 
--repository-format=docker \
 
--location=us-central1 \
 
--description="Docker repository"

กำหนดค่า Docker เพื่อใช้ข้อมูลเข้าสู่ระบบ gcloud เมื่อเข้าถึง Artifact Registry

gcloud auth configure-docker us-central1-docker.pkg.dev

3 การสแกนอัตโนมัติ

การสแกนอาร์ติแฟกต์จะทริกเกอร์โดยอัตโนมัติทุกครั้งที่คุณพุชอิมเมจใหม่ไปยัง Artifact Registry หรือ Container Registry ข้อมูลช่องโหว่จะได้รับการอัปเดตอย่างต่อเนื่องเมื่อพบช่องโหว่ใหม่ๆ ในส่วนนี้ คุณจะพุชอิมเมจไปยัง Artifact Registry และสำรวจผลลัพธ์

สร้างและเปลี่ยนเป็นไดเรกทอรีงาน

mkdir vuln-scan && cd vuln-scan

กำหนดรูปภาพตัวอย่าง

สร้างไฟล์ชื่อ Dockerfile โดยใช้เนื้อหาต่อไปนี้

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

สร้างไฟล์ชื่อ main.py โดยมีเนื้อหาต่อไปนี้

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

สร้างและพุชรูปภาพไปยัง AR

ใช้ Cloud Build เพื่อสร้างและพุชคอนเทนเนอร์ไปยัง Artifact Registry โดยอัตโนมัติ จดแท็ก bad ในรูปภาพ วิธีนี้จะช่วยให้คุณระบุได้สำหรับขั้นตอนต่อๆ ไป

gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad

ตรวจสอบรายละเอียดรูปภาพ

เมื่อกระบวนการบิลด์เสร็จสมบูรณ์ ให้ตรวจสอบอิมเมจและช่องโหว่ในแดชบอร์ด Artifact Registry

  1. เปิด Artifact Registry ใน Cloud Console
  2. คลิกที่เก็บการสแกนอาร์ติแฟกต์เพื่อดูเนื้อหา
  3. คลิกดูรายละเอียดของรูปภาพ
  4. คลิกเข้าไปในสรุปล่าสุดของรูปภาพของคุณ
  5. เมื่อสแกนเสร็จแล้ว ให้คลิกแท็บช่องโหว่ของรูปภาพ

จากแท็บช่องโหว่ คุณจะเห็นผลลัพธ์ของการสแกนอัตโนมัติสำหรับอิมเมจที่คุณเพิ่งสร้างขึ้น

361be7b3bf293fca.png

ระบบจะเปิดใช้การสแกนอัตโนมัติโดยค่าเริ่มต้น สำรวจการตั้งค่า Artifact Registry เพื่อดูวิธีปิด/เปิดการสแกนอัตโนมัติ

4 การสแกนตามคำขอ

คุณอาจต้องเรียกใช้การสแกนก่อนที่จะพุชอิมเมจไปยังที่เก็บในหลายสถานการณ์ ตัวอย่างเช่น นักพัฒนาคอนเทนเนอร์อาจสแกนอิมเมจและแก้ปัญหาก่อนพุชโค้ดไปยังตัวควบคุมแหล่งที่มา ในตัวอย่างด้านล่าง คุณจะได้สร้างและวิเคราะห์รูปภาพในเครื่องก่อนที่จะดำเนินการกับผลลัพธ์

สร้างอิมเมจ

ในขั้นตอนนี้ คุณจะใช้ Docker ในเครื่องเพื่อสร้างอิมเมจไปยังแคชในเครื่อง

docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .

สแกนรูปภาพ

เมื่อสร้างรูปภาพแล้ว ให้ขอการสแกนรูปภาพ ผลการสแกนจะจัดเก็บไว้ในเซิร์ฟเวอร์ข้อมูลเมตา งานเสร็จสมบูรณ์พร้อมตำแหน่งของผลลัพธ์ในเซิร์ฟเวอร์ข้อมูลเมตา

gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --format="value(response.scan)" > scan_id.txt

ตรวจสอบไฟล์เอาต์พุต

โปรดใช้เวลาสักครู่เพื่อตรวจสอบเอาต์พุตของขั้นตอนก่อนหน้าซึ่งจัดเก็บไว้ในไฟล์ scan_id.txt สังเกตตำแหน่งรายงานของผลการสแกนในเซิร์ฟเวอร์ข้อมูลเมตา

cat scan_id.txt

ตรวจสอบผลการสแกนโดยละเอียด

หากต้องการดูผลลัพธ์จริงของการสแกน ให้ใช้คำสั่ง list-vulnerabilities บนตำแหน่งรายงานที่ระบุไว้ในไฟล์เอาต์พุต

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) 

เอาต์พุตจะมีข้อมูลจำนวนมากเกี่ยวกับช่องโหว่ทั้งหมดในภาพ

แจ้งปัญหาร้ายแรง

มนุษย์ไม่ค่อยใช้ข้อมูลที่จัดเก็บไว้ในรายงานโดยตรง โดยปกติแล้ว ผลลัพธ์ที่ได้จะใช้โดยกระบวนการอัตโนมัติ ใช้คำสั่งด้านล่างเพื่ออ่านรายละเอียดของรายงานและบันทึกหากพบช่องโหว่ที่ร้ายแรง

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

เอาต์พุตจากคำสั่งนี้จะ

Failed vulnerability check for CRITICAL level

5 สร้างการสแกนไปป์ไลน์

ในส่วนนี้ คุณจะได้สร้างไปป์ไลน์บิลด์อัตโนมัติที่จะสร้างอิมเมจคอนเทนเนอร์ จากนั้นสแกนโค้ดแล้วประเมินผลลัพธ์ หากไม่พบช่องโหว่ที่สำคัญ ระบบจะพุชอิมเมจไปยังที่เก็บ หากพบช่องโหว่ที่สำคัญ บิลด์จะล้มเหลวและออก

ให้สิทธิ์เข้าถึงบัญชีบริการ Cloud Build

Cloud Build ต้องมีสิทธิ์เข้าถึง API การสแกนตามคำขอ ให้สิทธิ์เข้าถึงด้วยคำสั่งต่อไปนี้

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"

สร้างไปป์ไลน์ Cloud Build

คำสั่งต่อไปนี้จะสร้างไฟล์ cloudbuild.yaml ในไดเรกทอรีที่จะใช้สำหรับกระบวนการอัตโนมัติ สำหรับตัวอย่างนี้ โปรดทราบว่าขั้นตอนจำกัดอยู่ที่กระบวนการสร้างคอนเทนเนอร์ ในทางปฏิบัติ คุณควรใส่คำแนะนำและการทดสอบเฉพาะแอปพลิเคชันนอกเหนือจากขั้นตอนคอนเทนเนอร์

สร้างไฟล์ด้วยคำสั่งต่อไปนี้

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

เรียกใช้ไปป์ไลน์ CI

ส่งบิลด์เพื่อประมวลผลเพื่อยืนยันช่วงพักโฆษณาของบิลด์เมื่อพบช่องโหว่ที่มีความรุนแรงระดับร้ายแรง

gcloud builds submit

ตรวจสอบการสร้างไม่สำเร็จ

บิลด์ที่คุณเพิ่งส่งจะล้มเหลวเนื่องจากอิมเมจมีช่องโหว่ร้ายแรง

ตรวจสอบความล้มเหลวของบิลด์ในหน้าประวัติ Cloud Build

แก้ไขช่องโหว่

อัปเดต Dockerfile ให้ใช้อิมเมจฐานที่ไม่มีช่องโหว่ CRITICAL

เขียนทับ Dockerfile เพื่อใช้อิมเมจ Debian 10 ด้วยคำสั่งต่อไปนี้

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

เรียกใช้กระบวนการ CI ด้วยรูปภาพที่ดี

ส่งบิลด์สำหรับการประมวลผลเพื่อยืนยันว่าบิลด์จะสำเร็จเมื่อไม่พบช่องโหว่ระดับร้ายแรง

gcloud builds submit

ตรวจสอบความสำเร็จของบิลด์

บิลด์ที่คุณเพิ่งส่งจะสำเร็จเนื่องจากอิมเมจที่อัปเดตไม่มีช่องโหว่ที่ร้ายแรง

ตรวจสอบความสำเร็จของบิลด์ในหน้าประวัติ Cloud Build

ตรวจสอบผลการสแกน

ตรวจสอบรูปภาพที่ดีในรีจิสทรีอาร์ติแฟกต์

  1. เปิด Artifact Registry ใน Cloud Console
  2. คลิกที่เก็บการสแกนอาร์ติแฟกต์เพื่อดูเนื้อหา
  3. คลิกดูรายละเอียดของรูปภาพ
  4. คลิกเข้าไปในสรุปล่าสุดของรูปภาพของคุณ
  5. คลิกแท็บช่องโหว่ของรูปภาพ

6 รูปภาพลงนาม

สร้างบันทึกของผู้รับรอง

หมายเหตุของผู้รับรองเป็นข้อมูลส่วนเล็กๆ ที่ทำหน้าที่เป็นป้ายกำกับสำหรับประเภทลายเซ็นที่ใช้ เช่น โน้ตรายการหนึ่งอาจระบุถึงการสแกนช่องโหว่ ในขณะที่อีกรายการหนึ่งอาจใช้สำหรับการลงชื่อ QA โดยจะมีการอ้างอิงหมายเหตุในระหว่างกระบวนการลงนาม

สร้างโน้ต

cat > ./vulnz_note.json << EOM
{
 
"attestation": {
   
"hint": {
     
"human_readable_name": "Container Vulnerabilities attestation authority"
   
}
 
}
}
EOM

เก็บโน้ต

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}"

ยืนยันหมายเหตุ

curl -vvv  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

กำลังสร้างผู้รับรอง

ระบบจะใช้ผู้รับรองเพื่อดำเนินการลงนามในรูปภาพจริง และจะแนบรายการหมายเหตุไปกับรูปภาพสำหรับการยืนยันในภายหลัง สร้างผู้รับรองเพื่อใช้ในภายหลัง

สร้างผู้รับรอง

ATTESTOR_ID=vulnz-attestor

gcloud
container binauthz attestors create $ATTESTOR_ID \
    --attestation-authority-note=$NOTE_ID \
    --attestation-authority-note-project=${PROJECT_ID}

ยืนยันผู้รับรอง

gcloud container binauthz attestors list

โปรดทราบว่าบรรทัดสุดท้ายจะระบุว่า NUM_PUBLIC_KEYS: 0 คุณจะระบุคีย์ในขั้นตอนถัดไป

โปรดทราบว่า Cloud Build จะสร้างผู้รับรอง built-by-cloud-build ในโปรเจ็กต์ของคุณโดยอัตโนมัติเมื่อคุณเรียกใช้บิลด์ที่สร้างอิมเมจ ดังนั้นคำสั่งด้านบนจะแสดงผลผู้รับรอง 2 รายการ คือ vulnz-attestor และ built-by-cloud-build หลังจากสร้างอิมเมจเรียบร้อยแล้ว Cloud Build จะลงนามและสร้างเอกสารรับรองให้กับอิมเมจโดยอัตโนมัติ

กำลังเพิ่มบทบาท IAM

บัญชีบริการการให้สิทธิ์แบบไบนารีจะต้องมีสิทธิ์ดูหมายเหตุในเอกสารรับรอง ให้สิทธิ์เข้าถึงด้วยการเรียก API ต่อไปนี้

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

ใช้ไฟล์ดังกล่าวเพื่อสร้างนโยบาย 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"

การเพิ่มคีย์ KMS

ผู้รับรองต้องใช้คีย์การเข้ารหัสเพื่อแนบบันทึกและระบุลายเซ็นที่ยืนยันได้ ในขั้นตอนนี้ คุณจะได้สร้างและจัดเก็บคีย์ใน KMS เพื่อให้ Cloud Build เข้าถึงในภายหลัง

ก่อนอื่นให้เพิ่มตัวแปรสภาพแวดล้อมเพื่ออธิบายคีย์ใหม่

KEY_LOCATION=global
KEYRING
=binauthz-keys
KEY_NAME
=codelab-key
KEY_VERSION
=1

สร้างคีย์ริงเพื่อเก็บชุดคีย์

gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"

สร้างคู่คีย์การลงนามแบบอสมมาตรใหม่สำหรับผู้รับรอง

gcloud kms keys create "${KEY_NAME}" \
    --keyring="${KEYRING}" --location="${KEY_LOCATION}" \
    --purpose asymmetric-signing   \
    --default-algorithm="ec-sign-p256-sha256"

คุณควรเห็นคีย์ปรากฏบนหน้า KMS ของ Google Cloud Console

จากนั้นเชื่อมโยงคีย์กับผู้รับรองผ่านคำสั่ง 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}"

หากคุณพิมพ์รายชื่อหน่วยงานอีกครั้ง คุณจะเห็นคีย์ที่ลงทะเบียนแล้ว

gcloud container binauthz attestors list

การสร้างเอกสารรับรองที่ลงชื่อ

ในจุดนี้ คุณได้กำหนดค่าคุณลักษณะที่ทำให้คุณสามารถใส่เครื่องหมายในรูปภาพได้ ใช้ผู้รับรองที่สร้างไว้ก่อนหน้านี้เพื่อลงนามอิมเมจคอนเทนเนอร์ที่คุณทำงานอยู่ด้วย

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)')

ตอนนี้คุณใช้ gcloud เพื่อสร้างเอกสารรับรองได้แล้ว คำสั่งจะใส่รายละเอียดของคีย์ที่คุณต้องการใช้สำหรับลงชื่อ และอิมเมจคอนเทนเนอร์เฉพาะที่คุณต้องการอนุมัติ

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}"

ในข้อกำหนดของ Container Analysis การดำเนินการนี้จะสร้างรายการใหม่ และแนบกับบันทึกของผู้รับรอง คุณระบุเอกสารรับรองได้เพื่อให้แน่ใจว่าทุกอย่างทำงานตามที่คาดไว้

gcloud container binauthz attestations list \
   --attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}

7 การรับรองด้วย Cloud Build

คุณได้เปิดใช้การรับรองรูปภาพและใช้ผู้รับรองเพื่อลงนามรูปภาพตัวอย่างด้วยตนเอง ในทางปฏิบัติ คุณควรใช้เอกสารรับรองในระหว่างกระบวนการอัตโนมัติ เช่น ไปป์ไลน์ CI/CD

ในส่วนนี้ คุณจะได้กำหนดค่า Cloud Build เพื่อยืนยันอิมเมจโดยอัตโนมัติ

บทบาท

เพิ่มบทบาทผู้ดูผู้รับรองการให้สิทธิ์แบบไบนารีในบัญชีบริการ Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/binaryauthorization.attestorsViewer

เพิ่มบทบาทผู้ลงนาม/ผู้รับรอง Cloud KMS CryptoKey ในบัญชีบริการ Cloud Build (การลงชื่อที่ใช้ KMS)

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/cloudkms.signerVerifier

เพิ่มบทบาทผู้แนบบันทึก Container Analysis ไปยังบัญชีบริการ Cloud Build:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/containeranalysis.notes.attacher

เตรียมขั้นตอน Cloud Build สำหรับบิลด์ที่กำหนดเอง

คุณจะใช้ขั้นตอนบิลด์ที่กำหนดเองใน Cloud Build เพื่อทำให้กระบวนการรับรองง่ายขึ้น Google มีขั้นตอนการสร้างที่กําหนดเองนี้ซึ่งมีฟังก์ชันตัวช่วยที่จะเพิ่มประสิทธิภาพให้กับกระบวนการ ก่อนใช้งาน คุณต้องสร้างโค้ดสำหรับขั้นตอนบิลด์ที่กำหนดเองในคอนเทนเนอร์และพุชไปยัง Cloud Build โดยเรียกใช้คำสั่งต่อไปนี้

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

เพิ่มขั้นตอนการลงนามใน cloudbuild.yaml

ในขั้นตอนนี้ คุณจะเพิ่มขั้นตอนเอกสารรับรองลงในไปป์ไลน์ Cloud Build ที่คุณสร้างก่อนหน้านี้

  1. ดูขั้นตอนใหม่ที่คุณจะเพิ่ม

รีวิวเท่านั้น ไม่คัดลอก

#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. เขียนทับไฟล์ cloudbuild.yaml ของคุณด้วยไปป์ไลน์ที่สมบูรณ์ที่อัปเดตแล้ว
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

เรียกใช้บิลด์

gcloud builds submit

ตรวจสอบบิลด์ในประวัติ Cloud Build

เปิด Cloud Console ไปที่หน้าประวัติ Cloud Build แล้วตรวจสอบบิลด์ล่าสุดและการดำเนินการตามขั้นตอนของบิลด์ได้สำเร็จ

8 นโยบายควบคุมการเข้าชม

การให้สิทธิ์แบบไบนารีเป็นฟีเจอร์ใน GKE และ Cloud Run ที่มอบความสามารถในการตรวจสอบกฎก่อนที่จะอนุญาตให้อิมเมจคอนเทนเนอร์ทำงาน การตรวจสอบจะดำเนินการตามคำขอเพื่อเรียกใช้อิมเมจทั้งจากไปป์ไลน์ CI/CD ที่เชื่อถือได้ หรือเมื่อผู้ใช้พยายามทำให้อิมเมจใช้งานได้ด้วยตนเอง ซึ่งความสามารถนี้จะช่วยให้คุณรักษาความปลอดภัยของสภาพแวดล้อมรันไทม์ได้อย่างมีประสิทธิภาพมากกว่าการตรวจสอบไปป์ไลน์ CI/CD เพียงอย่างเดียว

หากต้องการทำความเข้าใจความสามารถนี้ คุณจะต้องแก้ไขนโยบาย GKE เริ่มต้นเพื่อบังคับใช้กฎการให้สิทธิ์ที่เข้มงวด

สร้างคลัสเตอร์ GKE

สร้างคลัสเตอร์ GKE ด้วยคำสั่งต่อไปนี้

gcloud beta container clusters create binauthz \
   
--zone us-central1-a  \
   
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE

อนุญาตให้ Cloud Build ทำให้ใช้งานได้กับคลัสเตอร์นี้:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/container.developer"

อนุญาตนโยบายทั้งหมด

ก่อนอื่นให้ยืนยันสถานะนโยบายเริ่มต้นและความสามารถในการทำให้อิมเมจใดก็ได้ใช้งานได้

  1. อ่านนโยบายที่มีอยู่
gcloud container binauthz policy export
  1. โปรดทราบว่านโยบายการบังคับใช้ตั้งค่าเป็น ALWAYS_ALLOW

evaluationMode: ALWAYS_ALLOW

  1. ทำให้ตัวอย่างใช้งานได้เพื่อยืนยันว่าคุณสามารถติดตั้งใช้งานได้ทุกอย่าง
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. ยืนยันว่าการทำให้ใช้งานได้ใช้งานได้
kubectl get pods

คุณจะเห็นเอาต์พุตต่อไปนี้

161db370d99ffb13.png

  1. ลบการทำให้ใช้งานได้
kubectl delete pod hello-server

ปฏิเสธนโยบายทั้งหมด

จากนั้นให้อัปเดตนโยบายเพื่อไม่อนุญาตรูปภาพทั้งหมด

  1. ส่งออกนโยบายปัจจุบันไปยังไฟล์ที่แก้ไขได้
gcloud container binauthz policy export  > policy.yaml
  1. เปลี่ยนนโยบาย

ในเครื่องมือแก้ไขข้อความ ให้เปลี่ยนโหมดการประเมินจาก ALWAYS_ALLOW เป็น ALWAYS_DENY

edit policy.yaml

ไฟล์ YAML ของนโยบายควรปรากฏดังนี้

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_DENY
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. เปิดเทอร์มินัลแล้วใช้นโยบายใหม่และรอสักครู่เพื่อให้การเปลี่ยนแปลงมีผล
gcloud container binauthz policy import policy.yaml
  1. ลองทำให้ภาระงานตัวอย่างใช้งานได้
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. การทำให้ใช้งานได้ล้มเหลวโดยมีข้อความต่อไปนี้
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

เปลี่ยนกลับนโยบายเพื่ออนุญาตทั้งหมด

ก่อนไปยังส่วนถัดไป โปรดตรวจสอบว่าได้เปลี่ยนกลับการเปลี่ยนแปลงนโยบายแล้ว

  1. เปลี่ยนนโยบาย

ในเครื่องมือแก้ไขข้อความ ให้เปลี่ยนโหมดการประเมินจาก ALWAYS_DENY เป็น ALWAYS_ALLOW

edit policy.yaml

ไฟล์ YAML ของนโยบายควรปรากฏดังนี้

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. ใช้นโยบายที่เปลี่ยนกลับ
gcloud container binauthz policy import policy.yaml

9 บล็อกช่องโหว่ใน GKE

ในส่วนนี้ คุณจะได้รวมสิ่งที่ได้เรียนรู้จนถึงตอนนี้ โดยการติดตั้งใช้งานไปป์ไลน์ CI/CD กับ Cloud Build ที่จะสแกนอิมเมจ จากนั้นตรวจหาช่องโหว่ก่อนลงนามอิมเมจและพยายามติดตั้งใช้งาน GKE จะใช้การให้สิทธิ์แบบไบนารีเพื่อตรวจสอบว่าอิมเมจมีลายเซ็นจากการสแกนช่องโหว่ก่อนอนุญาตให้อิมเมจทำงาน

d5c41bb89e22fd61.png

อัปเดตนโยบาย GKE เพื่อต้องมีเอกสารรับรอง

ผู้รับรองต้องลงชื่ออิมเมจโดยการเพิ่มคลัสเตอร์AdmissionRules ต่างๆ ในนโยบาย GKE BinAuth

เขียนทับนโยบายด้วยการกำหนดค่าที่อัปเดตแล้วโดยใช้คำสั่งด้านล่าง

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

ใช้นโยบาย

gcloud beta container binauthz policy import binauth_policy.yaml

พยายามทำให้อิมเมจที่ไม่มีการรับรองใช้งานได้

สร้างข้อบ่งชี้การทำให้ใช้งานได้สำหรับแอปพลิเคชันที่คุณสร้างไว้ก่อนหน้านี้โดยใช้คำสั่งต่อไปนี้ อิมเมจที่ใช้ที่นี่คืออิมเมจที่คุณสร้างขึ้นก่อนหน้านี้ซึ่งมีช่องโหว่ร้ายแรงและไม่มีเอกสารรับรองที่ลงชื่อ

ตัวควบคุมการเข้าร่วม GKE จำเป็นต้องทราบอิมเมจที่ถูกต้องที่จะทำให้ใช้งานได้เพื่อตรวจสอบลายเซ็นอย่างสม่ำเสมอ ในการทำให้ได้ผลนี้ คุณจะต้องใช้ไดเจสต์รูปภาพแทนที่จะใช้แท็กง่ายๆ

รับสรุปรูปภาพสำหรับรูปภาพที่ไม่ดี

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)')

ใช้ไดเจสต์ในการกำหนดค่า 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

พยายามทำให้แอปใช้งานได้กับ GKE

kubectl apply -f deploy.yaml

ตรวจสอบภาระงานในคอนโซล และสังเกตข้อผิดพลาดที่ระบุว่าการทำให้ใช้งานได้ถูกปฏิเสธ

No attestations found that were valid and signed by a key trusted by the attestor

ทำให้รูปภาพที่ลงนามใช้งานได้

รับสรุปรูปภาพสำหรับรูปภาพที่ไม่ดี

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)')

ใช้ไดเจสต์ในการกำหนดค่า 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

ทำให้แอปใช้งานได้กับ GKE

kubectl apply -f deploy.yaml

ตรวจสอบภาระงานในคอนโซลและบันทึกการนำอิมเมจไปใช้งานได้สำเร็จ

10 ยินดีด้วย

ยินดีด้วย คุณศึกษา Codelab จบแล้ว

สิ่งที่เราได้พูดคุยกันมีดังนี้

  • วิธีเปิดใช้การสแกนอัตโนมัติ
  • วิธีสแกนแบบออนดีมานด์
  • วิธีผสานรวมการสแกนในไปป์ไลน์บิลด์
  • วิธีเซ็นชื่อกำกับรูปภาพที่ได้รับอนุมัติ
  • วิธีใช้ตัวควบคุมการเข้าร่วม GKE เพื่อบล็อกรูปภาพ
  • วิธีกำหนดค่า GKE เพื่ออนุญาตเฉพาะอิมเมจที่อนุมัติที่ลงนามแล้ว

ขั้นตอนต่อไปที่ทำได้

ล้างข้อมูล

เพื่อหลีกเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud สำหรับทรัพยากรที่ใช้ในบทแนะนำนี้ โปรดลบโปรเจ็กต์ที่มีทรัพยากรดังกล่าวหรือเก็บโปรเจ็กต์ไว้และลบทรัพยากรแต่ละรายการ

กำลังลบโปรเจ็กต์

วิธีที่ง่ายที่สุดในการยกเลิกการเรียกเก็บเงินคือการลบโปรเจ็กต์ที่คุณสร้างไว้สำหรับบทแนะนำ