1. 简介

软件漏洞是指程序缺陷,可能会导致意外的系统故障,或让作恶方有机可乘,破解软件。Container Analysis 提供两种操作系统扫描方式,用于检测容器内的漏洞:
- 借助 On-Demand Scanning API,您可以手动扫描容器映像,以查找操作系统漏洞,扫描操作可在本地计算机执行,也可在 Container Registry 或 Artifact Registry 中远程执行。
- 借助 Container Scanning API,您可以自动检测操作系统漏洞,并在每次将映像推送到 Container Registry 或 Artifact Registry 时进行扫描。启用此 API 还会启用语言包扫描,以查找 Go 和 Java 漏洞。
借助 On-Demand Scanning API,您可以扫描本地计算机上存储的映像,也可以扫描 Container Registry 或 Artifact Registry 中远程存储的映像。这样,您就可以精细地控制要进行漏洞扫描的容器。您可以在 CI/CD 流水线中使用按需扫描来扫描映像,然后再决定是否将其存储在注册数据库中。
学习内容
在本实验中,您将:
- 使用 Cloud Build 构建映像
- 使用 Artifact Registry 存储和管理容器
- 利用自动漏洞扫描功能
- 配置按需扫描
- 在 Cloud Build 中向 CICD 添加映像扫描
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 免费试用计划的条件。
环境设置
在 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
3. 使用 Cloud Build 构建映像
在本部分中,您将创建一个自动化构建流水线来构建容器映像、扫描该映像,然后评估结果。如果未发现严重漏洞,则会将映像推送到仓库。如果发现严重漏洞,构建将失败并退出。
为 Cloud Build 服务账号提供访问权限
Cloud Build 需要有权访问 On-Demand Scanning 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"
创建并切换到工作目录
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
创建 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: ['-']
EOF
运行 CI 流水线
提交 build 以供处理
gcloud builds submit
查看 build 详情
构建流程开始后,在 Cloud Build 信息中心内查看进度。
- 在 Cloud 控制台中打开 Cloud Build
- 点击相应 build 即可查看内容
4. Artifact Registry for Containers
创建 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
更新 Cloud Build 流水线
修改您的 build 流水线,将生成的映像推送到 Artifact Registry
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: ['-']
# push 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']
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF
运行 CI 流水线
提交 build 以供处理
gcloud builds submit
5. 自动执行漏洞扫描
您每次将新映像推送到 Artifact Registry 或 Container Registry 时,都会自动触发制品扫描。漏洞信息会随着新漏洞的发现而持续更新。在本部分中,您将检查刚刚构建并推送到 Artifact Registry 的映像,并查看漏洞扫描结果。
查看映像详情
上一个构建流程完成后,在 Artifact Registry 信息中心查看映像和漏洞扫描结果。
- 在 Cloud 控制台中打开 Artifact Registry
- 点击 artifact-scanning-repo 以查看其内容
- 点击进入映像详情
- 点击进入映像的最新摘要
- 扫描完成后,点击相应映像的“漏洞”标签页
在“漏洞”标签页中,您会看到刚刚构建的映像的自动扫描结果。

默认情况下,系统会启用自动扫描功能。查看 Artifact Registry 设置,了解如何开启/关闭自动扫描。
6. 按需扫描
在将映像推送到仓库之前,您可能需要在各种场景下执行扫描。例如,容器开发者可能会扫描映像并修复发现的问题,然后再将代码推送到源代码控制系统。在下面的示例中,您将先在本地构建和分析映像,然后再根据结果采取行动。
构建映像
在此步骤中,您将使用本地 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)
输出包含大量有关映像中所有漏洞的数据。
标记严重问题
人类用户很少直接使用报告中存储的数据。该结果通常供自动化流程使用。使用以下命令读取报告详细信息,并在发现任何严重程度为 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
此命令的输出将为
Failed vulnerability check for CRITICAL level
7. 使用 Cloud Build 在 CICD 中进行扫描
为 Cloud Build 服务账号提供访问权限
Cloud Build 需要有权访问 On-Demand Scanning 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 流水线
提交 build 以供处理,验证在发现 CRITICAL 严重级别的漏洞时,构建会中断。
gcloud builds submit
查看构建失败
您刚刚提交的 build 将会失败,因为映像包含严重漏洞。
在 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 流程
提交 build 以供处理,验证在未发现 CRITICAL 严重级别的漏洞时,构建会成功。
gcloud builds submit
查看 build 是否成功
您刚刚提交的 build 将会成功,因为更新后的映像不包含任何 CRITICAL 严重级别的漏洞。
在 Cloud Build 历史记录页面中查看构建成功情况
查看扫描结果
查看 Artifact Registry 中的良好映像
- 在 Cloud 控制台中打开 Artifact Registry
- 点击 artifact-scanning-repo 以查看其内容
- 点击进入映像详情
- 点击进入映像的最新摘要
- 点击映像的“漏洞”标签页
8. 恭喜!
恭喜,您已完成此 Codelab!
所学内容:
- 使用 Cloud Build 构建映像
- Artifact Registry for Containers
- 自动漏洞扫描
- 按需扫描
- 使用 Cloud Build 在 CICD 中进行扫描
后续步骤:
- 保护 Cloud Run 和 Google Kubernetes Engine 中的映像部署 | Cloud Build 文档
- 快速入门:使用 GKE 配置 Binary Authorization 政策 | Google Cloud
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。
—
上次更新时间:2023 年 3 月 21 日