Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ github_checks_aliases:
# Include files that contain various tasks, task groups, and build variant definitions
include:
- filename: .evergreen/config/functions.yml
- filename: .evergreen/config/sbom.yml

- filename: .evergreen/config/build-task-groups.yml
- filename: .evergreen/config/build-variants.yml
Expand Down
36 changes: 36 additions & 0 deletions .evergreen/config/functions.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
functions:
"upload-sbom":
- command: ec2.assume_role
display_name: Assume ECR readonly IAM role
params:
role_arn: arn:aws:iam::901841024863:role/ecr-role-evergreen-ro
- command: subprocess.exec
type: setup
display_name: Log in to ECR
params:
working_dir: src
binary: bash
include_expansions_in_env:
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
args:
- -c
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 901841024863.dkr.ecr.us-east-1.amazonaws.com
- command: ec2.assume_role
display_name: Assume Silkbomb IAM role
params:
role_arn: arn:aws:iam::901841024863:role/silkbomb
- command: subprocess.exec
type: test
display_name: Upload SBOM via Silkbomb
params:
working_dir: src
binary: bash
include_expansions_in_env:
- branch_name
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN
args:
- .evergreen/upload-sbom.sh

"fetch source":
# Executes git clone and applies the submitted patch, if any
- command: git.get_project
Expand Down
19 changes: 19 additions & 0 deletions .evergreen/config/sbom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
tasks:
- name: upload-sbom
tags: ["ssdlc"]
allowed_requesters: ["commit"]
exec_timeout_secs: 600
commands:
- func: "upload-sbom"

buildvariants:
- name: sbom
display_name: "SBOM"
allowed_requesters: ["commit"]
stepback: false
paths:
- sbom.json
run_on:
- ubuntu2004-small
tasks:
- name: upload-sbom
48 changes: 48 additions & 0 deletions .evergreen/generate-sbom.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Environment Variables:
# None required — all inputs are derived from the repository.
set -eo pipefail

SERIAL_NUMBER="urn:uuid:dc42a43b-4ace-4c42-9a6e-0b9e28fdd100"

echo "Installing CycloneDX PHP Composer plugin"
composer config allow-plugins.cyclonedx/cyclonedx-php-composer true
composer require --dev cyclonedx/cyclonedx-php-composer:6.2.0 --no-update

echo "Updating dependencies"
Comment thread
jasonhills-mongodb marked this conversation as resolved.
# --ignore-platform-reqs: SBOM generation doesn't need to run the code, so extension
# availability and exact PHP patch versions don't matter here.
# --no-scripts: skip git submodule updates and other scripts that require a full dev setup.
composer update --ignore-platform-reqs --no-scripts
Comment thread
jasonhills-mongodb marked this conversation as resolved.

echo "Generating SBOM"
composer CycloneDX:make-sbom \
--spec-version=1.5 \
--output-format=JSON \
--output-file=sbom.cdx.json \
--omit dev \
--no-validate

echo "Updating sbom.json with version tracking"

CURRENT_VERSION=$(jq -r '.version // 0' sbom.json 2>/dev/null || echo 0)

tmp_new=$(mktemp)
tmp_old=$(mktemp)
trap 'rm -f "$tmp_new" "$tmp_old"' EXIT
jq -S 'del(.version, .metadata.timestamp)' sbom.cdx.json > "$tmp_new"
jq -S 'del(.version, .metadata.timestamp)' sbom.json 2>/dev/null > "$tmp_old" || echo '{}' > "$tmp_old"

if diff -q "$tmp_new" "$tmp_old" > /dev/null; then
NEW_VERSION=$CURRENT_VERSION
echo "SBOM content unchanged, keeping version ${NEW_VERSION}"
else
NEW_VERSION=$((CURRENT_VERSION + 1))
echo "SBOM content changed, incrementing version to ${NEW_VERSION}"
fi
Comment thread
jasonhills-mongodb marked this conversation as resolved.

jq --argjson v "$NEW_VERSION" --arg serial "$SERIAL_NUMBER" \
'.version = $v | .serialNumber = $serial' sbom.cdx.json > sbom.json
rm sbom.cdx.json

echo "Generated sbom.json (version ${NEW_VERSION})"
46 changes: 46 additions & 0 deletions .evergreen/upload-sbom.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -eo pipefail

: "${branch_name:?}"
: "${AWS_ACCESS_KEY_ID:?}"
: "${AWS_SECRET_ACCESS_KEY:?}"
: "${AWS_SESSION_TOKEN:?}"

silkbomb="901841024863.dkr.ecr.us-east-1.amazonaws.com/release-infrastructure/silkbomb:2.0"
docker pull "${silkbomb}"
Comment thread
jasonhills-mongodb marked this conversation as resolved.

silkbomb_augment_flags=(
--repo mongodb/mongo-php-library
--branch "${branch_name}"
--sbom-in /pwd/sbom.json
--sbom-out /pwd/augmented.sbom.json.new
--no-update-sbom-version
)

docker run --rm -v "$(pwd):/pwd" \
--user "$(id -u):$(id -g)" \
--env 'AWS_ACCESS_KEY_ID' --env 'AWS_SECRET_ACCESS_KEY' --env 'AWS_SESSION_TOKEN' \
"${silkbomb}" augment "${silkbomb_augment_flags[@]}"

[[ -f ./augmented.sbom.json.new ]] || {
echo "failed to generate augmented SBOM" >&2
exit 1
}

old_json=$(mktemp)
new_json=$(mktemp)
diff_txt=$(mktemp)
trap 'rm -f "$old_json" "$new_json" "$diff_txt"' EXIT

if [ -f ./augmented.sbom.json ]; then
jq -S 'del(.metadata.timestamp)' ./augmented.sbom.json > "$old_json"
else
echo '{}' > "$old_json"
fi
jq -S 'del(.metadata.timestamp)' ./augmented.sbom.json.new > "$new_json"

if ! diff -sty --left-column -W 200 "$old_json" "$new_json" > "$diff_txt"; then
declare status
status='{"status":"failed", "type":"test", "should_continue":true, "desc":"detected significant changes in Augmented SBOM"}'
Comment thread
jasonhills-mongodb marked this conversation as resolved.
curl -sS -d "${status}" -H "Content-Type: application/json" -X POST http://localhost:2285/task_status || true
fi
84 changes: 84 additions & 0 deletions .github/workflows/sbom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Generate SBOM
# Generates sbom.json using cyclonedx-php-composer and opens a PR if it has changed.
# Triggered when Composer dependency files change on v2.x, or manually.
# Internal documentation: go/sbom-scope
on:
workflow_dispatch: {}
push:
branches:
- v2.x
paths:
- "composer.json"
Comment thread
jasonhills-mongodb marked this conversation as resolved.
Comment thread
jasonhills-mongodb marked this conversation as resolved.

permissions:
contents: write
pull-requests: write

jobs:
sbom:
name: Generate SBOM and Create PR
runs-on: ubuntu-24.04
concurrency:
group: sbom-${{ github.ref }}
cancel-in-progress: false

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
tools: composer
Comment thread
jasonhills-mongodb marked this conversation as resolved.

- name: Stash existing SBOM
run: |
jq -S 'del(.metadata.timestamp, .version)' sbom.json > ${{ runner.temp }}/sbom.existing.json

- name: Generate SBOM
run: bash .evergreen/generate-sbom.sh

- name: Download CycloneDX CLI
run: |
curl -fsSL -o ${{ runner.temp }}/cyclonedx \
"https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.32.0/cyclonedx-linux-x64"
echo "454879e6a4a405c8a13bff49b8982adcb0596f3019b26b0811c66e4d7f0783e1 ${{ runner.temp }}/cyclonedx" | sha256sum --check
chmod +x ${{ runner.temp }}/cyclonedx

- name: Validate SBOM
run: ${{ runner.temp }}/cyclonedx validate --input-file sbom.json --fail-on-errors

- name: Check for SBOM changes
id: sbom_diff
run: |
jq -S 'del(.metadata.timestamp, .version)' sbom.json > ${{ runner.temp }}/sbom.generated.json
RESULT=$(diff --brief ${{ runner.temp }}/sbom.existing.json ${{ runner.temp }}/sbom.generated.json || true)
Comment thread
jasonhills-mongodb marked this conversation as resolved.
echo "result=$RESULT" | tee -a $GITHUB_OUTPUT

- name: Open Pull Request if SBOM has changed
if: steps.sbom_diff.outputs.result
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
add-paths: sbom.json
branch: auto-update-sbom-${{ github.ref_name }}
commit-message: "chore: Update SBOM after dependency changes"
delete-branch: true
labels: sbom
title: "Automation: Update SBOM [${{ github.ref_name }}]"
body: |
## Automated SBOM Update

This PR was automatically generated because a Composer dependency change was merged
into `${{ github.ref_name }}`.

`sbom.json` has been regenerated to reflect the current Composer package dependency
graph for production dependencies. The SBOM serial number is stable; the `.version`
field has been incremented to reflect this update.

Once merged, an Evergreen CI task will upload the updated SBOM to the internal
tracking system.

### Triggered by
- Commit: ${{ github.sha }}
- Workflow run: [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
Loading
Loading