Skip to main content
GitLab DevSecOps Part 4: How to Ensure License Compliance
  1. Blogs/

GitLab DevSecOps Part 4: How to Ensure License Compliance

Author
Romano Roth
I believe the next competitive edge isn’t AI itself, it’s the organisation around it. As Chief AI Officer at Zühlke, I work with C-level leaders to build enterprises that sense, decide, and adapt continuously. 20+ years turning this conviction into practice.
Ask AI about this article

You ship a Java application that depends on Spring Boot, which depends on dozens of other libraries, each with its own license — and most teams cannot tell you what those licenses actually are. In Part 4 of our GitLab DevSecOps series, Patrick Steger and I add license compliance to the pipeline so the question is answered automatically on every commit. The good news: with GitLab Ultimate, this is one template line away.

Why a Java Project Needs License Compliance
#

Patrick frames it the same way as software composition analysis. We pull in a long list of libraries to build a simple Spring Boot app, and each one comes with its own license. Some licenses are friendly, some are restrictive, some are downright dangerous for a commercial product. Reading every license by hand is not realistic, and even if you tried once, the dependency graph changes the next time someone bumps a version. You need a tool that tells you what you are using and lets you decide what is acceptable.

What License Compliance Does in GitLab
#

License compliance is a GitLab Ultimate feature. The job runs through your project’s dependencies, derives the license for each one, checks the resulting list against the licenses you have marked as acceptable, and flags anything that is not compliant. Under the hood, GitLab uses the open source License Finder tool. You do not configure the scanner yourself; you configure the policy.

Enabling It in .gitlab-ci.yml
#

Enabling the scan is the same pattern we used for the dependency analysis: include the GitLab-provided template in .gitlab-ci.yml. In this case the template is License-Scanning.gitlab-ci.yml. Add the include, commit, and the next pipeline run picks up a new license scanning job. If you want to pin the version of the scanner, copy the template into your own repo and reference it from there — same trick as before.

The Maven Bug We Hit
#

When we first ran it, the job failed on line 41 with LicenseFinder::Maven is not installed. The image GitLab shipped at the time of recording had a bug — Maven was present in the container but not marked as executable. The fix is five lines at the top of the pipeline that mark the Maven binary as executable. With that in place the job runs cleanly. Worth knowing: when a managed scanner suddenly breaks, it is almost never your YAML — check the upstream image first.

Where the Results Live
#

Results show up in two places. Inside the pipeline, the job adds a Licenses tab. At project level, you find the full report under Security & Compliance → License Compliance. On our Spring Boot demo we were surprised to see five distinct licenses — for a project that pulled in Spring Boot and very little else. That visibility alone is worth the setup cost. Most teams have no idea how many licenses they ship with.

Defining the Policy
#

In License Compliance → Policies → Add license policy, you mark each license as allowed or denied. We allowed four of the five we found and intentionally left one without a decision so we could see how the pipeline reports it. The next pipeline run flagged exactly that one as “not yet acceptable” and the four others as approved. The pipeline does not fail on it by default in our setup, but you can wire that in.

Approval Workflow for New Licenses
#

GitLab also supports a basic approval workflow for licenses that have not been classified yet. Under approvals you add an approval rule and assign a group as approvers — we added the zuehlke-devsecops group, which at the time meant Patrick and me. From then on, when a merge request introduces a dependency with an unclassified license, the merge request needs an approval from someone in that group before it can be merged. The full effect of this only becomes visible when you start working with feature branches and merge requests, which is a later session, but it is worth setting up now.

What This Buys You
#

For one line in the pipeline file (plus the temporary Maven fix) you get a full inventory of every license your project depends on, a UI to classify them, an approval workflow for new ones, and a license report on every pipeline run. The whole point of shifting compliance left is exactly this: turning a manual, painful, end-of-project scramble into a check that runs on every commit and surfaces issues while they are still cheap to fix.

Key Takeaways
#

  1. You ship more licenses than you think. A bare Spring Boot demo pulled in five distinct licenses. On a real product, expect dozens. Without a scanner, no one on the team can answer the question “what licenses are we shipping?”

  2. Add the template, get the scan. License-Scanning.gitlab-ci.yml is a one-line include. The scanner uses License Finder under the hood; you do not have to wire it up yourself.

  3. The policy matters more than the tool. Scanning is the easy part. Deciding which licenses are acceptable for your business — and who is allowed to make that call — is the work that actually has to happen.

  4. Use the approval workflow. Assign a group as license approvers. New, unclassified licenses then become a conscious decision in a merge request, not something that slips into production unnoticed.

  5. Watch the upstream image. We hit a Maven-not-executable bug in the GitLab-provided container. When a managed scanner breaks, suspect the image before you suspect your config.

  6. Compliance is a CI concern, not a release concern. Running this on every commit means you classify a new license once, when it appears. Running it at release time means a panic the week before go-live.