การทำให้ Gating ใช้งานได้ด้วยการตรวจสอบสิทธิ์แบบไบนารี

1. บทนำ

การให้สิทธิ์แบบไบนารีคือการควบคุมความปลอดภัยในเวลาที่ทำให้ใช้งานได้ ซึ่งช่วยให้มั่นใจได้ว่าจะมีเพียงการทำให้อิมเมจคอนเทนเนอร์ที่เชื่อถือได้ใช้งานได้ใน Google Kubernetes Engine (GKE) หรือ Cloud Run เท่านั้น การให้สิทธิ์แบบไบนารีช่วยให้คุณกำหนดให้หน่วยงานที่เชื่อถือลงนามในอิมเมจระหว่างกระบวนการพัฒนาได้ จากนั้นจึงบังคับใช้การตรวจสอบลายเซ็นเมื่อทำการติดตั้งใช้งาน การบังคับใช้การตรวจสอบช่วยให้คุณควบคุมสภาพแวดล้อมคอนเทนเนอร์ได้มากขึ้นโดยการตรวจสอบว่ามีการผสานรวมเฉพาะอิมเมจที่ยืนยันแล้วเข้ากับกระบวนการสร้างและเผยแพร่

แผนภาพต่อไปนี้แสดงคอมโพเนนต์ในการตั้งค่าการให้สิทธิ์แบบไบนารี/Cloud Build

ไปป์ไลน์เอกสารรับรองการให้สิทธิ์แบบไบนารีของ Cloud Build**รูปที่ 1.**ไปป์ไลน์ Cloud Build ที่สร้างการรับรองการให้สิทธิ์แบบไบนารี

ในไปป์ไลน์นี้

  1. ระบบจะพุชโค้ดเพื่อสร้างอิมเมจคอนเทนเนอร์ไปยังที่เก็บซอร์ส เช่น Cloud Source Repositories
  2. เครื่องมือการรวมอย่างต่อเนื่อง (CI) Cloud Build จะสร้างและทดสอบคอนเทนเนอร์
  3. การสร้างจะพุชอิมเมจคอนเทนเนอร์ไปยัง Container Registry หรือรีจิสทรีอื่นที่จัดเก็บอิมเมจที่สร้าง
  4. Cloud Key Management Service ซึ่งให้บริการจัดการคีย์สำหรับคู่คีย์การเข้ารหัส จะลงนามในอิมเมจคอนเทนเนอร์ จากนั้นระบบจะจัดเก็บลายเซ็นที่ได้ไว้ในการรับรองที่สร้างขึ้นใหม่
  5. ในเวลาที่ทำการทำให้ใช้งานได้ ผู้รับรองจะยืนยันเอกสารรับรองโดยใช้คีย์สาธารณะจากคู่คีย์ การให้สิทธิ์แบบไบนารีบังคับใช้นโยบายโดยกำหนดให้ต้องมีเอกสารรับรองที่ลงนามแล้วเพื่อทำให้ใช้งานอิมเมจคอนเทนเนอร์ได้

ในแล็บนี้ คุณจะมุ่งเน้นที่เครื่องมือและเทคนิคในการรักษาความปลอดภัยของอาร์ติแฟกต์ที่ติดตั้งใช้งาน Lab นี้มุ่งเน้นที่อาร์ติแฟกต์ (คอนเทนเนอร์) หลังจากที่สร้างขึ้นแล้ว แต่ยังไม่ได้นําไปใช้ในสภาพแวดล้อมใดๆ

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

  • การลงนามในรูปภาพ
  • นโยบายการควบคุมการรับส่ง
  • การลงนามในรูปภาพที่สแกน
  • การให้สิทธิ์รูปภาพที่ลงนาม
  • รูปภาพที่ไม่มีการลงนามซึ่งถูกบล็อก

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 ของ Cloud การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีเลย หากต้องการปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่สร้างขึ้นหรือลบทั้งโปรเจ็กต์ได้ ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

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

ใน 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

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

mkdir vuln-scan && cd vuln-scan

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

สร้างไฟล์ชื่อ Dockerfile ที่มีเนื้อหาต่อไปนี้

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

สร้างไฟล์ชื่อ 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 โดยอัตโนมัติ

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

3. การลงนามในรูปภาพ

ผู้รับรองคืออะไร

ผู้รับรอง

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

บทบาทแต่ละบทบาทอาจเป็นตัวแทนของบุคคลหนึ่งๆ หรือทีมในองค์กรของคุณ ในสภาพแวดล้อมการใช้งานจริง บทบาทเหล่านี้มักจะได้รับการจัดการโดยโปรเจ็กต์ Google Cloud Platform (GCP) แยกต่างหาก และสิทธิ์เข้าถึงทรัพยากรจะได้รับการแชร์ระหว่างกันในลักษณะที่จำกัดโดยใช้ Cloud IAM

a37eb2ed54b9c2eb.png

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

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

208aa5ebc53ff2b3.png

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

Binary Authorization API ใช้แนวคิดของ "ผู้รับรอง" และ "เอกสารรับรอง" แต่จะใช้การติดตั้งใช้งานโดยใช้หมายเหตุและรายการที่เกี่ยวข้องใน Container Analysis API

63a701bd0057ea17.png

สร้างหมายเหตุผู้รับรอง

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

919f997db0ffb881.png

สร้างโน้ต

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

ตอนนี้ระบบได้บันทึกโน้ตของคุณไว้ใน Container Analysis API แล้ว

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

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

ed05d438c79b654d.png

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

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ผู้รับรองในโปรเจ็กต์โดยอัตโนมัติเมื่อคุณเรียกใช้บิลด์ที่สร้างอิมเมจ ดังนั้นคำสั่งด้านบนจะแสดง Attestor 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

1e3af7c177f7a311.png

ก่อนที่จะใช้ Attestor นี้ได้ หน่วยงานของคุณต้องสร้างคู่คีย์การเข้ารหัสที่ใช้ลงนามในอิมเมจคอนเทนเนอร์ได้ ซึ่งทำได้ผ่าน Google Cloud Key Management Service (KMS)

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

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

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

การสร้างการรับรองที่ลงนาม

ตอนนี้คุณได้กำหนดค่าฟีเจอร์ที่ช่วยให้คุณลงนามในรูปภาพได้แล้ว ใช้ Attestor ที่คุณสร้างไว้ก่อนหน้านี้เพื่อลงนามในอิมเมจคอนเทนเนอร์ที่คุณใช้

858d7e6feeb6f159.png

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

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}

4. นโยบายการควบคุมการรับส่ง

การให้สิทธิ์แบบไบนารีเป็นฟีเจอร์ใน 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. เปลี่ยนนโยบาย

ในโปรแกรมแก้ไขข้อความ ให้เปลี่ยน evaluationMode จาก 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

นโยบายนี้ค่อนข้างง่าย บรรทัด globalPolicyEvaluationMode ประกาศว่านโยบายนี้ขยายขอบเขตนโยบายส่วนกลางที่ Google กำหนด ซึ่งจะช่วยให้คอนเทนเนอร์ GKE อย่างเป็นทางการทั้งหมดทำงานได้โดยค่าเริ่มต้น นอกจากนี้ นโยบายยังประกาศ defaultAdmissionRule ที่ระบุว่า พ็อดอื่นๆ ทั้งหมดจะถูกปฏิเสธ กฎการยอมรับมีบรรทัด enforcementMode ซึ่งระบุว่าควรบล็อกไม่ให้พ็อดทั้งหมดที่ไม่เป็นไปตามกฎนี้ทํางานในคลัสเตอร์

ดูวิธีการสร้างนโยบายที่ซับซ้อนยิ่งขึ้นได้ในเอกสารประกอบของการให้สิทธิ์แบบไบนารี

657752497e59378c.png

  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. เปลี่ยนนโยบาย

ในโปรแกรมแก้ไขข้อความ ให้เปลี่ยน evaluationMode จาก 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

5. การลงนามในรูปภาพที่สแกน

คุณได้เปิดใช้การลงนามรูปภาพและใช้ Attestor ด้วยตนเองเพื่อลงนามในรูปภาพตัวอย่าง ในทางปฏิบัติ คุณจะต้องใช้การรับรองในระหว่างกระบวนการอัตโนมัติ เช่น ไปป์ไลน์ 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 จะต้องมีสิทธิ์เข้าถึง 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 ที่กำหนดเอง

คุณจะใช้ขั้นตอนการบิลด์ที่กำหนดเองใน 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 แล้วตรวจสอบบิลด์ล่าสุดและการดำเนินการตามขั้นตอนการสร้างที่สำเร็จ

6. การให้สิทธิ์รูปภาพที่ลงนาม

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

d5c41bb89e22fd61.png

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

กำหนดให้รูปภาพต้องลงนามโดย Attestor โดยการเพิ่ม ClusterAdmissionRules ลงในนโยบาย BinAuth ของ GKE

ปัจจุบันคลัสเตอร์ของคุณใช้นโยบายที่มีกฎ 1 ข้อ ได้แก่ อนุญาตคอนเทนเนอร์จากที่เก็บอย่างเป็นทางการ และปฏิเสธคอนเทนเนอร์อื่นๆ ทั้งหมด

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

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

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

822240fc0b02408e.png

อัปโหลดนโยบายใหม่ไปยังการให้สิทธิ์แบบไบนารี

gcloud beta container binauthz policy import binauth_policy.yaml

ทำให้ใช้งานได้อิมเมจที่ลงนามแล้ว

รับไดเจสต์รูปภาพสำหรับรูปภาพที่ดี

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

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

7. รูปภาพที่ไม่มีการลงนามซึ่งถูกบล็อก

สร้างรูปภาพ

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

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

พุชอิมเมจที่ไม่ได้ลงนามไปยังที่เก็บ

docker push us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad

รับไดเจสต์รูปภาพสำหรับรูปภาพที่ไม่เหมาะสม

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

8. ยินดีด้วย

ยินดีด้วย คุณทำ Codelab เสร็จแล้ว

สิ่งที่เราได้พูดถึงไปแล้ว

  • การลงนามในรูปภาพ
  • นโยบายการควบคุมการรับส่ง
  • การลงนามในรูปภาพที่สแกน
  • การให้สิทธิ์รูปภาพที่ลงนาม
  • รูปภาพที่ไม่มีการลงนามซึ่งถูกบล็อก

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

ล้างข้อมูล

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

การลบโปรเจ็กต์

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

อัปเดตล่าสุด: 21/3/23