Skip to content

Commit f2a3e1b

Browse files
authored
build(compliance): add missing known license information in sboms (#2562)
Signed-off-by: Victoria <kaysa.vps@gmail.com>
1 parent 026280f commit f2a3e1b

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

.github/workflows/release.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ jobs:
135135
sbom_name="${repo_name}-sbom-${arch}"
136136
137137
syft -o cyclonedx-json=/tmp/sbom-$material_name.cyclonedx.json $entry
138+
139+
# Add missing known licenses
140+
${{ github.workspace }}/.github/workflows/utils/add-license-to-sbom.sh /tmp/sbom-$material_name.cyclonedx.json "ariga.io/atlas/cmd/atlas" "Apache-2.0" type="library"
141+
${{ github.workspace }}/.github/workflows/utils/add-license-to-sbom.sh /tmp/sbom-$material_name.cyclonedx.json "github.com/ariga/language-tools/packages/language-server-go" "Apache-2.0" type="library"
142+
138143
chainloop attestation add --name $container_name --value $entry --kind CONTAINER_IMAGE --attestation-id ${{ env.ATTESTATION_ID }}
139144
chainloop attestation add --name $sbom_name --value /tmp/sbom-$material_name.cyclonedx.json --kind SBOM_CYCLONEDX_JSON --attestation-id ${{ env.ATTESTATION_ID }}
140145
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#!/usr/bin/env bash
2+
3+
# Script to add license information to SBOM components
4+
# Usage:
5+
# ./add-license-to-sbom.sh <sbom_file> <component_name> <license_identifier> [version=<version>] [type=<type>] [--custom_license] [--strict] [--help]
6+
# Example: ./add-license-to-sbom.sh sbom.json "backend" "Apache-2.0" version="v1.0.0"
7+
# Example: ./add-license-to-sbom.sh sbom.json "frontend" "Chainloop Proprietary License" type="library" --custom_license --strict
8+
9+
set -euo pipefail
10+
11+
# Check for help flag first
12+
if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then
13+
cat << EOF
14+
SBOM License Addition Script
15+
16+
This script adds license information to SBOM components if they exist and don't already have licenses.
17+
18+
Usage:
19+
./add-license-to-sbom.sh <sbom_file> <component_name> <license_identifier> [options]
20+
21+
Arguments:
22+
sbom_file Path to the SBOM file (CycloneDX JSON format)
23+
component_name Name of the component to add license to
24+
license_identifier SPDX license identifier (e.g., "Apache-2.0", "MIT") or custom license name
25+
26+
Options:
27+
version=<ver> Match component by name and version
28+
type=<type> Match component by name and type
29+
--custom_license Treat license_identifier as custom license name (default: SPDX identifier)
30+
--strict Fail if component doesn't exist or already has licenses
31+
--help, -h Show this help message
32+
33+
Examples:
34+
# Add SPDX license identifier to component by name and version
35+
./add-license-to-sbom.sh sbom.json "backend" "Apache-2.0" version="v1.0.0"
36+
37+
# Add SPDX license identifier to component by name and type
38+
./add-license-to-sbom.sh sbom.json "frontend" "MIT" type="library"
39+
40+
# Add custom license name to component
41+
./add-license-to-sbom.sh sbom.json "backend" "Chainloop Proprietary License" --custom_license
42+
43+
# Use strict mode (fail if component missing or has licenses)
44+
./add-license-to-sbom.sh sbom.json "cli" "BSD-3-Clause" --strict
45+
46+
# Match by name only with SPDX identifier
47+
./add-license-to-sbom.sh sbom.json "backend" "GPL-3.0-or-later"
48+
49+
Behavior:
50+
- Default: Skips with message if component not found or already has licenses
51+
- Strict: Exits with error code 1 if component not found or already has licenses
52+
EOF
53+
exit 0
54+
fi
55+
56+
# Validate required arguments
57+
if [[ $# -lt 3 ]]; then
58+
echo "Error: Missing required arguments"
59+
echo "Use --help for usage information"
60+
exit 1
61+
fi
62+
63+
SBOM_FILE="$1"
64+
COMPONENT_NAME="$2"
65+
LICENSE_NAME="$3"
66+
67+
# Validate SBOM file exists
68+
if [[ ! -f "$SBOM_FILE" ]]; then
69+
echo "Error: SBOM file '$SBOM_FILE' does not exist"
70+
exit 1
71+
fi
72+
73+
# Initialize optional parameters
74+
VERSION=""
75+
TYPE=""
76+
CUSTOM_LICENSE=false # Default to SPDX identifier format
77+
STRICT_MODE=false
78+
79+
# Parse optional parameters from command line arguments (starting from 4th argument)
80+
for arg in "${@:4}"; do
81+
case $arg in
82+
version=*)
83+
# Extract version value after the '=' sign
84+
VERSION="${arg#*=}"
85+
;;
86+
type=*)
87+
# Extract type value after the '=' sign
88+
TYPE="${arg#*=}"
89+
;;
90+
--custom_license)
91+
# Treat license_identifier as custom license name instead of SPDX identifier
92+
CUSTOM_LICENSE=true
93+
;;
94+
--strict)
95+
# Enable strict mode - will fail if component missing or has licenses
96+
STRICT_MODE=true
97+
;;
98+
esac
99+
done
100+
101+
# Build jq selector based on available criteria to identify the component
102+
# This creates a flexible matching system depending on what parameters were provided
103+
if [[ -n "$VERSION" && -n "$TYPE" ]]; then
104+
# Match by name, version AND type (most specific)
105+
SELECTOR=".name == \"$COMPONENT_NAME\" and .version == \"$VERSION\" and .type == \"$TYPE\""
106+
IDENTIFIER="name='$COMPONENT_NAME', version='$VERSION', type='$TYPE'"
107+
elif [[ -n "$VERSION" ]]; then
108+
# Match by name and version only
109+
SELECTOR=".name == \"$COMPONENT_NAME\" and .version == \"$VERSION\""
110+
IDENTIFIER="name='$COMPONENT_NAME', version='$VERSION'"
111+
elif [[ -n "$TYPE" ]]; then
112+
# Match by name and type only
113+
SELECTOR=".name == \"$COMPONENT_NAME\" and .type == \"$TYPE\""
114+
IDENTIFIER="name='$COMPONENT_NAME', type='$TYPE'"
115+
else
116+
# Match by name only (least specific)
117+
SELECTOR=".name == \"$COMPONENT_NAME\""
118+
IDENTIFIER="name='$COMPONENT_NAME'"
119+
fi
120+
121+
# Check if component exists in SBOM using our constructed selector
122+
# Uses jq to search through components array and returns the name if found
123+
HAS_COMPONENT=$(jq -r ".components[] | select($SELECTOR) | .name" "$SBOM_FILE" | head -1)
124+
125+
if [[ -n "$HAS_COMPONENT" ]]; then
126+
# Component was found - now check if it already has license information
127+
# Count existing licenses (using // [] to handle missing licenses field)
128+
HAS_LICENSES=$(jq -r ".components[] | select($SELECTOR) | (.licenses // []) | length" "$SBOM_FILE" | head -1)
129+
130+
if [[ "$HAS_LICENSES" == "0" ]]; then
131+
# Component exists but has no licenses - proceed with adding license
132+
echo "Adding license '$LICENSE_NAME' to component with $IDENTIFIER"
133+
134+
# Use jq to add license information to the matching component
135+
# Creates temporary file and atomically moves it to avoid corruption
136+
if [[ "$CUSTOM_LICENSE" == "true" ]]; then
137+
# Use "name" field for custom license names
138+
jq "(.components[] | select($SELECTOR) | select((.licenses // []) | length == 0) | .licenses) = [{\"license\": {\"name\": \"$LICENSE_NAME\"}}]" "$SBOM_FILE" > "${SBOM_FILE}.tmp" && mv "${SBOM_FILE}.tmp" "$SBOM_FILE"
139+
else
140+
# Use "id" field for SPDX license identifiers
141+
jq "(.components[] | select($SELECTOR) | select((.licenses // []) | length == 0) | .licenses) = [{\"license\": {\"id\": \"$LICENSE_NAME\"}}]" "$SBOM_FILE" > "${SBOM_FILE}.tmp" && mv "${SBOM_FILE}.tmp" "$SBOM_FILE"
142+
fi
143+
144+
echo "License added successfully"
145+
else
146+
# Component already has license information
147+
echo "Component with $IDENTIFIER already has licenses"
148+
if [[ "$STRICT_MODE" == "true" ]]; then
149+
# In strict mode, this is an error condition
150+
echo "ERROR: --strict mode enabled and component already has licenses"
151+
exit 1
152+
else
153+
# In lenient mode, just skip with a message
154+
echo "Skipping license addition"
155+
fi
156+
fi
157+
else
158+
# Component was not found in SBOM
159+
echo "Component with $IDENTIFIER not found in SBOM"
160+
if [[ "$STRICT_MODE" == "true" ]]; then
161+
# In strict mode, missing component is an error
162+
echo "ERROR: --strict mode enabled and component not found"
163+
exit 1
164+
else
165+
# In lenient mode, just skip with a message
166+
echo "Skipping license addition"
167+
fi
168+
fi

0 commit comments

Comments
 (0)