Combining cdxgen and Dependency Track for simple SBOM handling
Having a centralized index for all the libraries used in your projects is a powerful tool in e.g. reacting to vulnerabilities and license changes. This is what a Software Bill of Materials (SBOM) is designed for, and thankfully the folks over at OWASP and CycloneDX have made generating and gathering this data easy and free!
The goal here is to build a pipeline of collection of
git repositories |> SBOM reports |> Dependency Track |> analysis.
First thing first, we need to have all our source code easily accessible for mass analysis. A simple way to do this is to clone all your repos to a local disk, as shown here for Azure Repos. This post will operate on the assumption that there's a folder structure of Project/Repo(s)
on your local disk.
Dependency Track is a SBOM analysis platform from OWASP, providing views for analysis and an API for SBOM ingestion. It runs as a docker container, and this post assumes that it's running at localhost:8089 and that there's an active API key.
CycloneDX has a great 'omnivorous' tool cdxgen for generating SBOM from pretty much any kind of repo. Using the CLI can be as easy as cdxgen -o bom.json
. It integrates nicely into Dependency Track by using the --server-url
and --api-key
parameters.
So with our project structure in place we can have a script looping through the directories, generating SBOM for each, and uploading the results directly to a running dt instance
$apiUrl = "http://localhost:8089"
$apiKey = "KEY_HERE"
$rootPath = "path/to/repos"
$tempBomPath = Join-Path $rootPath "bom.json"
# Add project names to exclude
$excludedProjects = @("Skip", "Me")
# Get all project directories (first level)
$projects = Get-ChildItem -Path $rootPath -Directory
foreach ($project in $projects)
{
if ($excludedProjects -contains $project.Name)
{
Write-Host "Skipping excluded project $( $project.Name )" -ForegroundColor Yellow
continue
}
Write-Host "Processing project $project" -ForegroundColor Cyan
# Get all repo directories (second level only)
$repos = Get-ChildItem -Path $project.FullName -Directory
$multipleRepos = $repos.Count -gt 1
foreach ($repo in $repos)
{
$repoPath = $repo.FullName
# Skip empty repositories
$hasFiles = Get-ChildItem -Path $repoPath -File -Recurse -ErrorAction SilentlyContinue
if (-not $hasFiles)
{
Write-Host "Skipping empty repository $repoPath" -ForegroundColor DarkYellow
continue
}
$projectName = if ($multipleRepos)
{
"$( $project.Name )__$( $repo.Name )"
}
else
{
$project.Name
}
Set-Location $repoPath
cdxgen-slim.exe -o $tempBomPath --server-url $apiUrl --api-key $apiKey --project-version "latest" --project-name $projectName --no-babel --fail-on-error --no-install-deps -t npm -t dotnet -t py
Remove-Item $tempBomPath -ErrorAction SilentlyContinue
}
}
Write-Host "SBOM generation completed!" -ForegroundColor Cyan
Note that in the script I'm using a local copy of cdxgen-slim.exe
here (for reasons). See the cdxgen installation instructions for an approach suiting your needs. It even runs in a container! The script also showcases some flags for what kinds of projects to analyze: -t npm -t dotnet -t py
And that's it basically - an SBOM generator that analyses your repos and pushes the results to Dependency Track for further analysis.
Thoughts, comments? Send me an email!