Skip to content
Merged
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
24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test

on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable

- name: Run tests
run: make test
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

build:
CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o dtrack
CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o dtrack-cli
format:
go fmt ./...
format-check:
Expand All @@ -11,4 +11,6 @@ format-check:
echo "--- Diff ---"; \
gofmt -d .; \
exit 1; \
fi
fi
test:
go test -v -race ./...
102 changes: 71 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,68 @@

# Dependency-Track Lifecycle CLI

[![Release](https://github.com/MedUnes/dtrack-cli/actions/workflows/release.yml/badge.svg)](https://github.com/MedUnes/dtrack-cli/actions/workflows/release.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/medunes/dtrack-cli)](https://goreportcard.com/report/github.com/medunes/dtrack-cli)
[![License](https://img.shields.io/github/license/medunes/dtrack-cli)](LICENSE)
[![Go Reference](https://pkg.go.dev/badge/github.com/medunes/dtrack-cli.svg)](https://pkg.go.dev/github.com/medunes/dtrack-cli)

A Go-based CLI tool to automate the upload and lifecycle management of Software Bill of Materials (SBOM) in [OWASP Dependency-Track](https://dependencytrack.org/).
A Go-based CLI tool to automate the upload and lifecycle management of Software Bill of Materials (SBOM)
in [OWASP Dependency-Track](https://dependencytrack.org/).

This tool bridges the gap between simple API uploads and full CI/CD lifecycle management by handling **version sprawl**, **active states**, and **latest version tagging** in a single execution.
This tool bridges the gap between simple API uploads and full CI/CD lifecycle management by handling **version sprawl**,
**active states**, and **latest version tagging** in a single execution.

## 🚀 Why this tool? (The Gap)

If you simply use `curl` to upload an SBOM to Dependency-Track, you encounter two major problems over time. These are well-documented pain points in the community:
If you simply use `curl` to upload an SBOM to Dependency-Track, you encounter two major problems over time. These are
well-documented pain points in the community:

### 1. The "Version Sprawl" Problem

Every CI build creates a new version. If you have 100 builds, you have 100 "Active" versions. Dependency-Track monitors *all* active versions for vulnerabilities, meaning you will receive alerts for vulnerabilities in old, undeployed versions.
Every CI build creates a new version. If you have 100 builds, you have 100 "Active" versions. Dependency-Track monitors
*all* active versions for vulnerabilities, meaning you will receive alerts for vulnerabilities in old, undeployed
versions.

* **Community Validation:** Users have explicitly requested an `isActiveExclusively` flag to solve this, noting that "Over time there will be hundreds of 'active' versions, even though they are actually not 'active'".
* **Current Workaround:** Teams currently resort to manual housekeeping or complex scripts to set "dirty tags to inactive" to avoid polluting their risk score.
* **Our Solution:** The `-clean` flag automatically iterates through project versions and sets old ones to `active: false`.
* **Community Validation:** Users have explicitly requested an `isActiveExclusively` flag to solve this, noting that "
Over time there will be hundreds of 'active' versions, even though they are actually not 'active'".
* **Current Workaround:** Teams currently resort to manual housekeeping or complex scripts to set "dirty tags to
inactive" to avoid polluting their risk score.
* **Our Solution:** The `-clean` flag automatically iterates through project versions and sets old ones to
`active: false`.

### 2. The "Latest Version" Ambiguity

Dependency-Track attempts to guess the "latest" version, but it is not always accurate (e.g., when patching older release branches or dealing with pre-releases).
Dependency-Track attempts to guess the "latest" version, but it is not always accurate (e.g., when patching older
release branches or dealing with pre-releases).

* **Community Validation:** Users have reported issues where Dependency-Track incorrectly identifies pre-release versions as "latest," skewing "Outdated Component" analysis metrics.
* **Our Solution:** The `-latest` flag explicitly forces the version you are currently uploading to be marked `isLatest=true`, ensuring your "Outdated Component" metrics are calculated against the correct baseline.
* **Community Validation:** Users have reported issues where Dependency-Track incorrectly identifies pre-release
versions as "latest," skewing "Outdated Component" analysis metrics.
* **Our Solution:** The `-latest` flag explicitly forces the version you are currently uploading to be marked
`isLatest=true`, ensuring your "Outdated Component" metrics are calculated against the correct baseline.

### 3. Missing Auto-Purge/Cleanup

There is no built-in native feature to "keep only the last X versions" or "purge old versions" during upload.

* **Community Validation:** Feature requests for "automatic purging of projects" have been raised by users who find it "hard to do this manually" for projects with many releases.
* **Our Solution:** While we don't delete data (auditors hate that!), our tool effectively "archives" old versions by deactivating them, solving the noise issue without destroying history.
* **Community Validation:** Feature requests for "automatic purging of projects" have been raised by users who find it "
hard to do this manually" for projects with many releases.
* **Our Solution:** While we don't delete data (auditors hate that!), our tool effectively "archives" old versions by
deactivating them, solving the noise issue without destroying history.

## 🧠 Concepts: Active vs. Latest

Understanding these flags is critical for a clean dashboard:

| Flag | Dependency-Track Meaning | Impact on Pipeline |
| --- | --- | --- |
| **Active** | Indicates this version is currently deployed/supported. | **Critical.** Only "Active" versions contribute to Portfolio Metrics and trigger Vulnerability Alerts. |
| Flag | Dependency-Track Meaning | Impact on Pipeline |
|------------|------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| **Active** | Indicates this version is currently deployed/supported. | **Critical.** Only "Active" versions contribute to Portfolio Metrics and trigger Vulnerability Alerts. |
| **Latest** | Indicates this is the most current version of the project. | **Visual & Analytical.** Used as the baseline for "Outdated Component" analysis and marked with a badge in the UI. |

## 📦 Installation

Since this is a single-file Go program, you can run it directly or build a binary.

### Option 1: Download the lastest release binary (Recommended for CI)

**Run the following command to get the latest release binary**:

```bash
Expand Down Expand Up @@ -83,7 +96,7 @@ Use the `-ci` shortcut flag, which enables `-upload`, `-latest`, and `-clean` si

```bash
# Syntax: go run main.go [flags] <API_KEY> <PROJECT_NAME> <VERSION>
dtrack -ci -file ./build/bom.json $DT_API_KEY "My-Web-App" "v1.2.0"
dtrack-cli -ci -file ./build/bom.json $DT_API_KEY "My-Web-App" "v1.2.0"

```

Expand All @@ -98,7 +111,7 @@ dtrack -ci -file ./build/bom.json $DT_API_KEY "My-Web-App" "v1.2.0"
**Goal:** Check what versions exist and when they were uploaded without making changes.

```bash
dtrack -list $DT_API_KEY "My-Web-App"
dtrack-cli -list $DT_API_KEY "My-Web-App"

```

Expand All @@ -115,44 +128,71 @@ v1.1.0 false false 2023-10-20 10:00 def-456...

### Scenario 3: Maintenance / Hotfix

**Goal:** You uploaded a hotfix for an older version (`v1.0.1`) and want to mark it as Active, but you **do not** want it to become the "Latest" version (because `v2.0` already exists).
**Goal:** You uploaded a hotfix for an older version (`v1.0.1`) and want to mark it as Active, but you **do not** want
it to become the "Latest" version (because `v2.0` already exists).

Use specific flags instead of `-ci`.

```bash
# Upload and Clean (deactivate others), but do NOT touch the 'Latest' flag
dtrack -upload -clean $DT_API_KEY "My-Web-App" "v1.0.1"
dtrack-cli -upload -clean $DT_API_KEY "My-Web-App" "v1.0.1"

```

### Scenario 4: Manual Cleanup (No Upload)

**Goal:** Your dashboard is cluttered with 50 old versions. You want to keep `v2.0` as the only active one, but you don't have the SBOM file handy to re-upload.
**Goal:** Your dashboard is cluttered with 50 old versions. You want to keep `v2.0` as the only active one, but you
don't have the SBOM file handy to re-upload.

```bash
# Just clean up the metadata
dtrack -clean -latest $DT_API_KEY "My-Web-App" "v2.0"
dtrack-cli -clean -latest $DT_API_KEY "My-Web-App" "v2.0"

```

### Scenario 5: Debugging HTTP issues

**Goal:** An upload or lookup is failing in a way that isn't obvious — perhaps the base URL is wrong, an upstream proxy
is rewriting requests, or the server is responding with HTML instead of JSON. Reach for `-verbose` to surface the actual
request URL, response status, and a body preview (first 512 bytes).

```bash
dtrack-cli -verbose -list $DT_API_KEY "My-Web-App"

```

**Example output:**

```text
[verbose] → GET https://dtrack.example.com/api/v1/project?excludeInactive=false&name=My-Web-App&pageNumber=1&pageSize=50
[verbose] ← 200 OK
[verbose] Body (preview): [{"uuid":"abc-123","name":"My-Web-App","version":"v1.2.0",...}]
```

## 🚩 Flag Reference

| Flag | Description | Requirement |
| --- | --- |---------------------------------------|
| `-upload` | Uploads the file specified by `-file`. | Requires `VERSION` argument. |
| `-list` | Displays a table of all versions for this project. | |
| `-latest` | Marks the target version as `isLatest=true` and unsets it for others. | Requires `VERSION` argument. |
| `-clean` | Marks the target version as `active=true` and **all others** as `active=false`. | Requires `VERSION` argument. |
| `-ci` | **Recommended.** Shortcut for `-upload -latest -clean`. | Requires `VERSION` argument. |
| `-url` | Base URL of your Dependency-Track instance. | Default: `https://dtrack.example.com` |
| `-file` | Path to the SBOM file. | Default: `sbom.json` |
| Flag | Description | Requirement |
|-----------|---------------------------------------------------------------------------------|---------------------------------------|
| `-upload` | Uploads the file specified by `-file`. | Requires `VERSION` argument. |
| `-list` | Displays a table of all versions for this project. | |
| `-latest` | Marks the target version as `isLatest=true` and unsets it for others. | Requires `VERSION` argument. |
| `-clean` | Marks the target version as `active=true` and **all others** as `active=false`. | Requires `VERSION` argument. |
| `-ci` | **Recommended.** Shortcut for `-upload -latest -clean`. | Requires `VERSION` argument. |
| `-url` | Base URL of your Dependency-Track instance. Trailing slashes are stripped. | Default: `https://dtrack.example.com` |
| `-file` | Path to the SBOM file. | Default: `sbom.json` |
| `-verbose` | Prints HTTP request/response details (method, URL, status, body preview) for debugging. | Optional, additive to any other flag. |

## ⚠️ Requirements

* **Go 1.21+** (uses `slices` and `cmp` packages).
* **Network:** Access to the Dependency-Track API.
* **Permissions:** The API Key used must have `BOM_UPLOAD` and `PROJECT_CREATION_UPLOAD` permissions.

## 🧪 Development

* `make build` — produce the static binary.
* `make test` — run `go test -v -race ./...`.

## 📚 References

* Dependency Track REST API documentation https://docs.dependencytrack.org/integrations/rest-api/
Loading
Loading