開始使用 Google Cloud CLI (GKE)

本教學課程說明如何設定及測試需要認證的二進位授權政策。這類政策會先驗證容器映像檔是否具有已簽署的認證,再允許部署映像檔,確保以容器為基礎的軟體供應鏈安全無虞。

部署時,二進位授權會使用驗證者驗證認證中的數位簽章。認證是由簽署者建立,通常是持續整合 (CI) 管道的一部分。

在本教學課程中,GKE 叢集、認證和認證者都位於單一專案中。單一專案設定大多用於測試或實驗服務。如需更貼近實際情況的範例,請參閱多項專案的設定

下列步驟說明您在指令列執行的工作。如要使用 Google Cloud 控制台完成這些步驟,請參閱「透過 Google Cloud 控制台開始使用」。

啟用二進位授權

設定預設專案

第一步是設定 gcloud 指令使用的預設 Google Cloud 專案:

PROJECT_ID=PROJECT_ID
gcloud config set project ${PROJECT_ID}

其中 PROJECT_ID 是專案名稱。

啟用必要的 API

啟用下列 API:

Artifact Registry

gcloud --project=${PROJECT_ID} \
    services enable\
    container.googleapis.com\
    artifactregistry.googleapis.com\
    binaryauthorization.googleapis.com

建立啟用二進位授權功能的叢集

建立叢集

建立啟用二進位授權的 GKE 叢集。這是要執行已部署容器映像檔的叢集。建立叢集時,請將 --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE 標記傳遞至 gcloud container clusters create 指令。

如要建立叢集,請按照下列步驟操作:

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

您將在 GKE 區域 us-central1-a 中建立名為 test-cluster 的叢集。

設定 kubectl

您也必須更新 kubectl 安裝的本機 kubeconfig 檔案。這會提供在 GKE 中存取叢集所需的憑證和端點資訊。

如要更新本機 kubeconfig 檔案,請按照下列步驟操作:

gcloud container clusters get-credentials \
    --zone us-central1-a \
    test-cluster

查看預設政策

二進位授權的政策是一組規則,可管理容器映像檔的部署作業。每個專案只能有一項政策。 根據預設,這項政策會允許部署所有容器映像檔。

您可以使用二進位授權匯出及匯入 YAML 格式的政策檔案。這個格式反映了服務儲存政策的結構。使用 gcloud 指令設定政策時,您會編輯這個檔案。

如要查看預設政策,請匯出政策 YAML 檔案:

gcloud container binauthz policy export

根據預設,檔案包含下列內容:

defaultAdmissionRule:
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
  evaluationMode: ALWAYS_ALLOW
globalPolicyEvaluationMode: ENABLE
name: projects/PROJECT_ID/policy

預設規則定義在 defaultAdmissionRule 節點中。evaluationMode 指定政策允許所有映像檔部署嘗試。在本教學課程中,您將更新預設規則,要求提供認證。

globalPolicyEvaluationMode 可豁免 Google 管理的系統映像檔,使其不受二進位授權強制執行機制限制。

如要將豁免圖片加入許可清單,請在政策檔案中新增下列內容:

admissionWhitelistPatterns:
  - namePattern: EXEMPT_IMAGE_PATH

EXEMPT_IMAGE_PATH 替換為要排除的圖片路徑。如要排除其他圖片,請新增其他 - namePattern 項目。進一步瞭解 admissionWhitelistPatterns

如要進一步瞭解政策結構,請參閱政策 YAML 參考資料

建立驗證者

驗證者是驗證機構,二進位授權執行者會在部署時使用驗證者,決定是否允許 GKE 部署相應的已簽署容器映像檔。驗證者包含公開金鑰,通常由貴機構負責軟體供應鏈安全的人員管理。

如要建立驗證者,請完成下列步驟:

  • 構件分析中建立附註,儲存授權程序中使用的可信中繼資料
  • 在二進位授權中建立驗證者本身,並連結您建立的附註

在本教學課程中,您有一個名為 test-attestor 的驗證者,以及一個名為 test-attestor-note 的容器分析附註。在實際情況中,您可以擁有任意數量的驗證者,每個驗證者代表參與容器映像檔授權程序的當事人。

建立構件分析附註

  1. 設定變數,以儲存簽署者和構件分析附註的名稱:

    ATTESTOR_NAME=test-attestor
    NOTE_ID=test-attestor-note
    

    取代:

    • test-attestor:您選擇的驗證者名稱。
    • attestor-note:您選擇的驗證者附註名稱。
  2. /tmp/note_payload.json 中建立 JSON 檔案,說明 Container Analysis 附註:

    cat > /tmp/note_payload.json << EOM
    {
      "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}",
      "attestation": {
        "hint": {
          "human_readable_name": "Attestor Note"
        }
      }
    }
    EOM
    
  3. 將 HTTP 要求傳送至 Artifact Analysis REST API,建立附註:

    curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
        --data-binary @/tmp/note_payload.json  \
        "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
    
  4. 確認記事已建立:

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

建立驗證者

現在,您可以建立驗證者:

  1. 在二進位授權中建立驗證者:

    gcloud container binauthz attestors create ${ATTESTOR_NAME} \
    --attestation-authority-note=${NOTE_ID} \
    --attestation-authority-note-project=${PROJECT_ID}
    
  2. 確認驗證者是否已建立:

    gcloud container binauthz attestors list
    

您建立的驗證者尚未與金鑰組建立關聯,因此無法使用。請在本指南稍後建立金鑰組。

產生金鑰組

二進位授權會使用加密編譯金鑰,安全地驗證簽署者的身分。確保只有授權的容器映像檔可以部署。金鑰組包含私密金鑰和公開金鑰。簽署者會使用私密金鑰簽署容器映像檔摘要,產生簽章並儲存在認證中。公開金鑰會儲存在驗證者中。在部署時,二進位授權執行者會使用驗證者的公開金鑰,驗證認證中的簽章,然後允許部署容器。

在本教學課程中,您會使用公開金鑰基礎架構 (X.509) (PKIX) 格式的加密金鑰。本教學課程使用建議的橢圓曲線數位簽章演算法 (ECDSA),產生 PKIX 金鑰組。您也可以使用 RSA 或 PGP 金鑰簽署映像檔。

如要進一步瞭解簽署演算法,請參閱「金鑰用途與演算法」一文。

Cloud Key Management Service (Cloud KMS) 產生及儲存的金鑰符合 PKIX 標準。如要進一步瞭解如何使用 PKIX 金鑰和 Cloud KMS,請參閱「使用 gcloud CLI 建立驗證者」。

PKIX (Cloud KMS)

如要在 Cloud KMS 中建立金鑰組,請按照下列步驟操作:

  1. 設定建立金鑰組所需的環境變數。

    KMS_KEY_PROJECT_ID=${PROJECT_ID}
    KMS_KEYRING_NAME=my-binauthz-keyring
    KMS_KEY_NAME=my-binauthz-kms-key-name
    KMS_KEY_LOCATION=global
    KMS_KEY_PURPOSE=asymmetric-signing
    KMS_KEY_ALGORITHM=ec-sign-p256-sha256
    KMS_PROTECTION_LEVEL=software
    KMS_KEY_VERSION=1
    
  2. 如要建立金鑰環,請執行下列指令:

    gcloud kms keyrings create ${KMS_KEYRING_NAME} \
      --location ${KMS_KEY_LOCATION}
    
  3. 如要建立金鑰,請執行下列指令:

    gcloud kms keys create ${KMS_KEY_NAME} \
      --location ${KMS_KEY_LOCATION} \
      --keyring ${KMS_KEYRING_NAME}  \
      --purpose ${KMS_KEY_PURPOSE} \
      --default-algorithm ${KMS_KEY_ALGORITHM} \
      --protection-level ${KMS_PROTECTION_LEVEL}
    
  4. 如要將公開金鑰新增至認證者,請執行下列指令:

    gcloud --project="${PROJECT_ID}" \
        container binauthz attestors public-keys add \
        --attestor="${ATTESTOR_NAME}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    
  5. 從驗證者取得公開金鑰 ID,方法如下:

    您隨時可以使用 gcloud container binauthz attestors describe <var>ATTESTOR_NAME</var> 指令查看公開金鑰 ID。

    如要將公開金鑰 ID 儲存至環境變數,請輸入下列指令:

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
    --format='value(userOwnedGrafeasNote.publicKeys[0].id)' --project ${PROJECT_ID})
    

PKIX (本機金鑰)

如要產生 PKIX 金鑰組,請按照下列步驟操作:

  1. 建立私密金鑰:

    PRIVATE_KEY_FILE="/tmp/ec_private.pem"
    openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
    
  2. 從私密金鑰中擷取公開金鑰:

    PUBLIC_KEY_FILE="/tmp/ec_public.pem"
    openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
    
  3. 將公開金鑰新增至驗證者。

    現在,請將匯出的公開金鑰新增至驗證者,以便二進位檔授權服務用於身分驗證:

    gcloud --project="${PROJECT_ID}" \
        beta container binauthz attestors public-keys add \
        --attestor="${ATTESTOR_NAME}" \
        --pkix-public-key-file=${PUBLIC_KEY_FILE} \
        --pkix-public-key-algorithm=ecdsa-p256-sha256
    
  4. 儲存公開金鑰 ID。

    如要儲存公開金鑰 ID,請從上述 public-keys add 的輸出內容複製。將驗證者公開金鑰新增至驗證者後,如要查看驗證者的公開金鑰 ID,請使用 gcloud container binauthz attestors describe ${ATTESTOR_NAME}

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    

設定政策

現在可以設定政策。在這個步驟中,您會將政策 YAML 檔案匯出至本機系統,並修改預設規則,要求上述定義的認證者進行認證。

如要設定政策,請按照下列步驟操作:

  1. 建立新的政策檔案,允許Google 維護的系統映像檔,將 evaluationMode 設為 REQUIRE_ATTESTATION,並新增名為 requireAttestationsBy 的節點,參照您建立的認證者:

    cat > /tmp/policy.yaml << EOM
        globalPolicyEvaluationMode: ENABLE
        defaultAdmissionRule:
          evaluationMode: REQUIRE_ATTESTATION
          enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
          requireAttestationsBy:
            - projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}
        name: projects/${PROJECT_ID}/policy
    EOM
    
  2. 將政策 YAML 檔案匯入二進位授權:

    gcloud container binauthz policy import /tmp/policy.yaml
    

如要進一步瞭解如何設定政策,請參閱「使用 gcloud CLI 設定政策」。

測試政策

您可以嘗試將範例容器映像檔部署到叢集,測試上述設定的政策。由於未進行必要的認證,政策會禁止部署作業。

在本教學課程中,您可以使用 Artifact Registry 中的範例圖片。Artifact Registry 中的映像檔位於 us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 路徑。路徑包含 Google 建立的公開映像檔,其中含有「Hello, World!」範例應用程式。

請先嘗試部署映像檔:

kubectl run hello-server --image us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 --port 8080

現在,請驗證二進位授權是否封鎖了部署作業:

kubectl get pods

指令會列印下列訊息,表示映像檔未部署:

No resources found.

您可以取得部署作業的進一步詳細資料:

kubectl get event --template \
'{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}\{{.message}}{{"\n"}}{{end}}'

你會看到類似以下的回應:

FailedCreate: Error creating: pods POD_NAME is forbidden: admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image IMAGE_NAME denied by Binary Authorization default admission rule. Image IMAGE_NAME denied by attestor ATTESTOR_NAME: No attestations found

輸出內容如下:

  • POD_NAME:Pod 的名稱。
  • IMAGE_NAME:圖片名稱。
  • ATTESTOR_NAME:驗證者名稱。

請務必刪除部署作業,才能繼續下一個步驟:

kubectl delete deployment hello-server

建立認證

驗證是由簽署人建立的數位文件,證明 GKE 有權部署相關聯的容器映像檔。建立認證的程序有時稱為「簽署映像檔」。簽署者可以是人,但通常是容器映像檔建構時執行的自動化程序。簽名是使用金鑰組中的私密金鑰建立。在部署時,二進位授權執行者會使用驗證者的公開金鑰,驗證認證中的簽名。

在本教學課程中,驗證程序只會聲明您授權部署映像檔。

如要建立認證,請按照下列步驟操作:

  1. 設定儲存登錄路徑和映像檔摘要的變數:

    Artifact Registry

    IMAGE_PATH="us-docker.pkg.dev/google-samples/containers/gke/hello-app"
    IMAGE_DIGEST="sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567"
    IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
    
  2. 如要建立認證,請執行下列步驟:

    PKIX Cloud KMS

    如要使用 Cloud KMS 金鑰建立認證,請執行下列指令:

    gcloud beta container binauthz attestations sign-and-create \
        --project="${PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="${ATTESTOR_NAME}" \
        --attestor-project="${PROJECT_ID}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    

    PKIX (本機金鑰)

    如要使用本機金鑰建立認證,請執行下列操作:

    1. 產生認證酬載:

      gcloud container binauthz create-signature-payload \
      --artifact-url=${IMAGE_TO_ATTEST} > /tmp/generated_payload.json
      

      酬載 JSON 檔案包含下列內容:

      {
      "critical": {
        "identity": {
          "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea
      882eb722c3be4"
        },
        "type": "Google cloud binauthz container signature"
      }
      }
      
    2. 如要使用 PKIX 私密金鑰簽署酬載並產生簽章檔案,請執行下列指令:

      openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
      

      簽章檔案是您在本指南稍早建立的酬載 JSON 檔案簽署版本。

    3. 建立及驗證認證:

      gcloud container binauthz attestations create \
        --project="${PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}" \
        --validate
      

      PUBLIC_KEY_ID 替換為您在上方「產生 PKIX 金鑰組」中找到的公開金鑰 ID。

      validate 旗標會檢查您在政策中設定的認證者是否可驗證認證。

  3. 確認認證是否已建立:

    gcloud container binauthz attestations list \
        --attestor=$ATTESTOR_NAME --attestor-project=$PROJECT_ID
    

如要進一步瞭解如何建立認證,請參閱建立認證

重新測試政策

再次將範例容器映像檔部署至叢集,測試政策。 這次您必須使用摘要 (而非 1.0latest 等標記) 部署映像檔,因為二進位授權會使用摘要來查詢認證。在此,二進位授權允許部署映像檔,因為已完成必要的認證。

如要部署映像檔,請按照下列步驟操作:

kubectl run hello-server --image ${IMAGE_TO_ATTEST} --port 8080

如要確認映像檔是否已部署,請執行下列步驟:

kubectl get pods

指令會列印類似以下的訊息,表示部署作業已成功:

NAME                            READY     STATUS    RESTARTS   AGE
hello-server-579859fb5b-h2k8s   1/1       Running   0          1m