Dependency-Track: Update portfolio
The Dependency-Track portfolio page provides a comprehensive overview of all projects, primarily applications, that are being tracked for security vulnerabilities and outdated dependencies. This page serves as a crucial tool for identifying which projects contain vulnerabilities that need to be addressed and for monitoring dependencies that require updates to maintain application security and compliance. There is this page in Dependency Track where you can see all projects ( by projects we mean mostly applications ) which have vulnerabilities and needs to be fixed, dependency track is to follow which dependencies are out of track and needs to be updated
[
dependency-track.attracs.com
https://dependency-track.attracs.com/projects
](https://dependency-track.attracs.com/projects)
The image below is a visual aid showing the Dependency-Track portfolio page and how projects are listed for tracking and management:
To streamline the process of updating dependencies and managing vulnerabilities across these projects, we have developed automation scripts. These scripts help automate the update process, ensuring consistency and saving time.
The following script automates the process of updating project dependencies, generating Software Bill of Materials (SBOMs), and activating the new versions in Dependency-Track:
This are the following scripts:
[
github.com
https://github.com/Attracs/docker-devops-dependency-track/blob/main/manual-runs/update_dtrack_portfolio.sh
](https://github.com/Attracs/docker-devops-dependency-track/blob/main/manual-runs/update_dtrack_portfolio.sh)
#!/usr/bin/env bash
set -euo pipefail
# ============================================================
# LOAD API KEY
# ============================================================
SCRIPT_DIR="$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" 2626 pwd)"
if [[ -z "${API_KEY:-}" ]]; then
if [[ -f "$SCRIPT_DIR/vars.conf" ]]; then
# shellcheck source=/dev/null
source "$SCRIPT_DIR/vars.conf"
else
echo "ERROR: API_KEY not set and vars.conf not found"
exit 1
fi
fi
API_BASE="https://dependency-track-api.attracs.com/api/v1"
# ============================================================
# LOOP THROUGH ALL PROJECTS
# ============================================================
for PROJECT_PATH in "$SCRIPT_DIR"/projects/*; do
[[ -d "$PROJECT_PATH/.git" ]] || continue
PROJECT_NAME="$(basename "$PROJECT_PATH")"
echo
echo "=========================================="
echo "Processing repository: $PROJECT_NAME"
echo "=========================================="
cd "$PROJECT_PATH"
# ============================================================
# GIT FETCH (SAFE)
# ============================================================
echo "Fetching branches and tags..."
git fetch --all --tags --prune || {
echo "WARNING: git fetch failed 2014 skipping $PROJECT_NAME"
continue
}
# Fix shallow repo (CI-safe)
if git rev-parse --is-shallow-repository | grep -q true; then
echo "Repository is shallow 2014 unshallowing..."
git fetch --unshallow --tags || true
fi
# ============================================================
# DETERMINE NEWEST: TAG OR COMMIT
# ============================================================
HEAD_COMMIT="$(git rev-parse --short HEAD)"
HEAD_TS="$(git log -1 --format=%ct HEAD)"
LATEST_TAG="$(git tag --sort=-creatordate | head -n 1 || true)"
TAG_TS=0
if [[ -n "$LATEST_TAG" ]]; then
TAG_TS="$(git log -1 --format=%ct "$LATEST_TAG")"
fi
if [[ "$TAG_TS" -gt "$HEAD_TS" ]]; then
PROJECT_VERSION="${LATEST_TAG#v}"
VERSION_SOURCE="tag ($LATEST_TAG)"
else
PROJECT_VERSION="$HEAD_COMMIT"
VERSION_SOURCE="commit ($HEAD_COMMIT)"
fi
OUTPUT_FILE="$SCRIPT_DIR/${PROJECT_NAME}-${PROJECT_VERSION}-sbom.xml"
echo "Version : $PROJECT_VERSION"
echo "Version source : $VERSION_SOURCE"
echo "SBOM file : $OUTPUT_FILE"
# ============================================================
# GENERATE SBOM
# ============================================================
syft dir:. \
--source-name "$PROJECT_NAME" \
--source-version "$PROJECT_VERSION" \
-o cyclonedx-xml@1.5="$OUTPUT_FILE"
cyclonedx validate \
--fail-on-errors \
--input-file "$OUTPUT_FILE" \
--input-format xml
# ============================================================
# UPLOAD SBOM
# ============================================================
echo "Uploading SBOM..."
curl -sS -X POST "$API_BASE/bom" \
-H "X-Api-Key: $API_KEY" \
-H "Content-Type: multipart/form-data" \
-H "X-Alto-Is-Latest-Version: true" \
-F "autoCreate=true" \
-F "projectName=$PROJECT_NAME" \
-F "projectVersion=$PROJECT_VERSION" \
-F "projectClassifier=APPLICATION" \
-F "bom=@$OUTPUT_FILE" \
>/dev/null
# ============================================================
# ACTIVATE NEW VERSION / DEACTIVATE OLD
# ============================================================
PROJECTS_JSON="$(curl -sS -H "X-Api-Key: $API_KEY" "$API_BASE/project?name=$PROJECT_NAME")"
NEW_UUID="$(echo "$PROJECTS_JSON" | jq -r --arg V "$PROJECT_VERSION" '.[] | select(.version==$V) | .uuid')"
if [[ -z "$NEW_UUID" || "$NEW_UUID" == "null" ]]; then
echo "ERROR: New version not found 2014 skipping activation"
continue
fi
echo "$PROJECTS_JSON" | jq -r '.[] | "\(.uuid) \(.version)"' | while read -r UUID VERSION; do
if [[ "$UUID" == "$NEW_UUID" ]]; then
ACTIVE=true
IS_LATEST=true
else
ACTIVE=false
IS_LATEST=false
fi
curl -sS -X PATCH \
-H "X-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
"$API_BASE/project/$UUID" \
-d "{\"active\": $ACTIVE, \"isLatest\": $IS_LATEST}" \
>/dev/null
done
echo "271 Finished $PROJECT_NAME"
done
echo
echo "271 All repositories processed successfully."
This script performs several key actions for each project:
- Determines whether the latest tag or the latest commit is newer, and uses that as the project version.
- Generates a Software Bill of Materials (SBOM) for the project.
- Uploads the SBOM to Dependency-Track.
- Deactivates all old versions in Dependency-Track, keeping only the latest version as active.
Note: Even though only the latest version is marked as active, you can still view older versions in Dependency-Track for reference and historical tracking.
In summary, this automation ensures that all repositories are processed successfully, keeping dependencies up to date and vulnerabilities under control.
Automating with GitHub Actions
After local testing and verifying that everything works as expected, this automation is set up to run automatically using GitHub Actions. The workflow is scheduled to execute every Friday at 00:00, ensuring all projects are updated regularly. Below is the GitHub Actions workflow script used to automate this process:
[
github.com
https://github.com/Attracs/docker-devops-dependency-track/blob/main/.github/workflows/update-dtrack.yml
](https://github.com/Attracs/docker-devops-dependency-track/blob/main/.github/workflows/update-dtrack.yml)
name: Dependency-Track
on:
schedule:
- cron: '0 0 * * 5' # Every Friday at midnight UTC
workflow_dispatch:
push:
tags:
- 'v*'
jobs:
dtrack:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq curl unzip git
- name: Install Syft
uses: anchore/sbom-action/download-syft@v0
- name: Install CycloneDX CLI
run: |
curl -Lo cyclonedx-cli \
https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.29.1/cyclonedx-linux-x64
chmod +x cyclonedx-cli
sudo mv cyclonedx-cli /usr/local/bin/cyclonedx
- name: Make scripts executable
working-directory: manual-runs
run: chmod +x *.sh
- name: Clone / update repositories
working-directory: manual-runs
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: ./clone_repos.sh
- name: Run Dependency-Track portfolio update
working-directory: manual-runs
env:
API_KEY: ${{ secrets.DTRACK_API_KEY }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: ./update_dtrack_portfolio.sh
This workflow ensures that the update process is performed automatically on a weekly basis, keeping all tracked projects up to date in Dependency-Track. This automation is executed every Friday, so that by Monday meetings, developers can review and address the latest vulnerabilities that need to be fixed.