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 需要有权访问按需扫描 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
运行持续集成流水线
提交 build 以进行处理
gcloud builds submit
查看 build 详情
构建流程开始后,在 Cloud Build 信息中心内查看进度。
- 在 Cloud 控制台中打开 Cloud Build
- 点击 build 即可查看内容
4. 适用于容器的 Artifact Registry
创建 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
更新 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)
输出包含有关映像中所有漏洞的大量数据。
标记严重问题
人类很少直接使用报告中存储的数据。结果通常由自动化流程使用。使用以下命令读取报告详情,并记录是否发现了任何严重漏洞
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 需要有权访问按需扫描 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 以进行处理,以便在发现严重级别为“严重”的漏洞时验证 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
使用良好的映像运行持续集成流程
提交 build 以进行处理,以验证在未发现严重漏洞的情况下 build 是否会成功。
gcloud builds submit
检查构建成功与否
您刚刚提交的 build 将会成功,因为更新后的映像不含任何严重漏洞。
在 Cloud Build 历史记录页面中查看 build 是否成功
查看扫描结果
在 Artifact Registry 中查看正常的映像
- 在 Cloud 控制台中打开 Artifact Registry
- 点击 artifact-scanning-repo 以查看内容
- 点击查看图片详情
- 点击查看映像的最新摘要
- 点击映像的“漏洞”标签页
8. 恭喜!
恭喜,您已完成此 Codelab!
所学内容:
- 使用 Cloud Build 构建映像
- 适用于容器的 Artifact Registry
- 自动漏洞扫描
- 按需扫描
- 使用 Cloud Build 在 CICD 中进行扫描
后续步骤:
- 保护部署到 Cloud Run 和 Google Kubernetes Engine 的映像 |Cloud Build 文档
- 快速入门:使用 GKE 配置 Binary Authorization 政策 |Google Cloud
清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。
—
上次更新时间:2023 年 3 月 21 日