343 lines
8.5 KiB
Bash
343 lines
8.5 KiB
Bash
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
# Copyright (c) StellaOps
|
|
#
|
|
# bundle.sh - Bundle SBOM validators for air-gap deployment
|
|
# Sprint: SPRINT_20260107_005_003 Task VG-008
|
|
#
|
|
# Usage:
|
|
# ./bundle.sh [--output-dir DIR] [--platform PLATFORM]
|
|
#
|
|
# Options:
|
|
# --output-dir DIR Output directory for bundle (default: ./bundle)
|
|
# --platform PLATFORM Target platform (linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64)
|
|
# If not specified, bundles for current platform
|
|
# --all-platforms Bundle for all supported platforms
|
|
# --help Show this help message
|
|
#
|
|
# Examples:
|
|
# ./bundle.sh # Bundle for current platform
|
|
# ./bundle.sh --platform linux-amd64 # Bundle for specific platform
|
|
# ./bundle.sh --all-platforms # Bundle for all platforms
|
|
|
|
set -euo pipefail
|
|
|
|
# Validator versions - pin for reproducibility
|
|
SBOM_UTILITY_VERSION="0.17.0"
|
|
SPDX_TOOLS_VERSION="1.1.9"
|
|
|
|
# Download URLs
|
|
SBOM_UTILITY_BASE="https://github.com/CycloneDX/sbom-utility/releases/download/v${SBOM_UTILITY_VERSION}"
|
|
SPDX_TOOLS_BASE="https://github.com/spdx/tools-java/releases/download/v${SPDX_TOOLS_VERSION}"
|
|
|
|
# Script directory
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Defaults
|
|
OUTPUT_DIR="${SCRIPT_DIR}/bundle"
|
|
TARGET_PLATFORM=""
|
|
ALL_PLATFORMS=false
|
|
|
|
# Supported platforms
|
|
PLATFORMS=("linux-amd64" "linux-arm64" "darwin-amd64" "darwin-arm64" "windows-amd64")
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1" >&2
|
|
}
|
|
|
|
detect_platform() {
|
|
local os arch
|
|
|
|
case "$(uname -s)" in
|
|
Linux*) os="linux" ;;
|
|
Darwin*) os="darwin" ;;
|
|
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
|
|
*) log_error "Unsupported OS: $(uname -s)"; exit 1 ;;
|
|
esac
|
|
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) arch="amd64" ;;
|
|
arm64|aarch64) arch="arm64" ;;
|
|
*) log_error "Unsupported architecture: $(uname -m)"; exit 1 ;;
|
|
esac
|
|
|
|
echo "${os}-${arch}"
|
|
}
|
|
|
|
show_help() {
|
|
head -n 24 "$0" | tail -n +2 | sed 's/^# //' | sed 's/^#//'
|
|
exit 0
|
|
}
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--output-dir)
|
|
OUTPUT_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--platform)
|
|
TARGET_PLATFORM="$2"
|
|
shift 2
|
|
;;
|
|
--all-platforms)
|
|
ALL_PLATFORMS=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
log_error "Unknown option: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$TARGET_PLATFORM" && "$ALL_PLATFORMS" == "false" ]]; then
|
|
TARGET_PLATFORM=$(detect_platform)
|
|
fi
|
|
}
|
|
|
|
download_file() {
|
|
local url="$1"
|
|
local output="$2"
|
|
|
|
log_info "Downloading: ${url}"
|
|
|
|
if command -v curl &> /dev/null; then
|
|
curl -fsSL -o "$output" "$url"
|
|
elif command -v wget &> /dev/null; then
|
|
wget -q -O "$output" "$url"
|
|
else
|
|
log_error "Neither curl nor wget found"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
verify_checksum() {
|
|
local file="$1"
|
|
local expected="$2"
|
|
|
|
local actual
|
|
actual=$(sha256sum "$file" | cut -d' ' -f1)
|
|
|
|
if [[ "$actual" != "$expected" ]]; then
|
|
log_error "Checksum mismatch for ${file}"
|
|
log_error "Expected: ${expected}"
|
|
log_error "Actual: ${actual}"
|
|
return 1
|
|
fi
|
|
|
|
log_info "Checksum verified: ${file}"
|
|
return 0
|
|
}
|
|
|
|
bundle_sbom_utility() {
|
|
local platform="$1"
|
|
local bundle_dir="$2"
|
|
|
|
local os arch ext
|
|
os="${platform%-*}"
|
|
arch="${platform#*-}"
|
|
ext=""
|
|
|
|
[[ "$os" == "windows" ]] && ext=".exe"
|
|
|
|
local filename="sbom-utility-v${SBOM_UTILITY_VERSION}-${os}-${arch}.tar.gz"
|
|
local url="${SBOM_UTILITY_BASE}/${filename}"
|
|
local temp_dir
|
|
temp_dir=$(mktemp -d)
|
|
|
|
log_info "Bundling sbom-utility for ${platform}..."
|
|
|
|
download_file "$url" "${temp_dir}/${filename}"
|
|
|
|
# Extract
|
|
tar -xzf "${temp_dir}/${filename}" -C "${temp_dir}"
|
|
|
|
# Copy binary
|
|
local binary_name="sbom-utility${ext}"
|
|
local src_binary="${temp_dir}/${binary_name}"
|
|
local dest_binary="${bundle_dir}/sbom-utility/${SBOM_UTILITY_VERSION}/${binary_name}"
|
|
|
|
mkdir -p "$(dirname "$dest_binary")"
|
|
cp "$src_binary" "$dest_binary"
|
|
chmod +x "$dest_binary" 2>/dev/null || true
|
|
|
|
# Compute and record hash
|
|
local hash
|
|
hash=$(sha256sum "$dest_binary" | cut -d' ' -f1)
|
|
echo "sbom-utility/${SBOM_UTILITY_VERSION}/${binary_name}:${hash}" >> "${bundle_dir}/SHA256SUMS"
|
|
|
|
# Cleanup
|
|
rm -rf "$temp_dir"
|
|
|
|
log_info "sbom-utility ${SBOM_UTILITY_VERSION} bundled for ${platform}"
|
|
}
|
|
|
|
bundle_spdx_tools() {
|
|
local bundle_dir="$1"
|
|
|
|
local filename="tools-java-${SPDX_TOOLS_VERSION}-jar-with-dependencies.jar"
|
|
local url="${SPDX_TOOLS_BASE}/${filename}"
|
|
local temp_dir
|
|
temp_dir=$(mktemp -d)
|
|
|
|
log_info "Bundling spdx-tools (platform-independent JAR)..."
|
|
|
|
download_file "$url" "${temp_dir}/${filename}"
|
|
|
|
# Copy JAR
|
|
local dest_jar="${bundle_dir}/spdx-tools/${SPDX_TOOLS_VERSION}/${filename}"
|
|
mkdir -p "$(dirname "$dest_jar")"
|
|
cp "${temp_dir}/${filename}" "$dest_jar"
|
|
|
|
# Compute and record hash
|
|
local hash
|
|
hash=$(sha256sum "$dest_jar" | cut -d' ' -f1)
|
|
echo "spdx-tools/${SPDX_TOOLS_VERSION}/${filename}:${hash}" >> "${bundle_dir}/SHA256SUMS"
|
|
|
|
# Cleanup
|
|
rm -rf "$temp_dir"
|
|
|
|
log_info "spdx-tools ${SPDX_TOOLS_VERSION} bundled"
|
|
}
|
|
|
|
create_manifest() {
|
|
local bundle_dir="$1"
|
|
|
|
cat > "${bundle_dir}/manifest.json" << EOF
|
|
{
|
|
"schema": "stellaops.validator-bundle@1",
|
|
"generatedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
"validators": {
|
|
"sbom-utility": {
|
|
"version": "${SBOM_UTILITY_VERSION}",
|
|
"source": "https://github.com/CycloneDX/sbom-utility",
|
|
"formats": ["cyclonedx-json", "cyclonedx-xml"]
|
|
},
|
|
"spdx-tools": {
|
|
"version": "${SPDX_TOOLS_VERSION}",
|
|
"source": "https://github.com/spdx/tools-java",
|
|
"formats": ["spdx-json", "spdx-rdf", "spdx-tag-value"],
|
|
"requires": "java >= 11"
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
log_info "Created manifest.json"
|
|
}
|
|
|
|
create_readme() {
|
|
local bundle_dir="$1"
|
|
|
|
cat > "${bundle_dir}/README.md" << 'EOF'
|
|
# SBOM Validator Bundle
|
|
|
|
This bundle contains pre-downloaded SBOM validators for air-gap deployments.
|
|
|
|
## Contents
|
|
|
|
- **sbom-utility**: CycloneDX validator (Go binary)
|
|
- **spdx-tools**: SPDX validator (Java JAR, requires JRE 11+)
|
|
|
|
## Installation
|
|
|
|
1. Copy this bundle to your air-gapped environment
|
|
2. Set `STELLAOPS_VALIDATOR_DIR` environment variable to point to this directory
|
|
3. Or configure in `appsettings.yaml`:
|
|
|
|
```yaml
|
|
Scanner:
|
|
Validation:
|
|
BinaryDirectory: /path/to/validator-bundle
|
|
OfflineMode: true
|
|
```
|
|
|
|
## Verification
|
|
|
|
Verify file integrity using the SHA256SUMS file:
|
|
|
|
```bash
|
|
cd /path/to/validator-bundle
|
|
sha256sum -c SHA256SUMS
|
|
```
|
|
|
|
## Version Information
|
|
|
|
See `manifest.json` for exact versions and source URLs.
|
|
|
|
## License
|
|
|
|
- sbom-utility: Apache-2.0
|
|
- spdx-tools: Apache-2.0
|
|
EOF
|
|
|
|
log_info "Created README.md"
|
|
}
|
|
|
|
bundle_platform() {
|
|
local platform="$1"
|
|
local bundle_dir="${OUTPUT_DIR}/${platform}"
|
|
|
|
log_info "Creating bundle for platform: ${platform}"
|
|
|
|
mkdir -p "$bundle_dir"
|
|
|
|
# Initialize checksum file
|
|
: > "${bundle_dir}/SHA256SUMS"
|
|
|
|
# Bundle validators
|
|
bundle_sbom_utility "$platform" "$bundle_dir"
|
|
bundle_spdx_tools "$bundle_dir"
|
|
|
|
# Create metadata files
|
|
create_manifest "$bundle_dir"
|
|
create_readme "$bundle_dir"
|
|
|
|
# Sort checksums for determinism
|
|
sort -o "${bundle_dir}/SHA256SUMS" "${bundle_dir}/SHA256SUMS"
|
|
|
|
log_info "Bundle created: ${bundle_dir}"
|
|
}
|
|
|
|
main() {
|
|
parse_args "$@"
|
|
|
|
log_info "SBOM Validator Bundle Generator"
|
|
log_info "sbom-utility version: ${SBOM_UTILITY_VERSION}"
|
|
log_info "spdx-tools version: ${SPDX_TOOLS_VERSION}"
|
|
log_info "Output directory: ${OUTPUT_DIR}"
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
if [[ "$ALL_PLATFORMS" == "true" ]]; then
|
|
for platform in "${PLATFORMS[@]}"; do
|
|
bundle_platform "$platform"
|
|
done
|
|
else
|
|
bundle_platform "$TARGET_PLATFORM"
|
|
fi
|
|
|
|
log_info "Bundle generation complete!"
|
|
log_info "To install, copy the bundle to your target system and set STELLAOPS_VALIDATOR_DIR"
|
|
}
|
|
|
|
main "$@"
|