Dependency Track is an open source component analysis platform from OWASP. You upload the SBOM of your application, and Dependency Track keeps track of the components inside it. It checks those components against vulnerability sources like the National Vulnerability Database, GitHub Advisories and OSV. It also lets you define policies and send notifications when something new shows up. In short: it tells you which of your applications are affected when the next vulnerable library hits the news.
Recently Dependency Track got an upgrade and version 5 was released. So, time to upgrade!
However, that turned out not to be as easy as expected. It took us 2 attempts. Our first attempt failed completely, so we took a different route. Here is what we tried and the two things that cost us the most time.
Big shout out to Jef, who looked over my shoulder during the upgrade and helped tackling the issues when we got stuck.
Two approaches in the documentation
The Dependency Track documentation describes two ways to get a new version running.
- Upgrading running instances: the in-place approach. You run the schema migrations, then replace the API server instances one at a time. This gives you no planned downtime, as long as more than one instance is running and the release notes don't call for a full stop.
- Migrating from v4 to v5: a separate migration. The
v4-migratortool copies your v4 data into a new v5 database. v4 has to be offline while it runs, and v5 only supports PostgreSQL.
We started with the first one. That turned out to be no success for us.
Attempt 1: the in-place upgrade
We pointed the v5 container at our existing v4 database and let it migrate on startup.
That didn't work. The migration process started, but failed with the following error message:
Caused by: org.flywaydb.core.internal.sqlscript.FlywaySqlScriptException: Failed to execute script V202605111028__add_latest_version_published_at_column_to_package_metadata.sql No matter what we tried, we couldn't fix this error.
Remark: v5 renames many configuration properties and environment variables, and it no longer accepts the v4 names. If you reuse your v4 configuration in Azure Container Apps, check it against the v5 configuration reference.
Attempt 2: migrate the database separately
Instead of one big step, we split the upgrade in two. First, we migrated the data into a v5 database with v4-migrator, then we started the v5 application on top of it.
Before you start, the documentation lists a few requirements:
- v4 must be on version 4.14.2 or later, and the v4 API server must be stopped.
- The target is a dedicated PostgreSQL 14+ database. Don't start the v5 API server against it before the migration has run.
- The database user you use for the migration should be the same one the v5 API server uses afterwards.
The migration runs in steps: bootstrap applies the v5 schema on the target database, verify checks the target, and run does the extract, transform and load. Afterwards you verify again and cleanup the staging schema.
The migration tool is available in a docker container that we ran locally during the upgrade process.
Two things cost us a lot of time.
Caveat 1: the quotes in the documentation
The documentation shows the JDBC URLs in single quotes:
docker run --rm -t ghcr.io/dependencytrack/v4-migrator:5.0.0 bootstrap \
--target-url 'jdbc:postgresql://target-host:5432/dtrack' \
--target-user dtrack \
--target-pass
That doesn't work for us. It only worked after we removed the quotes:
docker run --rm -t ghcr.io/dependencytrack/v4-migrator:5.0.0 bootstrap \
--target-url jdbc:postgresql://target-host:5432/dtrack \
--target-user dtrack \
--target-pass
The error didn't point at the quotes, so we checked permissions, connectivity, versions (and even the weather) first.
Caveat 2: the pg_trgm extension
Dependency Track v5 needs the pg_trgm extension. The bootstrap step tries to install it, and the preflight check verifies it.
This extension was not installed out-of-the-box. So, the preflight check failed. Because we were using an Azure Database for PostgreSQL Flexible Server: the extension must be allow-listed first through the azure.extensions server parameter:
After that, we could create the extension:
CREATE EXTENSION IF NOT EXISTS pg_trgm;
Starting the v5 application
With the migrated database in place, we could finally deploy the v5 container to Azure Container Apps.
This time it started without problems.
Tip: The migration is deliberately lossy in a few places. Every notification rule is disabled after the migration, and repository and analyzer credentials have to be entered again in the v5 secret manager. Plan some time for this after the cutover.
That's it!