1. 简介
Container Analysis 为容器提供漏洞扫描和元数据存储服务。扫描服务会对 Artifact Registry 和 Container Registry 中的映像执行漏洞扫描,然后存储生成的元数据并通过 API 使其可供使用。借助元数据存储,您可以存储来自不同来源(包括漏洞扫描、Google Cloud 服务和第三方提供商)的信息。
漏洞扫描可自动或按需执行:
- 启用自动扫描后,您每次将新映像推送到 Artifact Registry 或 Container Registry 时,都会自动触发扫描。发现新漏洞时,漏洞信息会持续更新。
- 启用按需扫描后,您必须运行一个命令来扫描本地映像或 Artifact Registry 或 Container Registry 中的映像。借助按需扫描功能,您可以灵活地选择容器扫描时间。例如,您可以扫描本地构建的映像并修复漏洞,然后再将其存储在注册表中。扫描结果最长可能需要 48 小时才能完成,而且扫描后漏洞信息不会更新。
将 Container Analysis 集成到 CI/CD 流水线中之后,您可以根据该元数据做出决策。例如,您可以使用 Binary Authorization 创建部署政策,以仅允许部署来自受信任注册表的合规映像。
学习内容
- 如何启用自动扫描
- 如何执行按需扫描
- 如何在构建流水线中集成扫描
- 如何为已获批准的图片签名
- 如何使用 GKE 准入控制器屏蔽映像
- 如何配置 GKE 以仅允许已签名的已获批准映像
2. 设置和要求
自定进度的环境设置
- 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。
- 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时更新。
- 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用
PROJECT_ID
标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。 - 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
- 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除整个项目。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
启动 Cloudshell Editor
本实验室专为与 Google Cloud Shell 编辑器搭配使用而设计和测试。如需访问编辑器,请执行以下操作:
- 访问 https://console.cloud.google.com 以访问您的 Google 项目。
- 点击右上角的 Cloud Shell 编辑器图标
- 窗口底部会打开一个新窗格
环境设置
在 Cloud Shell 中,设置项目 ID 和项目编号。将它们保存为 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,以便在访问 Artifact Registry 时使用您的 gcloud 凭据。
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 信息中心查看映像和漏洞结果。
- 在 Cloud 控制台中打开 Artifact Registry
- 点击 artifact-scanning-repo 以查看其内容
- 点击查看图片详情
- 点击图片的最新摘要
- 扫描完成后,点击相应映像的“漏洞”标签页
在“漏洞”标签页中,您会看到系统对您刚刚构建的映像执行自动扫描的结果。
自动扫描功能默认处于启用状态。探索 Artifact Registry 设置,了解如何关闭/开启自动扫描。
4. On-Demand Scanning
在很多情况下,您可能需要先运行扫描,然后才能将映像推送到代码库。例如,容器开发者可能会先扫描映像并修复问题,然后再将代码推送到源代码控制系统。在以下示例中,您将在本地构建和分析图片,然后再根据结果采取行动。
构建映像
在此步骤中,您将使用本地 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
运行持续集成流水线
提交 build 以进行处理,以验证在发现严重性为 CRITICAL 的漏洞时 build 是否会中断。
gcloud builds submit
审核 build 失败
您刚刚提交的 build 将会失败,因为映像包含严重漏洞。
在 Cloud Build 历史记录页面中查看构建失败情况
修复漏洞
更新 Dockerfile,以使用不包含严重漏洞的基础映像。
使用以下命令覆盖 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 流程
提交 build 以进行处理,以验证在未发现严重漏洞的情况下 build 是否会成功。
gcloud builds submit
审核 build 成功
您刚刚提交的 build 将会成功,因为更新后的映像不含任何严重漏洞。
在 Cloud Build 历史记录页面中查看 build 是否成功
查看扫描结果
在 Artifact Registry 中查看正常的映像
- 在 Cloud 控制台中打开 Artifact Registry
- 点击 artifact-scanning-repo 以查看其内容
- 点击查看图片详情
- 点击图片的最新摘要
- 点击相应映像的“漏洞”标签页
6. 为映像签名
创建证明者备注
认证者备注只是一小部分数据,可用作所应用签名类型的标签。例如,一条备注可能用于指明漏洞扫描,而另一条备注可能用于质量检查签收。签名流程中会引用该备注。
创建记事
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
证明者。因此,上述命令会返回两个证明程序: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"
您应该会在 Google Cloud 控制台的 KMS 页面上看到您的密钥。
现在,通过 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 以自动对映像进行证明
角色
将 Binary Authorization Attestor Viewer 角色添加到 Cloud Build 服务账号:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
将 Cloud KMS CryptoKey Signer/Verifier 角色添加到 Cloud Build 服务账号(基于 KMS 的签名):
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
将 Container Analysis Notes Attacher 添加到 Cloud Build 服务账号:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
准备自定义 build Cloud Build 步骤
您将在 Cloud Build 中使用“自定义 build”步骤来简化认证流程。Google 提供了此“自定义 build”步骤,其中包含用于简化流程的辅助函数。在使用前,自定义构建步骤的代码必须构建到容器中并推送到 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 流水线中添加认证步骤。
- 查看您要添加的新步骤。
仅限查看。不复制
#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'
- 使用更新后的完整流水线覆盖 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
运行 build
gcloud builds submit
在 Cloud Build 历史记录中查看 build
打开 Cloud 控制台,前往 Cloud Build 记录页面,查看最新的 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"
“全部允许”政策
首先,验证默认政策状态以及您是否能够部署任何映像
- 查看现有政策
gcloud container binauthz policy export
- 请注意,违规处置政策设置为
ALWAYS_ALLOW
evaluationMode: ALWAYS_ALLOW
- 部署示例以验证您是否可以部署任何内容
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- 验证部署是否成功
kubectl get pods
您将看到以下输出
- 删除部署
kubectl delete pod hello-server
“全部拒绝”政策
现在,更新该政策以禁止所有映像。
- 将当前政策导出到可修改的文件
gcloud container binauthz policy export > policy.yaml
- 更改政策
在文本编辑器中,将 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
- 打开终端并应用新政策,然后等待几秒钟以使更改传播
gcloud container binauthz policy import policy.yaml
- 尝试部署示例工作负载
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- 部署失败并显示以下消息
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
将政策还原为“全部允许”
在继续学习下一部分之前,请务必还原政策更改
- 更改政策
在文本编辑器中,将 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
- 应用已还原的政策
gcloud container binauthz policy import policy.yaml
9. 在 GKE 中屏蔽漏洞
在本部分中,您将结合之前学到的知识,使用 Cloud Build 实现 CI/CD 流水线,以便在签名映像并尝试部署之前扫描映像并检查是否存在漏洞。GKE 会使用 Binary Authorization 验证映像是否具有漏洞扫描签名,然后再允许映像运行。
更新 GKE 政策以要求进行认证
通过向 GKE BinAuth 政策添加 clusterAdmissionRules,要求映像由您的证明者签名
使用以下命令使用更新后的配置覆盖该政策。
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 以仅允许已签名的已获批准映像
后续步骤:
- 保护将映像部署到 Cloud Run 和 Google Kubernetes Engine 的操作 | Cloud Build 文档
- 快速入门:使用 GKE 配置 Binary Authorization 政策 | Google Cloud
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。