ExportSbom icon
Export icon
Get icon
Script icon
If icon
SlackIncomingWebhook icon
Fail icon
Set icon
Log icon

Gate Releases on New Licence Risk with an Aikido SBOM Diff Instead of a Full Backlog Scan

Export CycloneDX SBOMs from Aikido, compare against a stored baseline in Kestra KV, and fail the release only on newly introduced blocked licences.

Categories
CoreInfrastructure

Licence scanning usually fails for a boring reason: turn it on, get four hundred violations that predate everyone in the room, and switch it off again. This blueprint makes the check adoptable by comparing against a baseline instead of against zero. It exports the CycloneDX SBOM from Aikido, diffs the component set against the last approved release, and blocks only when a newly introduced dependency carries a blocked licence. Pre-existing violations are still reported, so the debt stays visible, but they do not stop today's release. The baseline advances only on a clean run, which means a blocked release can never quietly become the new normal.

How it works

  1. The export_sbom task (io.kestra.plugin.aikido.repositories.ExportSbom) pulls the CycloneDX SBOM with scope: EXCLUDE_DEV_DEPS, so the gate reflects what ships rather than what the test suite pulls in. includeVex: true carries exploitability context alongside the components.
  2. The supply_chain_issues task (io.kestra.plugin.aikido.issues.Export) pulls the open findings Aikido already raised for the same repository, including malware and licence issues, so the gate has scanner context and not just licence strings.
  3. The read_baseline task (io.kestra.plugin.core.kv.Get) loads the previously approved component set with errorOnMissing: false, so the very first run treats everything as pre-existing instead of blocking the world.
  4. The assess task (io.kestra.plugin.scripts.python.Script) does the diff in plain Python with no third-party dependencies. It splits findings into new_violations and pre_existing_violations and writes a verdict.json output file.
  5. The gate task (io.kestra.plugin.core.flow.If) branches on that verdict. The blocking path posts a structured Slack notice and then calls io.kestra.plugin.core.execution.Fail, so a release pipeline waiting on this execution stops too.
  6. The clean path advances the baseline through io.kestra.plugin.core.kv.Set and logs how much debt was carried forward.

What you get

  • A licence gate you can switch on today without a four hundred item backlog blocking the first release.
  • A real distinction between new risk and inherited risk, with both reported.
  • A baseline that only moves on a clean run, stored in Kestra KV rather than in a file someone has to remember to commit.
  • CycloneDX SBOMs exported straight from Aikido, with VEX context included.
  • Flow outputs (blocked, new_violations) that a parent release flow can branch on.

Who it's for

  • Release engineers who need a supply chain gate that does not halt every deploy on day one.
  • Open source programme offices tracking copyleft exposure across many repositories.
  • Teams answering customer security questionnaires who need a defensible, dated licence position.

Why orchestrate this with Kestra

The hard part of a licence gate is not parsing an SBOM, it is the state. You need last release's component set, a decision about what counts as new, a place to keep that memory, and a way to stop the pipeline without leaving the baseline corrupted. Kestra supplies the durable KV store for the baseline, the branch that only advances it on success, typed flow outputs a parent pipeline can read, and an execution record showing exactly which components entered the artifact on which release. In a CI script this becomes a cache file nobody trusts and a gate everyone bypasses.

Prerequisites

  • An Aikido workspace with API credentials carrying the repositories:read and issues:read scopes.
  • The numeric Aikido repository id, visible in the repository URL in the Aikido UI or from io.kestra.plugin.aikido.repositories.List.
  • A Slack incoming webhook for block notices.
  • Docker available to the Kestra worker for the Python assessment step, or swap taskRunner to the process runner if Python is installed on the host.

Secrets

  • AIKIDO_CLIENT_ID, AIKIDO_CLIENT_SECRET: OAuth2 credentials for the Aikido public API.
  • SLACK_WEBHOOK: incoming webhook used for block notices and gate failures.

Quick start

  1. Add the secrets above to your Kestra namespace.
  2. Run io.kestra.plugin.aikido.repositories.List once to find the numeric id of the repository you want to gate.
  3. Execute this flow once to record the starting baseline. The first run always passes.
  4. Adjust blocked_licenses to your own policy. The shipped list covers the common copyleft and source-available cases.
  5. Call the flow from your release pipeline with the real release_tag, and branch on the blocked output.

How to extend

  • Fan the gate across every repository by wrapping it in a parent flow that calls io.kestra.plugin.aikido.repositories.List and then a Subflow per repository.
  • Add a Pause task on the blocking branch so a licence exception can be granted in-flow and recorded against a named approver.
  • Open a Jira issue per new violation with io.kestra.plugin.jira.issues.Create and store the component name in the summary.
  • Switch format to SBOM_SPDX when your downstream tooling expects SPDX rather than CycloneDX.
  • Archive each SBOM to object storage with io.kestra.plugin.aws.s3.Upload so you can reconstruct the exact dependency set of any past release.
  • Extend the Python assessment to flag components whose Aikido issue export marks them as malware, not just those with a blocked licence.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.