《OpenShift / RHEL / DevSecOps 汇总目录》
文本已在 OpenShift 4.17 + RHACS 4.6.1 环境中进行验证。
文章目录
本文使用在 OpenShift 中使用由 Jenkins、Nexus、Sonarqube、RHACS 组成的 DevSecOps CICD Pipeline 环境对应用镜像进行安全扫描检查。在发现安全违规后,通过升级应用使用 Java 库、基础镜像等手段修复应用镜像,同时对暂时无法修复的安全违规项目进行暂缓处理。

请在开始以下操作前先参照《OpenShift Security (2) - 安装 Red Hat Advanced Cluster Security(RHACS)》完成 RHACS 环境安装。
克隆 Git Repository
- 由于本文中需要对应用用到的配置进行修改,因此可将 https://github.com/liuxiaoyu-git/backend_quarkus 克隆的自己的 Git 账户下。
- 确认 code/src/main/docker/Dockerfile.jvm 文件中使用的是以下版本的镜像。如果不是,需要修改至 openjdk-11-rhel7:1.12-1
...
FROM registry.access.redhat.com/openjdk/openjdk-11-rhel7:1.12-1
...
- 确认 code/pom.xml 文件中的以下部分引用的是 2.13.3 版本的 jackson-databind 库。
...
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
...
安装 DevOps 环境
- 从 github 下载 openshift-demo:
$ git clone https://github.com/liuxiaoyu-git/openshift-demo && cd openshift-demo/bin
- 执行以下脚本创建 OpenShift 项目。
$ ./setup_cicd_projects.sh
安装配置 Nexus 环境
- 编辑 setup_nexus.sh 文件以下参数。可适当调整 NEXUS_PVC_SIZE 大小。因为会使用 Nexus 保存容器镜像,所以不要低于 10Gi。
NEXUS_PVC_SIZE="100Gi"
JENKINS_PVC_SIZE="10Gi"
SONAR_PVC_SIZE="10Gi"
NEXUS_VERSION=3.68.1 ## 为了能在 OpenShift 上部署成功,版本可能需要调整
- 执行命令安装 Nexus 环境。
$ ./setup_nexus.sh
- 完成安装后会提示 Nexus 的 admin 和 jenkins 用户的密码都保存在 nexus_password.txt 文件中。
- 执行以下命令,获取 Nexus 控制台的访问地址。然后用浏览器访问 Nexus 控制台,分别用 admin 和 jenkins 用户登录。
$ echo https://$(oc get route nexus -n ci-cd -o jsonpath='{.spec.host}')
- 在 Nexus 控制台中的 Users 页面中修改 admin 和 jenkins 用户的密码,然后将新的密码更新到 nexus_password.txt 文件中。
- 并确认在 Browse 页面中有 docker 的仓库,它便是 Nexus 的 Container Image Registry 仓库。下面 Jenkins 会将应用镜像保存到 Nexus 镜像库中。
- 执行以下命令,获取 Nexus 提供的 Image Registry 访问地址。
$ NEXUS_REGISTRY=$(oc get route nexus-registry -n ci-cd -o jsonpath='{.spec.host}') && echo $NEXUS_REGISTRY
- 执行命令,向 Nexus 镜像仓库导入镜像。注:原 voravitl 下的镜像已有变化,所以部分用了 dawnskyliu 用户下的镜像。
$ sudo yum install skopeo -y
$ NEXUS_PASSWORD=<PASSWORD>
$ allImages="backend:v1 backend:CVE-2020-36518 frontend-js:node log4shell:latest"
$ for image in $allImages
do
echo "############## Copy $image ##############"
skopeo copy --src-tls-verify=true --dest-tls-verify=false --src-no-creds --dest-username admin --dest-password $NEXUS_PASSWORD \
docker://quay.io/voravitl/$image docker://$NEXUS_REGISTRY/$image
done
$ allImages="backend:11-ubuntu frontend-js:v1 backend-native:v1 backend-native:v1-distroless"
$ for image in $allImages
do
echo "############## Copy $image ##############"
skopeo copy --src-tls-verify=true --dest-tls-verify=false --src-no-creds --dest-username admin --dest-password $NEXUS_PASSWORD \
docker://quay.io/dawnskyliu/$image docker://$NEXUS_REGISTRY/$image
done
- 在 Nexus 控制台进入 Browse 菜单,然后查看 docker 仓库,确认其中有导入的镜像。
- 在 RHACS 控制台进入 Integrations 菜单,然后找到并进入 Sonatype Nexus。点击 New Integration 按钮,然后在以下界面中使用 $NEXUS_REGISTRY 作为 Endpoint 创建一个 Nexus Integration。
安装 Jenkins 环境
执行命令,安装 Jenkins。登录用户和密码保存在名为 nexus-credential 的 secret 中。
$ ./setup_jenkins.sh
安装 Sonar 环境
执行命令,安装 Sonarqube。登录用户名和密码是 sonar/sonar。
$ ./setup_sonar.sh
在安装完 Jenkins、Nexus、Sonar 后确认在 ci-cd 项目中应该部署好了以下资源:
使用 RHACS 客户端扫描 Nexus 中的 Image
- 从 RHACS 控制台页面下载 RHACS 客户端程序 roxctl 。
- 在 RHACS 中的 Integration 中创建一个 API Token,其中 Role 选择 Admin 类型。将生成的内容复制到 bin 目录下的 acs-token 文件中。
- 执行命令,用客户端程序检查 Nexus 中的容器镜像违规情况。注意:由于会不断有新的CVE出现,因此结果可能有差异。
$ ROX_CENTRAL_ADDRESS=$(oc get route central -n stackrox -o jsonpath='{.spec.host}'):443 && echo $ROX_CENTRAL_ADDRESS
$ roxctl --insecure-skip-tls-verify -e ${ROX_CENTRAL_ADDRESS} image check --image=${NEXUS_REGISTRY}/backend:v1 --output=table --token-file=acs-token
Policy check results for image: nexus-registry-ci-cd.apps.cluster-k8qw5.k8qw5.sandbox638.opentlc.com/backend:v1
(TOTAL: 2, LOW: 1, MEDIUM: 0, HIGH: 1, CRITICAL: 0)
+--------------------------------+----------+--------------+--------------------------------+--------------------------------+--------------------------------+
| POLICY | SEVERITY | BREAKS BUILD | DESCRIPTION | VIOLATION | REMEDIATION |
+--------------------------------+----------+--------------+--------------------------------+--------------------------------+--------------------------------+
| Fixable Severity at least | HIGH | X | Alert on deployments with | - Fixable RHSA-2024:4078 (CVSS | Use your package manager to |
| Important | | | fixable vulnerabilities with | 7.8) (severity Important) | update to a fixed version in |
| | | | a Severity Rating at least | found in component 'python3' | future builds or speak with |
| | | | Important | (version 3.9.18-3.el9.x86_64), | your security team to mitigate |
| | | | | resolved by version | the vulnerabilities. |
| | | | | 0:3.9.18-3.el9_4.1 | |
| | | | | | |
| | | | | - Fixable RHSA-2024:4078 | |
| | | | | (CVSS 7.8) (severity | |
| | | | | Important) found in component | |
| | | | | 'python3-libs' (version | |
| | | | | 3.9.18-3.el9.x86_64), resolved | |
| | | | | by version 0:3.9.18-3.el9_4.1 | |
+--------------------------------+----------+--------------+--------------------------------+--------------------------------+--------------------------------+
| Red Hat Package Manager in | LOW | - | Alert on deployments with | - Image includes component | Run `rpm -e --nodeps $(rpm -qa |
| Image | | | components of the Red | 'microdnf' (version | '*rpm*' '*dnf*' '*libsolv*' |
| | | | Hat/Fedora/CentOS package | 3.9.1-3.el9.x86_64) | '*hawkey*' 'yum*')` in the |
| | | | management system. | | image build for production |
| | | | | - Image includes | containers. |
| | | | | component 'rpm' (version | |
| | | | | 4.16.1.3-29.el9.x86_64) | |
+--------------------------------+----------+--------------+--------------------------------+--------------------------------+--------------------------------+
WARN: A total of 2 policies have been violated
ERROR: failed policies found: 1 policies violated that are failing the check
ERROR: Policy "Fixable Severity at least Important" - Possible remediation: "Use your package manager to update to a fixed version in future builds or speak with your security team to mitigate the vulnerabilities."
ERROR: checking image failed after 3 retries: failed policies found: 1 policies violated that are failing the check
- 执行命令,用客户端程序扫描 Nexus 中的容器镜像 CVE。注意:由于会不断有新的CVE出现,因此结果可能有差异。
$ roxctl --insecure-skip-tls-verify -e ${ROX_CENTRAL_ADDRESS} image scan --image=${NEXUS_REGISTRY}/backend:v1 --output=table --token-file=acs-token
Scan results for image: nexus-registry-ci-cd.apps.cluster-k8qw5.k8qw5.sandbox638.opentlc.com/backend:v1
(TOTAL-COMPONENTS: 36, TOTAL-VULNERABILITIES: 50, LOW: 27, MODERATE: 22, IMPORTANT: 1, CRITICAL: 0)
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
| COMPONENT | VERSION | CVE | SEVERITY | LINK |
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
| arc | 3.11.3 | CVE-2005-2945 | LOW | https://nvd.nist.gov/vuln/detail/CVE-2005-2945 |
+ + +----------------+-----------+-------------------------------------------------------+
| | | CVE-2005-2992 | LOW | https://nvd.nist.gov/vuln/detail/CVE-2005-2992 |
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
...
...
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
| systemd-libs | 252-32.el9_4.x86_64 | CVE-2021-3997 | MODERATE | https://access.redhat.com/security/cve/CVE-2021-3997 |
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
| tar | 2:1.34-6.el9_1.x86_64 | CVE-2005-2541 | MODERATE | https://access.redhat.com/security/cve/CVE-2005-2541 |
+ + +----------------+-----------+-------------------------------------------------------+
| | | CVE-2023-39804 | LOW | https://access.redhat.com/security/cve/CVE-2023-39804 |
+--------------------------+--------------------------------------+----------------+-----------+-------------------------------------------------------+
WARN: A total of 50 unique vulnerabilities were found in 36 components
- 执行命令,用客户端程序检查 Deployment 的配置违规情况。
$ roxctl --insecure-skip-tls-verify -e ${ROX_CENTRAL_ADDRESS} deployment check --file=../manifests/backend-bad-example.yaml --token-file=acs-token
Policy check results for deployments: [backend-v2]
(TOTAL: 2, LOW: 0, MEDIUM: 2, HIGH: 0, CRITICAL: 0)
+--------------------------------+----------+---------------+------------+--------------------------------+--------------------------------+--------------------------------+
| POLICY | SEVERITY | BREAKS DEPLOY | DEPLOYMENT | DESCRIPTION | VIOLATION | REMEDIATION |
+--------------------------------+----------+---------------+------------+--------------------------------+--------------------------------+--------------------------------+
| No CPU request or memory limit | MEDIUM | - | backend-v2 | Alert on deployments that have | - CPU request set to 0 cores | Specify CPU request and memory |
| specified | | | | containers without CPU request | for container 'backend' | limit for your deployment. |
| | | | | or memory limit | | |
| | | | | | - Memory limit set to 0 MB for | |
| | | | | | container 'backend' | |
+--------------------------------+----------+---------------+------------+--------------------------------+--------------------------------+--------------------------------+
| Pod Service Account Token | MEDIUM | - | backend-v2 | Protect pod default service | - Deployment mounts the | Add |
| Automatically Mounted | | | | account tokens from compromise | service account tokens. | `automountServiceAccountToken: |
| | | | | by minimizing the mounting | | false` or a value distinct |
| | | | | of the default service | - Namespace has name 'default' | from 'default' for the |
| | | | | account token to only those | | `serviceAccountName` key |
| | | | | pods whose application | - Service Account is set to | to the deployment's Pod |
| | | | | requires interaction with the | 'default' | configuration. |
| | | | | Kubernetes API. | | |
+--------------------------------+----------+---------------+------------+--------------------------------+--------------------------------+--------------------------------
WARN: A total of 2 policies have been violated
在 Jenkins 中使用 RHACS 扫描镜像
为 Jenkins 创建访问 RHACS 的 Secret
执行命令,根据 acs-token 文件生成 secret,该 secret 会在 Jenkins 中被使用。
$ oc create secret generic stackrox-token -n ci-cd --from-file=token=acs-token
创建并运行基于 Jenkins CI/CD Pipeline 的构建配置
- 执行命令,先设置好自己的 Git 账户名,然后修改 backend-build-stackrox-pipeline.yaml 文件的 NEXUS_REGISTRY 和 GIT_ACCOUNT,最后创建基于 Jenkins CI/CD Pipeline 的 BuildConfig 对象。
$ GIT_ACCOUNT=liuxiaoyu-git
$ cat ../manifests/backend-build-stackrox-pipeline.yaml | \
sed 's/value: NEXUS_REGISTRY/value: '$NEXUS_REGISTRY'/' | \
sed 's/GIT_ACCOUNT/'${GIT_ACCOUNT}'/' | \
oc create -n ci-cd -f -
- 执行以下命令,创建基于 pipeline 流程的构建配置。
$ oc get buildconfig -n ci-cd
NAME TYPE FROM LATEST
backend-build-stackrox-pipeline JenkinsPipeline Git@cve 1
- 执行命令,运行 backend-build-stackrox-pipeline。或在控制台的 “构建配置” 中找到 backend-build-stackrox-pipeline,然后点击 “开始构建”菜单。
$ oc start-build backend-build-stackrox-pipeline
- 此时控制台会转到 “构建” 页面。如果顺利的话,Jenkins Pipeline 会在运行到 Scan Image 步骤提示错误。
- 点击上图的 “查看日志” 链接,可以跳转到 Jenkins 控制台。在用登录 OpenShift 相同的用户和密码登录后,可在 Jenkins 控制台中查看 Pipeline 运行实例中的 Console Output 页面。确认可以看发现构建的镜像中包含的 Violation 违规项目的提示,最后 Pipeline 运行状态是 FAILURE。
说明:如果在 Jenkins 中安装了 Blue Ocean 插件,可以看到以下执行跟踪页面。
- 确认此时在 Nexus 中的 docker repository 中也有生成的 tag 为 1.0.0-1 容器镜像了。
基础镜像升级加固
- 在OpenShift 中的 ci-cd 项目中查看名为 backend 的 BuildConfig 构建配置,可以看出它使用了 “src/main/docker/Dockerfile.jvm” 作为 docker 文件。
strategy:
type: Docker
dockerStrategy:
dockerfilePath: src/main/docker/Dockerfile.jvm
- 在 git repository 中查看 code/src/main/docker/Dockerfile.jvm 文件,确认其用了 registry.access.redhat.com/openjdk/openjdk-11-rhel7:1.12-1 镜像作为基础镜像。
- 访问以下 Red Hat 官方地址查看 registry.access.redhat.com/openjdk/openjdk-11-rhel7:1.12-1 镜像的安全评级和包括的风险项目。注意:有可能会比下图包含的安全风险更多。
https://catalog.redhat.com/software/containers/openjdk/openjdk-11-rhel7/5bf57185dd19c775cddc4ce5?architecture=amd64&tag=1.12-1&container-tabs=security
- 查看此时 RedHat 提供的 openjdk-11-rhel7 镜像最新版是 registry.access.redhat.com/openjdk/openjdk-11-rhel7:1.14-3。注意:如果 RedHat 已出其他新版镜像,为了后面能演示出 RHACS 的 Defer 功能,可以选择一个还有少量漏洞的镜像使用。
- 在 git repository 中修改 code/src/main/docker/Dockerfile.jvm 文件,将使用的镜像改为较新的 “openjdk-11-rhel7:1.14-3”。
Java 应用库更新加固
- 确认 code/pom.xml 文件中的以下部分引用的是 2.13.3 版本的 jackson-databind 库。
...
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
...
- 访问 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind,确实此时 jackson-databind 的 2.13.3 版中包含 2 个 vunerabilites。可进一步查看可知包含的 CVE-2022-42003 和 CVE-2022-42004 就是本文第一次运行 Jenkins Pipeline 报的 VIOLATION 中前两项的 CVE。
- 修改 code/pom.xml 文件中使用 jackson-databind 的版本。根据上图可知 2.14.0-rc2 当前不含 vulnerability,因此可以使用该版本。
...
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0-rc2</version>
</dependency>
...
延期处理当前无法解决的 CVE
- 再次执行命令,运行 backend-build-stackrox-pipeline。确认 Jenkins Pipeline 可以成功完成运行,这说明 master 分支的应用代码不再有违规了。
$ oc start-build backend-build-stackrox-pipeline
- 执行完后确认还是在 Scan image 步骤失败。查看 Jenkins 日志,可以看到下图应用镜像扫描结果,其中提示由 “expat” 组件引起编号为 “RHSA-2022:6834” 的违规。这和前面步骤中查看到的所用新版基础镜像 registry.access.redhat.com/openjdk/openjdk-11-rhel7:1.14-3 中包含的 vulnerability 编号一致。
- 有些情况即使使用了新版基础镜像,但其中依然含有为修复的漏洞;有些情况是应用只能使用包含漏洞的镜像。为了能在这些情况下 Jenkins Pipeline 能完成应用镜像发布,需要在 RHACS 中暂时屏蔽对这些不能修复的漏洞进行扫描。
- 在 RHACS 控制台进入 Vulnerability Management 中的 Dashboard 页面,然后点击下图红框突出的 CVE 区域。
- 在 CVES 页面中按下图找到编号为 “RHSA-2022:6834” 的 CVE。在选中 RHSA-2022:6834 项目后点击 “DEFER AND APPROVE” 按钮,在下拉项中选择 “1 Week” 即可。说明:如果镜像还有其他当前不好修复的 CVE,都可使用此方法对它们暂时延期扫描。
再次运行 Jenkins Pipeline
- 再次执行命令运行 backend-build-stackrox-pipeline,确认 Jenkins Pipeline 可以成功完成运行。
$ oc start-build backend-build-stackrox-pipeline
如果在 Jenkins 中安装了 Blue Ocean 插件,可以看到以下执行结果。
- 确认在 dev 项目中已经有部署成功的 backend 应用了。
排查问题
以下问题是由于 ACS 的 scanner 组件无法访问造成的,请确认该组件对应的 Pod 运行正常。
ERROR: checking image failed after 3 retries: could not check build-time alerts: rpc error: code = Internal desc = image enrichment error: error scanning image: nexus-registry-ci-cd.apps.cluster-k8qw5.k8qw5.sandbox638.opentlc.com/backend:v1 error: scanning "nexus-registry-ci-cd.apps.cluster-k8qw5.k8qw5.sandbox638.opentlc.com/backend:v1" with scanner "Stackrox Scanner": Get "https://scanner.stackrox.svc:8080/scanner/sha/sha256:1fb8cb4ceb8153b374d85017c83f167fd99ce7039b6e2162d64de1c16e1d06de": dial tcp 172.30.5.237:8080: i/o timeout
演示视频
参考
https://github.com/rhthsa/openshift-demo/blob/main/acs.md
https://gitlab.com/ocp-demo/backend_quarkus/-/blob/master/docs/JENKINS.md