Python 和 SLSA 💃

软件工件的供应链层 (SLSA) 是一个用于生成和验证软件工件来源的工具框架。在 Python 生态系统中,有两种主要类型的软件工件:轮子(wheels)和源代码分发(distributions)。

我们如何使用 SLSA 框架来生成和验证 Python 工件的来源呢?

本篇文章是由我翻译、并根据我的实践和理解而形成的。英文原文在这里:https://sethmlarson.dev/python-and-slsa

内容

  1. 构建纯净的Python包
  2. 生成出处证明
  3. 上传到PyPI
  4. 验证Python包的来源
  5. 二进制Python包
  6. 文中用到的项目

注意:本文主要介绍托管在 GitHub 上的 Python 项目。SLSA 框架可通过 GitHub Actions 来实现开箱即用,只需最少的配置即可完成。

如果你对 Python 打包的术语或流程感到好奇,Python 打包用户指南 是了解更多信息的最佳场所。

下面是维护人员和用户的端到端工作流程,从构建 distributions、生成出处证明、验证出处、发布到 PyPI,以及在验证其出处后安装 wheel。让我们一起完成每一步!

端到端流程

构建纯净的Python包

纯 Python 包通常只有两个工件:源代码 distribution 和纯 Python wheel。纯 Python 包可以使用名为 build 的包从源代码构建。

下面是 GitHub Actions job 定义,它构建纯 Python Wheel Package 和源代码 distribution,并为每个工件创建 SHA-256 哈希值:

jobs:
build:
steps:
- uses: actions/checkout@...
- uses: actions/setup-python@...
with:
python-version: 3.x
- run: |
# 安装 build,创建 sdist 和 wheel
python -m pip install build
python -m build

# 收集所有文件的哈希值
cd dist && echo "hashes=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT
- uses: actions/upload-artifacts@...
with:
path: ./dist

这里将 build 完的 wheel package 上传到 GitHub Artifacts 存起来,用作后续在 “上传到PyPI” job 中使用。另外还将 dist 下的所有文件的哈希值存储在 hashes 用作后续 job provenance 的输入。

注意: SLSA 使用 sha265sum 的输出作为出处证明中 subject-base64 字段的输入。sha256sum 的输出是一个或多个对散列 + 名称。

生成出处证明

现在我们已经构建了 sdist 和 wheel,我们可以从文件哈希生成来源证明。

因为我们需要将 Build 阶段的的输出作为这里生成出处的输入,因此这里使用了 needs 选项来作为 job provenance 执行的前提条件。可以看到上面生成的哈希值在这里被 subject-base64 所使用。

jobs:
provenance:
needs: [build]
uses: slsa-framework/slsa-github-builder/.github/workflows/generator_generic_slsa3.yml@v1.9.0
permissions:
# 需要检测 GitHub 操作环境
actions: read
# 需要通过 GitHub OIDC 创建出处
id-token: write
# 需要创建并上传到 GitHub Releases
contents: write
with:
# 生成的 package SHA-256 哈希值
subject-base64: ${{ provenance.needs.build.output.hashes }}
# 将出处文件上传到 GitHub Release
upload-assets: true

你会注意到,这并没有像 GitHub 工作流那样定义任何单独的步骤。相反 SLSA builders 使用可重用工作流功能来证明给定的 builders 行为不能被用户或其他进程修改。

出处证明文件是 JSON lines,以 .intoto.jsonl 结尾。*.intoto.jsonl 文件可以包含多个工件的证明,也可以在同一文件中包含多个出处证明。该 .jsonl 格式意味着该文件是一个 “JSON lines” 文件,即每行一个 JSON 文档。

注意:这里有一点令人困惑的是 GitHub job 中的 id-token 需要 write 权限才能读取 GitHub OIDC 令牌。read 不允许你读取 OIDC…🤷。有关 id-token 权限的更多信息,请参阅 GitHub 文档

上传到PyPI

我们使用官方 pypa/gh-action-pypi-publish GitHub Action 将 wheel 包上传到 PyPI。

请注意,这个 publish job 需要在 buildprovenance 都完成后开始执行,这意味着我们可以假设 provenance job 已经为我们起草了 GitHub Release(因为 upload-assets: true 的设置),并且我们可以假设该 job 已成功。如果不先创建来 provenance 文件,我们不想将这些 wheel 包上传到 PyPI,因此我们最后上传到 PyPI。

发布

publish:
needs: ["build", "provenance"]
permissions:
contents: write
runs-on: "ubuntu-latest"
steps:
# 下载已构建的 distributions
- uses: "actions/download-artifact@..."
with:
name: "dist"
path: "dist/"
# 上传 distributions 到 GitHub Release
- env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
gh release upload ${{ github.ref_name }} \
dist/* --repo ${{ github.repository }}
# 发布 distributions 到 PyPI
- uses: "pypa/gh-action-pypi-publish@..."
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}

请注意,该 publish job 需要在开始之前完成 build 和作业。provenance 这意味着我们可以假设出处作业已经为我们创建了 GitHub 发布草案(感谢该 upload-assets: true 设置),并且我们可以假设该作业已成功。如果不先创建来源文件,我们不想将这些发行版上传到 PyPI,因此我们最后上传到 PyPI。

验证Python包的来源

让我们使用一个真正的 Python 项目来验证它的出处。以 urllib3 项目为例,它在 GitHub Releases 发布了版本中包含出处证明,这里演示的是使用它的最新版本 2.1.0

首先我们需要下载 slsa-verifier 用来验证出处。下载完该 slsa-verifier 工具后,让我们从 PyPI 获取 urllib3 wheel 包,而不使用 pip download. 我们使用该 --only-binary 选项强制 pip 下载 wheel。

安装

python3 -m pip download --only-binary=:all: urllib3
Collecting urllib3
Downloading urllib3-2.1.0-py3-none-any.whl.metadata (6.4 kB)
Downloading urllib3-2.1.0-py3-none-any.whl (104 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 104.6/104.6 kB 761.0 kB/s eta 0:00:00
Saved ./urllib3-2.1.0-py3-none-any.whl
Successfully downloaded urllib3

下载软件包后,我们需要从 GitHub 版本下载出处证明。我们需要使用与包版本相同的 GitHub Release 来确保获得正确的出处证明,因此 tag 也是 2.1.0。

curl --location -O https://github.com/urllib3/urllib3/releases/download/2.1.0/multiple.intoto.jsonl

该出处文件的名称为 multiple.intoto.jsonl,这是一个包含多个工件证明的出处证明的标准名称。对于 Python 项目来说几乎总是如此,因为几乎总是有一个源代码 distribution 和至少一个 wheel。

此时,我们当前的工作目录中应该有两个文件:wheel 和出处证明,ls 浏览一下确保已经准备好了:

ls
multiple.intoto.jsonl urllib3-2.1.0-py3-none-any.whl

从这里我们可以使用 slsa-verifier 来验证出处。我们可以验证最重要的事情,即哪个 GitHub 仓库实际构建了 wheel,以及其他信息,例如 git 标签、分支和建造者 ID:

源存储库 (--source-uri)
建造者 ID (--builder-id)
Git 分支 (--source-branch)
git 标签 (--source-tag)

因此,如果我们想验证轮子的源存储库,我们可以使用 --source-uri。当然还可以验证 --builder-id--source-branch--source-tag。具体我的测试目前 --builder-id--source-branch 似乎有问题。

# 这里仅验证 GitHub 仓库
slsa-verifier verify-artifact --provenance-path multiple.intoto.jsonl --source-uri github.com/urllib3/urllib3 urllib3-2.1.0-py3-none-any.whl
Verified signature against tlog entry index 49513169 at URL: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a08c2f012d69948ed5d12e8e020852bb7936ea9208d684688e5108cca859a3302
Verified build using builder "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.9.0" at commit 69be2992f8a25a1f27e49f339e4d5b98dec07462
Verifying artifact urllib3-2.1.0-py3-none-any.whl: PASSED

PASSED: Verified SLSA provenance

成功了!🥳 我们已经验证了这个 wheel 的出处,所以现在我们可以放心的安装它,因为我们知道它是按照我们的预期构建的:

python3 -m pip install urllib3-2.1.0-py3-none-any.whl 
Defaulting to user installation because normal site-packages is not writeable
Processing ./urllib3-2.1.0-py3-none-any.whl
Installing collected packages: urllib3
Attempting uninstall: urllib3
Found existing installation: urllib3 2.0.5
Uninstalling urllib3-2.0.5:
Successfully uninstalled urllib3-2.0.5
Successfully installed urllib3-2.1.0

二进制Python包

Python wheel 并不全是纯 Python!Python 的最大优势之一是作为 C、C++、Fortran、Rust、Go(等)的粘合语言,与其他一些编程语言相比,Python 的打包和起源故事变得更加复杂。

需要为多个平台、架构构建二进制 wheel,如果项目无法使用稳定的 ABI ,则需要为每个新的 Python 版本编译新的 wheel。要了解在这种情况下项目需要多少个 wheel,你可以查看 MarkupSafe,它在 v2.1.3 中提供了近 60 个wheel。当新的 Python 版本发布时,至少还会有 10 个版本来覆盖 Python 3.12 的所有平台。

不幸的是,这意味着我们需要在初始版本发布后的某个时间创建新的工件,而 SLSA 中没有一个简单的办法。这个问题有两种解决方案:

  • 为包创建一个新版本,而不仅仅是新 wheels。
  • 构建新的 wheels 并创建新的出处证明。

创建新版本

最简单的方法是在将 cibuildwheel GitHub Action 更新到最新版本后为包创建一个新版本以支持所有新的 Wheel 目标。这将创建一个新的来源证明、sdist 和 wheel。然而,如果项目的源代码没有任何改变,这感觉像是一个不幸的结果。

cibuildwheel

与新轮子相比,新版本会引起更多的流失:

  • 维护人员的额外工作
  • 存储和计算资源(PyTorch 的每个版本大约有 6GB 的 wheels
  • 依赖者需要更新锁定文件(依赖机器人疲劳,有人吗?)
  • 下游重新打包和分发

发布后wheels的出处

那么,如果我们不想仅仅为了新轮子的出处而创建新版本,该怎么办呢?

Markupsafe 的解决方案是添加一个手动 workflow_dispatch 触发器来运行典型的 wheel 构建工作流程,但配置为仅为给定的 Python 版本(即 cp312 CPython 3.12)构建新的 wheels。然后这些 wheels 会像平常一样通过 SLSA 进行证明并上传到 PyPI,但新的出处证明文件会添加到现有的 GitHub 发布工件中。

这是有效的,因为 PyPI 上的所有工件都有出处证明。有一些缺点:

  • 新的出处证明位于 GitHub Release 的单独工件中,而不是现有的出处证明中。这意味着想要验证新车轮来源的用户可能需要一些手动发现和步骤来下载正确的来源证明文件。
  • 通常新的架构或平台需要新版本的 cibuildwheel。由于需要更新源代码才能升级正在 cibuildwheel 使用的版本,因此过去版本的 git 标签将与构建新轮子所需的确切 git 提交不匹配。这意味着出处证明不会包含有关 git 标签的信息,因此使用该 --source-tag 选项进行验证将无法按预期进行。

上述第一点的另一个潜在解决方案是创建一个全新的来源证明,其中包含新旧工件的哈希值。

文中用到的项目

以下这些是本文使用的所有项目和工具:

以下项目是用来展示如何在 GitHub Actions 中针对 Python 项目配置 SLSA:


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

Problems and solutions when upgrading XLC from 10.1 to IBM Open XL C/C++ for AIX 17.1.0

In this article, I would like to document the problems encountered when upgrading from IBM XLC 10.1 to XLC 17.1 (IBM Open XL C/C++ for AIX 17.1.0) and how to fix the following 12 errors.

If you’ve encountered any other errors, feel free to share your comments with or without a solution.

1. Change cc to ibm-clang

First you need to change all the related cc to ibm-clang in the the global Makefile. for example:

- CC=cc
- CXX=xlC_r
- XCC=xlC_r
- MAKE_SHARED=xlC_r
+ CC=ibm-clang
+ CXX=ibm-clang_r
+ XCC=ibm-clang_r
+ MAKE_SHARED=ibm-clang_r

And check following link of Mapping of options to map new Clang options if any.

2. error: unknown argument: ‘-qmakedep=gcc’

- GEN_DEPENDENTS_OPTIONS=-qmakedep=gcc  -E -MF $@.1 > /dev/null
+ GEN_DEPENDENTS_OPTIONS= -E -MF $@.1 > /dev/null

3. should not return a value [-Wreturn-type]

- return -1;
+ return;

4. error: non-void function ‘main’ should return a value [-Wreturn-type]

- return;
+ return 0;

5. error: unsupported option ‘-G’ for target ‘powerpc64-ibm-aix7.3.0.0’

- LIB_101_FLAGS := -G 
+ LIB_101_FLAGS := -shared -Wl,-G

6. Undefined symbol (libxxxx.so)

- LIB_10_FLAGS := -bexport:$(SRC)/makefiles/xxxx.def
+ LIB_10_FLAGS := -lstdc++ -lm -bexport:$(SRC)/makefiles/xxxx.def

7. unsupported option -qlongdouble

- drv_connect.c.CC_OPTIONS=$(CFLAGS) -qlongdouble -brtl
+ drv_loadfunc.c.CC_OPTIONS=$(CFLAGS) $(IDIR) -brtl

8. Undefined symbol: ._Z8u9_closei

- extern int u9_close(int fd) ;
+ extern "C" int u9_close(int fd) ;

9. ERROR: Undefined symbol: .pow

- CXXLIBES = -lpthread -lC -lstdc++
+ CXXLIBES = -lpthread -lC -lstdc++ -lm

10. ‘main’ (argument array) must be of type ‘char **’

- d_char *argv[];
+ char *argv[];

11. first parameter of ‘main’ (argument count) must be of type ‘int’

- int main(char *argc, char *argv[])
+ int main(int argc, char *argv[])

12. ERROR: Undefined symbol: ._ZdaPv

- LIB_3_LIBS	:= -lverse -llog_nosig
+ LIB_3_LIBS := -lverse -llog_nosig -lstdc++

转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

2022-23 世界质量报告(World Quality Report)

2202-23 世界质量报告(World Quality Report 简称 WQR)是一项全球研究,不论是作为软件测试、开发工程师,关注这类软件质量报告可以帮助我们快速了解软件行业的现状和趋势。

七个主题

今年的 WQR 的关键趋势和推荐包括包括以下七个关键建议:

  • 敏捷质量调配 (DONE)
  • 质量自动化 (DONE)
  • 测试基础设施测试和配置 (DONE)
  • 测试数据提供和数据验证 (WIP)
  • 质量和可持续的 IT (NOT START)
  • 新兴技术趋势的质量工程 (NOT START)
  • 价值流管理 (NOT START)

Read More

解决通过 Jenkins Artifactory plugin 上传 artifacts 失败的问题 “unable to find valid certification path to requested target”

最近遇到了通过 Jenkins agent 无法上传 artifacts 到 Artifactory 的情况,具体错误如下:

[2023-09-11T08:21:53.385Z] Executing command: /bin/sh -c git log --pretty=format:%s -1
[2023-09-11T08:21:54.250Z] [consumer_0] Deploying artifact: https://artifactory.mycompany.com/artifactory/generic-int-den/my-project/hotfix/1.2.0.HF5/3/pj120_bin_opt_SunOS_3792bcf.tar.Z

[2023-09-11T08:21:54.269Z] Error occurred for request GET /artifactory/api/system/version HTTP/1.1: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
[2023-09-11T08:21:54.282Z] Error occurred for request PUT /artifactory/generic-int-den/my-project/hotfix/1.2.0.HF5/3/pj120_bin_opt_SunOS_3792bcf.tar.Z;build.timestamp=1694418199972;build.name=hotfix%2F1.2.0.HF5;build.number=3 HTTP/1.1: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
[2023-09-11T08:21:54.284Z] [consumer_0] An exception occurred during execution:
[2023-09-11T08:21:54.284Z] java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[2023-09-11T08:21:54.284Z] at org.jfrog.build.extractor.clientConfiguration.util.spec.SpecDeploymentConsumer.consumerRun(SpecDeploymentConsumer.java:44)
[2023-09-11T08:21:54.284Z] at org.jfrog.build.extractor.producerConsumer.ConsumerRunnableBase.run(ConsumerRunnableBase.java:11)
[2023-09-11T08:21:54.284Z] at java.lang.Thread.run(Thread.java:745)
[2023-09-11T08:21:54.285Z] Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这个问题产生的原因是通过 HTTPS 来上传文件的时候没有通过 Java 的安全认证。解决这个问题的办法就是重新生成认证文件,然后导入即可,具体的步骤如下。

生成安全认证(Security Certificate)文件

步骤如下:

  1. 首先生成通过浏览器打开的你的 Artifactory 网址
  2. 在网址的左侧应该有一个锁的图标,点击 Connection is secure -》Certificate is valid -》Details -》 Export
  3. 选择 DER-encoded binary, single certificate (*.der) 生成认证文件

比如我生成的安全认证文件的名字叫:artifactory.mycompany.der(名字可以任意起,只要后缀名不变即可)

通过命令行导入安全认证

登录到那台有问题的 Solaris agent,上传 artifactory.mycompany.der 到指定目录下,然后找到 cacerts 的路径,执行如下命令:

root@mysolaris:/# keytool -import -alias example -keystore /usr/java/jre/lib/security/cacerts -file /tmp/artifactory.mycompany.der
# 然后选择 yes

这时候会提示你输入密码,默认密码为 changeit,输入即可。然后重启你的 JVM 或是 VM。等再次通过该 Agent 上传 artifacts,一切恢复正常。

可参考: https://stackoverflow.com/questions/21076179/pkix-path-building-failed-and-unable-to-find-valid-certification-path-to-requ


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

解决在 AIX 通过 Jenkins agent git clone 失败的问题

最近又遇到了在 AIX 上通过 Jenkins agent 无法下载代码的情况,报了如下错误:

16:42:47  Caused by: hudson.plugins.git.GitException: Command "git init /disk1/agent/workspace/e_feature-aix-ci-build" returned status code 255:
16:42:47 stdout:
16:42:47 stderr: exec(): 0509-036 Cannot load program git because of the following errors:
16:42:47 0509-150 Dependent module /usr/lib/libiconv.a(libiconv.so.2) could not be loaded.
16:42:47 0509-152 Member libiconv.so.2 is not found in archive
16:42:47
16:42:47 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2734)
16:42:47 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2660)
16:42:47 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2656)
16:42:47 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommand(CliGitAPIImpl.java:1981)
16:42:47 at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$5.execute(CliGitAPIImpl.java:1047)

上次遇到在 AIX 遇到的 git clone 问题总结在这里 https://shenxianpeng.github.io/2021/06/git-clone-failed-on-aix/

而我在 AIX 机器上手动执行 git clone 命令却没有这个错误发生,从失败的 log 和 ldd /usr/bin/git 发现 libiconv.a 的路径不同,推测问题应该出在 LIBPATH 环境变量上。

因为在本地(AIX)执行 git 命令的时候 LIBPATH 是为空,如果设置了 LIBPATH 路径为 /usr/lib/ 会出上面一样的错误。

$ ldd /usr/bin/git
/usr/bin/git needs:
/usr/lib/libc.a(shr_64.o)
/usr/lib/libpthreads.a(shr_xpg5_64.o)
/opt/freeware/lib/libintl.a(libintl.so.8)
/opt/freeware/lib/libiconv.a(libiconv.so.2)
/opt/freeware/lib/libz.a(libz.so.1)
/unix
/usr/lib/libcrypt.a(shr_64.o)
/opt/freeware/lib64/libgcc_s.a(shr.o)
$

但 Jenkins agent 在执行的时候有默认的 LIBPATH,查看这个变量可以通过 Jenkins Agent 上的 Script Console 执行如下命令打印出来

println System.getenv("LIBPATH")
# 返回的结果 
/usr/java8_64/jre/lib/ppc64/j9vm:/usr/java8_64/jre/lib/ppc64:/usr/java8_64/jre/../lib/ppc64:/usr/java8_64/jre/lib/icc:/usr/lib

其中果然有 /usr/lib,这导致了 git 是去找 /usr/lib/libiconv.a 而不是 /opt/freeware/lib/libiconv.a

我尝试过很多种办法但最终还是无法在 Jenkins agent 在 git clone 的时候 unset LIBPATH,包括:

  1. 重新 link,将 /usr/lib/libiconv.a 链接到 /opt/freeware/lib/libiconv.a
mv /usr/lib/libiconv.a /usr/lib/libiconv.a.bak
ln -s /opt/freeware/lib/libiconv.a /usr/lib/libiconv.a
  1. 在 pipeline 中使用 withEnv 设置 LIBPATH 为空
withEnv(['LIBPATH=\'\'']) {
checkout scm
}
  1. 在 Agent 配置页面上尝试通过 Environment variables 来修改 LIBPATH(这个看起来像是 Jenkins 的一个 bug JENKINS-69821)

  2. 在配置 Jenkins agent 页面通过添加 export LIBPATH="" && 到 Prefix Start Agent Command 均不起作用。

最后是通过在 AIX 更新 Git 从版本 2.39.3 升级到 2.40.0 解决了这个错误,这有点巧合并没有真正把 Jenkins agent 的覆盖默认环境变量的问题给解决,但好在这个问题已经没有了。

仅此记录一下,防止以后遇到同样的错误不至于从头开始尝试,也希望这个记录也可能帮助到你。


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

Upload artifacts failed to Artifactory from AIX

Recently my CI pipeline suddenly does not work on AIX 7.1 with error Caused by: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath..

Click to see more details about the failure log.
22:13:30  Executing command: /bin/sh -c git log --pretty=format:%s -1
22:13:36 [consumer_0] Deploying artifact: https://artifactory.company.com/artifactory/generic-int-den/myproject/PRs/PR-880/1/myproject_bin_rel_AIX_5797b20.tar.Z
22:13:36 Error occurred for request GET /artifactory/api/system/version HTTP/1.1: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error.
22:13:36 Error occurred for request PUT /artifactory/generic-int-den/myproject/PRs/PR-880/1/cpplinter_bin_rel_AIX_5797b20.tar.Z;build.timestamp=1693273923987;build.name=PR-880;build.number=1 HTTP/1.1: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error.
22:13:36 [consumer_0] An exception occurred during execution:
22:13:36 java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at org.jfrog.build.extractor.clientConfiguration.util.spec.SpecDeploymentConsumer.consumerRun(SpecDeploymentConsumer.java:44)
22:13:36 at org.jfrog.build.extractor.producerConsumer.ConsumerRunnableBase.run(ConsumerRunnableBase.java:11)
22:13:36 at java.lang.Thread.run(Thread.java:785)
22:13:36 Caused by: javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at com.ibm.jsse2.j.a(j.java:3)
22:13:36 at com.ibm.jsse2.as.a(as.java:213)
22:13:36 at com.ibm.jsse2.C.a(C.java:339)
22:13:36 at com.ibm.jsse2.C.a(C.java:248)
22:13:36 at com.ibm.jsse2.D.a(D.java:291)
22:13:36 at com.ibm.jsse2.D.a(D.java:217)
22:13:36 at com.ibm.jsse2.C.r(C.java:373)
22:13:36 at com.ibm.jsse2.C.a(C.java:352)
22:13:36 at com.ibm.jsse2.as.a(as.java:752)
22:13:36 at com.ibm.jsse2.as.i(as.java:338)
22:13:36 at com.ibm.jsse2.as.a(as.java:711)
22:13:36 at com.ibm.jsse2.as.startHandshake(as.java:454)
22:13:36 at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
22:13:36 at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
22:13:36 at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
22:13:36 at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
22:13:36 at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
22:13:36 at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
22:13:36 at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
22:13:36 at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
22:13:36 at org.apache.http.impl.execchain.ServiceUnavailableRetryExec.execute(ServiceUnavailableRetryExec.java:85)
22:13:36 at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
22:13:36 at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
22:13:36 at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
22:13:36 at org.jfrog.build.client.PreemptiveHttpClient.execute(PreemptiveHttpClient.java:76)
22:13:36 at org.jfrog.build.client.PreemptiveHttpClient.execute(PreemptiveHttpClient.java:64)
22:13:36 at org.jfrog.build.client.JFrogHttpClient.sendRequest(JFrogHttpClient.java:133)
22:13:36 at org.jfrog.build.extractor.clientConfiguration.client.JFrogService.execute(JFrogService.java:112)
22:13:36 at org.jfrog.build.extractor.clientConfiguration.client.artifactory.services.Upload.execute(Upload.java:77)
22:13:36 at org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager.upload(ArtifactoryManager.java:267)
22:13:36 at org.jfrog.build.extractor.clientConfiguration.client.artifactory.ArtifactoryManager.upload(ArtifactoryManager.java:262)
22:13:36 at org.jfrog.build.extractor.clientConfiguration.util.spec.SpecDeploymentConsumer.consumerRun(SpecDeploymentConsumer.java:39)
22:13:36 ... 2 more
22:13:36 Caused by: com.ibm.jsse2.util.h: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at com.ibm.jsse2.util.f.a(f.java:107)
22:13:36 at com.ibm.jsse2.util.f.b(f.java:143)
22:13:36 at com.ibm.jsse2.util.e.a(e.java:6)
22:13:36 at com.ibm.jsse2.aA.a(aA.java:99)
22:13:36 at com.ibm.jsse2.aA.a(aA.java:112)
22:13:36 at com.ibm.jsse2.aA.checkServerTrusted(aA.java:28)
22:13:36 at com.ibm.jsse2.D.a(D.java:588)
22:13:36 ... 29 more
22:13:36 Caused by: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:422)
22:13:36 at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
22:13:36 at com.ibm.jsse2.util.f.a(f.java:120)
22:13:36 ... 35 more
22:13:36 Caused by: java.security.cert.CertPathValidatorException: The certificate issued by CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US is not trusted; internal cause is:
22:13:36 java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at com.ibm.security.cert.BasicChecker.<init>(BasicChecker.java:111)
22:13:36 at com.ibm.security.cert.PKIXCertPathValidatorImpl.engineValidate(PKIXCertPathValidatorImpl.java:199)
22:13:36 at com.ibm.security.cert.PKIXCertPathBuilderImpl.myValidator(PKIXCertPathBuilderImpl.java:749)
22:13:36 at com.ibm.security.cert.PKIXCertPathBuilderImpl.buildCertPath(PKIXCertPathBuilderImpl.java:661)
22:13:36 at com.ibm.security.cert.PKIXCertPathBuilderImpl.buildCertPath(PKIXCertPathBuilderImpl.java:607)
22:13:36 at com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:368)
22:13:36 ... 37 more
22:13:36 Caused by: java.security.cert.CertPathValidatorException: Certificate chaining error
22:13:36 at com.ibm.security.cert.CertPathUtil.findIssuer(CertPathUtil.java:316)
22:13:36 at com.ibm.security.cert.BasicChecker.<init>(BasicChecker.java:108)
22:13:36 ... 42 more
22:13:36

I have tried to download certificate.pem from my Artifactory and run this command, but the issue still there on my AIX 7.3.

/usr/java8_64/jre/bin/keytool -importcert -alias cacertalias -keystore /usr/java8_64/jre/lib/security/cacerts -file /path/to/your/certificate.pem

It investing it can not reproduce on my Windows, Linux and AIX 7.3 build machines.

What’s the different between them? the only different is Java runtime. On my problematic AIX 7.1 build machine, I used a shared runtime which is a link to path /tools/AIX-7.1/Java8_64-8.0.0.401/usr/java8_64/bin/java

bash-5.0$ /tools/AIX-7.1/Java8_64-8.0.0.401/usr/java8_64/bin/java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build pap6480sr4fp1-20170215_01(SR4 FP1))
IBM J9 VM (build 2.8, JRE 1.8.0 AIX ppc64-64 Compressed References 20170209_336038 (JIT enabled, AOT enabled)
J9VM - R28_20170209_0201_B336038
JIT - tr.r14.java.green_20170125_131456
GC - R28_20170209_0201_B336038_CMPRSS
J9CL - 20170209_336038)
JCL - 20170215_01 based on Oracle jdk8u121-b13

And I have anther Java runtime installed my that machine which is /usr/java8_64/bin/java

bash-5.0$ /usr/java8_64/bin/java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 8.0.6.5 - pap6480sr6fp5-20200111_02(SR6 FP5))
IBM J9 VM (build 2.9, JRE 1.8.0 AIX ppc64-64-Bit Compressed References 20200108_436782 (JIT enabled, AOT enabled)
OpenJ9 - 7d1059c
OMR - d059105
IBM - c8aee39)
JCL - 20200110_01 based on Oracle jdk8u241-b07

Actually the versions of these two java versions are different. I just changed configuration of JavaPath from /tools/AIX-7.1/Java8_64-8.0.0.401/usr/java8_64/bin/java to /usr/java8_64/bin/java in the Jenkins node and disconnect then launch agent again, it works.

I don’t why it works, I don’t know much about Java certificate, if you know the reason please leave comments and let me know. Thank you.


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

创建 NuGet Organization 的遇到的坑

其实创建包管理平台账户没什么可说的,但最近准备在 https://www.nuget.org 上面发布产品前创建 Organization 的时候确遇到了问题。

事情是这样的

作为一名公司员工在首次打开 NuGet 网站 (www.nuget.org) 的时候,点击【Sign in】,映入眼帘的就是【Sign in with Microsoft】,点击,下一步、下一步,我就顺利的就用公司邮箱注册了我的第一个 NuGet 的账户。

此时我准备创建一个 Organization 的时候,输入自己的公司邮箱提示这个邮箱地址已经被使用了,What ???

OK。那我就填写同事的公司邮箱地址吧。

同事在收到邮件通知后也是一步步操作,先是打开 NuGet.org,点击【Sign in with Microsoft】,然后也是需要填写自己的账户名,结果完成这一系列的操作之后,再输入他的邮件地址去注册 Organization 的时候也同样提示这个邮箱已经被使用了???什么操作!!!醉了…

如何解决的

就在这千钧一发焦急得等待发布之际,我突然灵机一动,以死马当活马医的心态,将我注册的 NuGet 的个人账户绑定的公司邮箱修改为了自己的 Gmail 邮箱,然后此时再去创建 Organization 的时候输入的是自己的公司邮箱,创建 Organization 成功了!!

好了,谨以此记录一下在注册 NuGet 时候遇到的问题。不知道对你是否有用,如果真的有帮助到你,举手示意一下哦。


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

Docker Buildx Bake:加速构建和管理多平台镜像的利器

随着容器化技术的普及和应用场景的增多,构建和管理多平台镜像变得越来越重要。Docker Buildx 是 Docker 官方对于 Docker CLI 的一个扩展,为 Docker 用户提供了更强大和灵活的构建功能。包括:

  1. 多平台构建:Docker Buildx 允许用户在一个构建命令中为多个不同的平台构建容器镜像。这样,你可以一次性构建适用于多种 CPU 架构的镜像,比如 x86、ARM 等,从而在不同的硬件设备上运行相同的镜像。
  2. 构建缓存优化:Docker Buildx 改进了构建过程中的缓存机制,通过自动识别 Dockerfile 中哪些部分是可缓存的,从而减少重复构建和加快构建速度。
  3. 并行构建:Buildx 允许并行构建多个镜像,提高了构建的效率。
  4. 多种输出格式:Buildx 支持不同的输出格式,包括 Docker 镜像、OCI 镜像、以及 rootfs 等。
  5. 构建策略:通过支持多种构建策略,用户可以更好地控制构建过程,例如,可以在多个节点上构建、使用远程构建等。

使用 docker buildx 需要 Docker Engine 版本不低于 19.03。

其中,Docker Buildx Bake 是 Buildx 的一个子命令,也是本篇文章要重点介绍包括概念、优势、使用场景以及如何使用该功能来加速构建和管理多平台镜像。

什么是 Docker Buildx Bake?

Docker Buildx Bake 是 Docker Buildx 的一项功能,它旨在简化和加速镜像构建过程。Bake 是一种声明式的构建定义方式,它允许用户在一个命令中定义多个构建配置和目标平台,实现自动化批量构建和发布跨平台镜像。

为什么使用 Docker Buildx Bake?

1. 提高构建效率

Bake 通过并行构建和缓存机制来提高构建效率。使用 Bake 可以一次性定义和构建多个镜像,而无需为每个镜像分别执行构建过程,这样可以大大节省构建时间,提高工作效率。

2. 支持多个平台和架构

Docker Buildx Bake 的另一个优势是它能够构建多个平台和架构的镜像。通过在 Bake 配置中指定不同的平台参数就可以轻松构建适用于不同操作系统和架构的镜像。这对于跨平台应用程序的开发和部署非常有用。

3. 一致的构建环境

通过 docker-bake.hcl (除了 HCL 配置文件之外还可以是 JSON 或是 YAML 文件)文件描述构建过程确保一致的构建环境,使不同的构建配置和目标平台之间具有相同的构建过程和结果。这种一致性有助于减少构建过程中的错误,而且构建配置更易于维护和管理。

如何使用 Docker Buildx Bake?

以下是使用 Docker Buildx Bake 进行高效构建的基本步骤,首先确保你已经安装了 Docker Engine 或 Docker Desktop 版本 19.03 以及以上。

然后你的 docker 命令将变成这样 docker buildx bake。以下 docker buildx bake --help 的帮助输出:

docker buildx bake --help

Usage: docker buildx bake [OPTIONS] [TARGET...]

Build from a file

Aliases:
docker buildx bake, docker buildx f

Options:
--builder string Override the configured builder instance
-f, --file stringArray Build definition file
--load Shorthand for "--set=*.output=type=docker"
--metadata-file string Write build result metadata to the file
--no-cache Do not use cache when building the image
--print Print the options without building
--progress string Set type of progress output ("auto", "plain", "tty"). Use plain to show container output (default "auto")
--provenance string Shorthand for "--set=*.attest=type=provenance"
--pull Always attempt to pull all referenced images
--push Shorthand for "--set=*.output=type=registry"
--sbom string Shorthand for "--set=*.attest=type=sbom"
--set stringArray Override target value (e.g., "targetpattern.key=value")

接下来尝试一下如何使用 docker buildx bake

1. 创建 Bake 配置文件

比如创建一个名为 docker-bake.dev.hcl 的 Bake 配置文件,并在其中定义构建上下文、目标平台和其他构建选项。以下是一个简单的示例:

# docker-bake.dev.hcl
group "default" {
targets = ["db", "webapp-dev"]
}

target "db" {
dockerfile = "Dockerfile.db"
tags = ["xianpengshen/docker-buildx-bake-demo:db"]
}

target "webapp-dev" {
dockerfile = "Dockerfile.webapp"
tags = ["xianpengshen/docker-buildx-bake-demo:webapp"]
}

target "webapp-release" {
inherits = ["webapp-dev"]
platforms = ["linux/amd64", "linux/arm64"]
}

2. 运行 Bake 构建

运行以下命令开始使用 Bake 构建镜像:

$ docker buildx bake -f docker-bake.dev.hcl db webapp-release

3. 打印构建选项

你还可以无需构建打印构建选项,使用用 --print 来查看某个目标构建是否符合预期。例如:

$ docker buildx bake -f docker-bake.dev.hcl --print db
[+] Building 0.0s (0/0)
{
"group": {
"default": {
"targets": [
"db"
]
}
},
"target": {
"db": {
"context": ".",
"dockerfile": "Dockerfile.db",
"tags": [
"xianpengshen/docker-buildx-bake-demo:db"
]
}
}
}

4. 发布构建镜像

通过添加 --push 选项可以将构建完成的镜像一键发布的镜像仓库,例如 $ docker buildx bake -f docker-bake.dev.hcl --push db webapp-release

以上示例中的 demo 放在这里了:https://github.com/shenxianpeng/docker-buildx-bake-demo

5. Buildx Bake 高级用法

Buildx Bake 还有其他更多的使用技巧,比如 variable, function , matrix 等这里就不一一介绍了,详情请参见官方 Buildx Bake reference 文档。

总结

Docker Buildx Bake 是一个功能强大的构建工具,它提供了一种简化和加速构建过程的方法。通过使用 Bake 你可以高效地构建和测试多个镜像,并且可以跨多个平台和架构进行构建。所以说 Bake 是开发人员和构建工程师的重要利器,掌握 Docker Buildx Bake 的使用方法将帮助你更好地应对多镜像构建的带来的挑战、加快应用程序的交付速度。


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」

详解SBOM:定义、关系、区别、最佳实践和生成工具

什么是 SBOM

SBOM 是软件材料清单(Software Bill of Materials)的缩写。它是一份详细记录软件构建过程中使用的所有组件、库和依赖项的清单。

SBOM 类似于产品的配方清单,它列出了构成软件应用程序的各种元素,包括开源软件组件、第三方库、框架、工具等。每个元素在 SBOM 中都会有详细的信息,如名称、版本号、许可证信息、依赖关系等。

SBOM 的目的是增加软件供应链的可见性和透明度,并提供更好的风险管理和安全性。它可以帮助软件开发者、供应商和用户了解其软件中使用的组件和依赖项,以便更好地管理潜在的漏洞、安全风险和合规性问题。通过 SBOM 用户可以识别和跟踪软件中存在的任何潜在漏洞或已知的安全问题,并及时采取相应的补救措施。

SBOM 还可以用于软件审计、合规性要求和法规遵从性等方面。一些行业标准和法规(如软件供应链安全框架(SSCF)和欧盟网络和信息安全指令(NIS指令))已经要求软件供应商提供 SBOM,以提高软件供应链的安全性和可信度。

总之,SBOM 是一份记录软件构建过程中使用的所有组件和依赖项的清单,它提供了对软件供应链的可见性,有助于管理风险、提高安全性,并满足合规性要求。

SBOM 和 SLSA 之间有什么关系,两者的区别是什么

SBOM(软件材料清单)和 SLSA(Supply Chain Levels for Software Artifacts)是两个不同但相关的概念。

  • SBOM 是软件材料清单,它提供了对软件供应链的可见性,包括组件的版本、许可证信息、漏洞等。SBOM 旨在帮助组织更好地管理和控制软件供应链,识别和处理潜在的漏洞、合规性问题和安全风险。
  • SLSA 是一种供应链安全框架,它定义了不同级别的安全要求和实践,以确保软件供应链的安全性。SLSA 旨在加强软件的可信度和安全性,防止恶意代码、供应链攻击和漏洞的传播。SLSA 关注整个软件供应链的安全,包括组件的来源、验证、构建过程和发布机制。

关于两者的区别:

  1. 视角不同:SBOM 关注软件构建物料的清单和可见性,提供对组件和依赖项的详细信息。SLSA 关注供应链的安全性,定义了安全级别和实践,强调确保软件供应链的可信度和安全性。
  2. 用途不同:SBOM 用于识别和管理软件构建中的组件、漏洞和合规性问题。它提供了一种管理软件供应链风险的工具。SLSA 则提供了一种安全框架,通过定义安全级别和要求,帮助组织确保软件供应链的安全性。
  3. 关联性:SLSA 可以利用 SBOM 作为其实施的一部分。SBOM 提供了 SLSA 所需的组件和依赖项的详细信息,有助于验证和审计供应链的安全性。SLSA 的实践可以包括要求使用 SBOM 生成和验证,以确保软件供应链的可见性和完整性。

SBOM 和 SLSA 都是软件供应链安全中的两个关键概念。它们可以相互关联和互补使用,以加强软件供应链的安全性和管理。

SBOM 和 Black Duck 之间有什么区别

SBOM(Software Bill of Materials)和 Synopsys BlackDuck 是两个相关但不同的概念。下面是它们之间的区别:

SBOM:

  1. 定义:SBOM 是一种文档或清单,用于记录软件构建过程中使用的所有组件和依赖项。它提供了对软件供应链的可见性和透明度。
  2. 内容:SBOM 列出了每个组件的名称、版本号、作者、许可证信息等详细信息。它有助于追踪和管理软件的组件、依赖关系、漏洞和许可证合规性等。
  3. 用途:SBOM 用于软件供应链管理、安全审计、合规性验证和风险管理。它帮助组织了解软件构建中使用的组件,识别潜在的漏洞和风险,并确保合规性。

Synopsys Black Duck:

  1. 功能:Synopsys Black Duck 是一种供应链风险管理工具。它可以扫描软件项目,识别其中使用的开源组件和第三方库,并分析其许可证合规性、安全漏洞和其他潜在风险。
  2. 特点:Black Duck 具有广泛的漏洞数据库和许可证知识库,可与开发流程和 CI/CD 工具集成,提供漏洞警报、许可证合规报告和风险分析等功能。
  3. 目的:Black Duck 帮助组织管理和控制软件供应链风险,提供实时的开源组件和第三方库的安全和合规性信息,以支持决策和采取适当的措施。

综上所述,SBOM 是记录软件构建中使用的组件和依赖项,提供对软件供应链的可见性和管理。而 Black Duck 是一种供应链风险管理工具,通过扫描和分析软件项目中的开源组件和第三方库,提供许可证合规性、安全漏洞和风险分析等功能。Black Duck 可以用于生成 SBOM,并提供更全面的风险和合规性分析。因此,Black Duck 是一个具体的工具,而 SBOM 是一种记录和管理软件供应链信息的概念。

SBOM 的最佳实践

  1. 自动化生成:使用自动化工具生成 SBOM,避免手动创建和维护,确保准确性和一致性。
  2. 包含详细信息:在 SBOM 中包含尽可能详细的信息,如组件名称、版本号、作者、许可证信息、依赖关系、漏洞信息等。
  3. 定期更新:定期更新 SBOM 以反映最新的构建物料清单,确保其准确性和完整性。
  4. 版本控制:对于每个软件版本,建立和管理相应的 SBOM 版本,以便跟踪软件版本和其对应的构建物料清单。
  5. 集成到软件生命周期:将 SBOM 集成到整个软件生命周期中,包括开发、构建、测试、部署和维护阶段。
  6. 漏洞管理和风险评估:利用 SBOM 中的漏洞信息,与漏洞数据库集成,进行漏洞管理和风险评估。
  7. 供应商合作:与供应商和合作伙伴共享和获取 SBOM 信息,确保他们也提供准确的 SBOM,并持续关注他们的漏洞管理和合规性措施。

SBOM 的生成工具

  1. CycloneDX:CycloneDX 是一种开放的软件组件描述标准,用于生成和共享 SBOM。它支持多种语言和构建工具,具有广泛的生态系统和工具集成。
  2. SPDX:SPDX(Software Package Data Exchange)是一种开放的标准,用于描述软件组件和相关许可证信息。它提供了一种统一的方式来生成和交换SBOM。
  3. OWASP Dependency-Track:Dependency-Track 是一个开源的供应链安全平台,可生成和分析 SBOM,提供漏洞管理、许可证合规性和供应链可视化等功能。
  4. WhiteSource: WhiteSource 是一种供应链管理工具,提供了自动化的开源组件识别、许可证管理和漏洞分析,可以生成SBOM并进行风险评估。
  5. JFrog Xray:JFrog Xray 是一种软件供应链分析工具,可以扫描和分析构建物料清单,提供漏洞警报、许可证合规性和安全性分析。
  6. Microsoft sbom-tool:是一种高度可扩展、适用于企业的工具,可为各种工件创建 SPDX 2.2 兼容的 SBOM。
  7. trivy:支持在容器、Kubernetes、代码存储库、Cloud 等中查找漏洞、错误配置、密钥 和生成 SBOM。

除了以上这些还有一些其他工具也提供了 SBOM 生成、管理和分析的功能,你可以根据具体需求选择适合的工具来实施 SBOM 的最佳实践。

总结

希望通过这篇文章,让你了解了 SBOM 的概念、与 SLSA 和 Black Duck 的关系和区别、最佳实践以及可用的生成工具来帮助更好地管理软件供应链安全。

如果你是项目成员,是 Fork 原始仓库还是直接原始仓库中修改代码?

想必你也见到过很多开源项目中的 CONTRIBUTION.md 文档中通常都会让贡献者 Fork 仓库,然后做修改。

那么如果你是该开源项目中的成员是否需要 Fork 仓库进行修改呢?

以前我没有认真去想过这个问题,对于项目成员感觉 Fork 或不 Fork 好像差不多,但仔细想想 Fork 仓库与不 Fork 仓库其实是有以下几个主要的差别的:

修改权限

在原始仓库中,你可能没有直接修改代码的权限,当你 Fork 一个仓库时,会创建一个属于你自己的副本,你可以在这个副本中拥有完全的修改权限,你可以自由地进行更改、添加新功能、解决bug等,而不会对原始仓库产生直接影响。

做实验性的工作

如果你计划进行较大的修改或实验性工作,并且不希望直接影响原始仓库,那么 fork 仓库并在 fork 的中进行修改更为合适。

比如你需要实验性的去大量清理现有仓库里的一些垃圾文件或是代码,如果你需要需要多次尝试,并将多次修改直接 git push 到推送原始仓库进行保存或是测试,这大大增加原始仓库的存储空间,如果你的修改是大型文件,那么对原始仓库的存储空间影响则会更大;如果你是 Fork 仓库则不会造成原始仓库的影响,直到你完成修改通过 Pull Request 合并到原始仓库时才会产生新的存储空间。

代码审查和协作

当你 Fork 一个仓库并在自己的副本中进行修改后,你必须通过 Pull Request(PR)向原始仓库合并修改,有助于确保代码质量和功能正确性。(当然不 Fork 也可以这样做或不做,但 Fork 了就必须这样做了)

版本控制和历史记录

Fork 一个仓库后,你可以在自己的副本中维护独立的版本控制历史。你可以跟踪自己的更改、回溯历史、管理代码版本,而不会影响到原始仓库的版本控制。同时,你可以从原始仓库同步最新的更改,保持你的副本与原始仓库的同步。

总结

Fork 仓库与不 Fork 仓库的主要差别在于修改权限、做实验性的工作、代码审查和协作,以及版本控制和历史记录。

个人认为只要一个仓库的贡献者超过 3 人,都建议所有人都 Fork 原始仓库,通过 Pull Request 方式合并代码。

但也有例外情况可能不适合 Fork:项目在 Fork 之后 CI/CD 无法独立工作,但是你需要它们。比如 Fork 后的仓库因为环境等原因不支持独立的运行 CI/CD 而你需要在提交 Pull Request 之前通过自动化对分支进行测试。

另外还要为原始仓库需要做适当的分支权限设置,以防止就算两个人的团队另外一个人不熟悉 Git 使用了非常危险的操作,比如强制推送(Force Push),变基(Rebasing),强制检出(Force Checkout)可能导致代码丢失、数据损坏或版本控制问题。


转载本站文章请注明作者和出处,请勿用于任何商业用途。欢迎关注公众号「DevOps攻城狮」