From e213fea869c48ce7c3972230e4c79f42dd449aa2 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 15:33:08 -0700 Subject: [PATCH] Generate license reports and SBOMs from build evidence with bom-tools Replace cargo-cyclonedx and allow-list with bom-tools 0.3.0, which scopes the third-party license reports and the new CycloneDX SBOMs to what each build actually compiled. Same migration as stepfunc/dnp3#450. cargo-cyclonedx described the default features, while most targets are built with tls-aws-lc, so the reports listed ring and omitted aws-lc-rs/aws-lc-sys. - each build job records its evidence via .github/scripts/build-evidence.sh (same script as dnp3), which also does the build and requires --target; macOS now builds with --target like the other platforms - packaging runs bom-tools for rodbus-ffi and rodbus-ffi-java, embeds each SBOM in its package next to the license report, and the GitHub release attaches the SBOMs - allowed.json: same review as dnp3 for the shared crates (ring, aws-lc-*, Step Function's open-source crates, embedded build dependencies), plus cmake, fs_extra, jobserver and pkg-config as build tools --- .github/scripts/build-evidence.sh | 26 +++++ .github/workflows/ci.yml | 81 +++++++++------ allowed.json | 161 +++++++++++++++++++++++------- 3 files changed, 205 insertions(+), 63 deletions(-) create mode 100755 .github/scripts/build-evidence.sh diff --git a/.github/scripts/build-evidence.sh b/.github/scripts/build-evidence.sh new file mode 100755 index 00000000..a6f9eb09 --- /dev/null +++ b/.github/scripts/build-evidence.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Build a product and record the evidence bom-tools needs: the cargo build log and the full and +# runtime `cargo tree` outputs, all from the same arguments in this environment. +# See https://github.com/stepfunc/bom-tools#producing-the-build-evidence +# +# usage: build-evidence.sh +set -euo pipefail + +out="$1" +build="$2" +shift 2 +# `cargo tree` only separates host and target features when given `--target`, so the build and +# the trees must always name the target explicitly, even for a native build +case " $* " in + *" --target "*) ;; + *) echo "build-evidence.sh: --target is required" >&2; exit 1 ;; +esac +mkdir -p "$out" +tree_format=(--prefix depth --color never --format '{p}|{f}') + +# a normal build first, so compiler errors stay readable in the CI log +"$build" build --release --locked "$@" +# then the same build as JSON; everything is fresh, so this only replays the artifacts +"$build" build --release --locked "$@" --message-format json > "$out/build.json" +cargo tree --locked "$@" -e normal,build "${tree_format[@]}" > "$out/tree.txt" +cargo tree --locked "$@" -e normal,no-proc-macro "${tree_format[@]}" > "$out/runtime-tree.txt" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14734027..7ca4f2ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,9 +117,11 @@ jobs: - name: Create the FFI modules dir run: mkdir ffi-modules\${{ matrix.target }} - name: Build FFI - run: cargo build -p rodbus-ffi --release --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial + shell: bash + run: bash .github/scripts/build-evidence.sh evidence/ffi/${{ matrix.target }} cargo -p rodbus-ffi --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial - name: Build JNI - run: cargo build -p rodbus-ffi-java --release --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial + shell: bash + run: bash .github/scripts/build-evidence.sh evidence/java/${{ matrix.target }} cargo -p rodbus-ffi-java --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial - name: Copy the FFI and JNI libs shell: pwsh run: | @@ -131,6 +133,11 @@ jobs: with: name: ffi-modules-${{ matrix.target }} path: ffi-modules + - name: Upload build evidence + uses: actions/upload-artifact@v7 + with: + name: evidence-${{ matrix.target }} + path: evidence - name: C Bindings Tests if: ${{ matrix.test }} run: cargo run --bin rodbus-bindings -- --c -r ${{ matrix.target }} -a ./target/${{ matrix.target }}/release @@ -159,22 +166,27 @@ jobs: - name: Create FFI modules dir run: mkdir -p ffi-modules/${{ matrix.target }} - name: Build FFI - run: cargo build -p rodbus-ffi --release --no-default-features --features tls-aws-lc,serial + run: bash .github/scripts/build-evidence.sh evidence/ffi/${{ matrix.target }} cargo -p rodbus-ffi --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial - name: Build JNI - run: cargo build -p rodbus-ffi-java --release --no-default-features --features tls-aws-lc,serial + run: bash .github/scripts/build-evidence.sh evidence/java/${{ matrix.target }} cargo -p rodbus-ffi-java --target ${{ matrix.target }} --no-default-features --features tls-aws-lc,serial - name: Copy the FFI and JNI libs run: | - cp ./target/release/librodbus_ffi.dylib ./ffi-modules/${{ matrix.target }} - cp ./target/release/librodbus_ffi_java.dylib ./ffi-modules/${{ matrix.target }} + cp ./target/${{ matrix.target }}/release/librodbus_ffi.dylib ./ffi-modules/${{ matrix.target }} + cp ./target/${{ matrix.target }}/release/librodbus_ffi_java.dylib ./ffi-modules/${{ matrix.target }} - name: Upload compiled FFI modules uses: actions/upload-artifact@v7 with: name: ffi-modules-${{ matrix.target }} path: ffi-modules + - name: Upload build evidence + uses: actions/upload-artifact@v7 + with: + name: evidence-${{ matrix.target }} + path: evidence - name: Test .NET bindings - run: cargo run --bin rodbus-bindings -- --dotnet + run: cargo run --bin rodbus-bindings -- --dotnet -r ${{ matrix.target }} -a ./target/${{ matrix.target }}/release - name: Test Java bindings - run: cargo run --bin rodbus-bindings -- --java + run: cargo run --bin rodbus-bindings -- --java -r ${{ matrix.target }} -a ./target/${{ matrix.target }}/release # Cross-compilation for Linux to produce portable C and JNI libraries bindings-linux: env: @@ -213,9 +225,9 @@ jobs: - name: Create FFI modules dir run: mkdir -p ffi-modules/${{ matrix.cases.target }} - name: Build FFI - run: cross build -p rodbus-ffi --release --target ${{ matrix.cases.target }} --no-default-features --features ${{ matrix.cases.features }} + run: bash .github/scripts/build-evidence.sh evidence/ffi/${{ matrix.cases.target }} cross -p rodbus-ffi --target ${{ matrix.cases.target }} --no-default-features --features ${{ matrix.cases.features }} - name: Build JNI - run: cross build -p rodbus-ffi-java --release --target ${{ matrix.cases.target }} --no-default-features --features ${{ matrix.cases.features }} + run: bash .github/scripts/build-evidence.sh evidence/java/${{ matrix.cases.target }} cross -p rodbus-ffi-java --target ${{ matrix.cases.target }} --no-default-features --features ${{ matrix.cases.features }} - name: Copy the FFI and JNI libs run: | cp ./target/${{ matrix.cases.target }}/release/librodbus_ffi.so ./ffi-modules/${{ matrix.cases.target }} @@ -225,6 +237,11 @@ jobs: with: name: ffi-modules-${{ matrix.cases.target }} path: ffi-modules + - name: Upload build evidence + uses: actions/upload-artifact@v7 + with: + name: evidence-${{ matrix.cases.target }} + path: evidence guide: runs-on: ubuntu-latest steps: @@ -251,10 +268,8 @@ jobs: steps: - name: Install Rust uses: dtolnay/rust-toolchain@stable - - name: Install Cargo CycloneDx - run: cargo install cargo-cyclonedx - - name: Install custom allow-list tool - run: cargo install --git https://github.com/stepfunc/bom-tools.git + - name: Install bom-tools + run: cargo install --locked --git https://github.com/stepfunc/bom-tools.git --tag 0.3.0 - name: Checkout uses: actions/checkout@v7 - name: Download compiled FFI @@ -263,25 +278,32 @@ jobs: pattern: ffi-modules-* path: ffi-modules merge-multiple: true - - name: Create SBOMs + - name: Download build evidence + uses: actions/download-artifact@v8 + with: + path: evidence + pattern: evidence-* + merge-multiple: true + - name: Create third-party license reports and SBOMs run: | - for dir in ffi-modules/*; do - echo "processing path: $dir" - target=`basename "${dir}"` - cargo cyclonedx -f json --target $target - mv ./ffi/rodbus-ffi/rodbus-ffi.cdx.json ffi-modules/$target - mv ./ffi/rodbus-ffi-java/rodbus-ffi-java.cdx.json ffi-modules/$target - done - - name: Create FFI third-party-licenses.txt - run: allow-list gen-licenses-dir -l ffi-modules -b rodbus-ffi.cdx.json -c allowed.json > third-party-licenses.txt - - name: Create FFI third-party-licenses-java.txt - run: allow-list gen-licenses-dir -l ffi-modules -b rodbus-ffi-java.cdx.json -c allowed.json > third-party-licenses-java.txt + cargo metadata --format-version 1 --all-features --locked > metadata.json + COMMON="-m metadata.json -c allowed.json" + bom-tools licenses -e evidence/ffi --root-package rodbus-ffi $COMMON > third-party-licenses.txt + bom-tools licenses -e evidence/java --root-package rodbus-ffi-java $COMMON > third-party-licenses-java.txt + mkdir sboms + bom-tools sbom -e evidence/ffi --root-package rodbus-ffi $COMMON --lockfile Cargo.lock > sboms/rodbus-ffi.cdx.json + bom-tools sbom -e evidence/java --root-package rodbus-ffi-java $COMMON --lockfile Cargo.lock > sboms/rodbus-ffi-java.cdx.json + - name: Upload SBOMs + uses: actions/upload-artifact@v7 + with: + name: sboms + path: sboms - name: Package C/C++ bindings - run: cargo run --bin rodbus-bindings -- --c --package ./ffi-modules --options ./packaging.json -f third-party-licenses.txt + run: cargo run --bin rodbus-bindings -- --c --package ./ffi-modules --options ./packaging.json -f third-party-licenses.txt -f sboms/rodbus-ffi.cdx.json - name: Package .NET bindings - run: cargo run --bin rodbus-bindings -- --dotnet --package ./ffi-modules --options ./packaging.json -f third-party-licenses.txt + run: cargo run --bin rodbus-bindings -- --dotnet --package ./ffi-modules --options ./packaging.json -f third-party-licenses.txt -f sboms/rodbus-ffi.cdx.json - name: Package Java bindings - run: cargo run --bin rodbus-bindings -- --java --package ./ffi-modules --options ./packaging.json -f third-party-licenses-java.txt + run: cargo run --bin rodbus-bindings -- --java --package ./ffi-modules --options ./packaging.json -f third-party-licenses-java.txt -f sboms/rodbus-ffi-java.cdx.json - name: Upload C/C++ bindings uses: actions/upload-artifact@v7 with: @@ -508,5 +530,6 @@ jobs: release/*.zip artifacts/dotnet-bindings/rodbus* artifacts/java-bindings-jar/*.jar + artifacts/sboms/*.cdx.json env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/allowed.json b/allowed.json index 56136aa3..1f0ec6f3 100644 --- a/allowed.json +++ b/allowed.json @@ -29,7 +29,6 @@ "miniz_oxide", "linux-raw-sys", "object", - "oo-bindgen", "once_cell_polyfill", "os_str_bytes", "pathdiff", @@ -52,35 +51,23 @@ "unicode-segmentation", "version_check", "walkdir", - "winapi-util" + "winapi-util", + "cmake", + "fs_extra", + "jobserver", + "pkg-config" ], "vendor": { - "rx509": { - "url": "https://github.com/stepfunc/rasn" - }, - "rodbus": { - "url": "https://github.com/stepfunc/rodbus" - }, - "rodbus-ffi": { - "url": "https://github.com/stepfunc/rodbus" - }, - "rodbus-ffi-java": { - "url": "https://github.com/stepfunc/rodbus" - }, - "scursor": { - "url": "https://github.com/stepfunc/scursor" - }, "sfio-promise": { "url": "https://github.com/stepfunc/promise" }, - "sfio-rustls-config": { - "url": "https://github.com/stepfunc/rustls-config" - }, "sfio-tokio-ffi": { - "url": "https://github.com/stepfunc/tokio-ffi" + "url": "https://github.com/stepfunc/tokio-ffi", + "embedded": true }, "sfio-tracing-ffi": { - "url": "https://github.com/stepfunc/tracing-ffi" + "url": "https://github.com/stepfunc/tracing-ffi", + "embedded": true } }, "third_party": { @@ -1265,25 +1252,16 @@ "id": "ring", "source": "crates.io", "licenses": [ - { - "MIT": { - "copyright": { - "Lines": [ - "Copyright (c) 2015-2016 the fiat-crypto authors (see https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS)" - ] - } - } - }, + "Apache2", { "ISC": { "copyright": { "Lines": [ - "Copyright 2015-2016 Brian Smith" + "Copyright 2015-2025 Brian Smith." ] } } - }, - "OpenSSL" + } ] }, "rustls": { @@ -1964,6 +1942,121 @@ } } ] + }, + "rx509": { + "id": "rx509", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright Step Function I/O LLC" + ] + } + } + } + ] + }, + "sfio-rustls-config": { + "id": "sfio-rustls-config", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright Step Function I/O LLC" + ] + } + } + } + ] + }, + "scursor": { + "id": "scursor", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright 2022 Step Function I/O LLC" + ] + } + } + } + ] + }, + "oo-bindgen": { + "id": "oo-bindgen", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright Step Function I/O LLC" + ] + } + } + } + ], + "embedded": true + }, + "aws-lc-rs": { + "id": "aws-lc-rs", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": { + "Lines": [ + "Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved." + ] + } + } + } + ] + }, + "aws-lc-sys": { + "id": "aws-lc-sys", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": { + "Lines": [ + "Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.", + "Copyright (c) 2014-2024 Google Inc." + ] + } + } + }, + "Apache2", + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015-2020 the fiat-crypto authors." + ] + } + } + }, + { + "BSD3": { + "copyright": { + "Lines": [ + "Copyright (C) 2017 - 2025, Stephan Mueller ." + ] + } + } + } + ] } + }, + "commercial_license": { + "name": "Step Function I/O License Agreement", + "url": "https://github.com/stepfunc/rodbus/blob/main/LICENSE.txt" } }