GitHub - Eurofunk/sbom-license-plugin: Gradle plugin to check licenses of dependencies using SBOM · GitHub
Skip to content

About

Gradle plugin to check licenses of dependencies using SBOM

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

SBOM license plugin

CI Status GitHub license Gradle Plugin Portal

The main purpose of this plugin is to provide a way how to check licenses of dependencies in the Gradle project based on the SBOM (software bill of material) file. To use this plugin, you need to have a valid SBOM file in your project. For generation of SBOM file you can use the cyclonedx gradle plugin.

Usage

Apply the plugin to your project:

plugins {
    id("io.github.eurofunk.sbom-license-plugin") version "0.0.1"
}

Task checkLicenses

This task checks the licenses of dependencies in the project based on the SBOM file.

tasks.checkLicenses {
    sbomFile = file("path/to/your/sbom.json")
}

Parameters:

Name Type Optional Default Value Description
sbomFile File No Path to the SBOM file.
dependenciesCheck EnumSet Yes DependencyCheck.TRANSITIVE Level at which dependencies are checked. Possible values: DIRECT, TRANSITIVE.
licenseGroups Collection Yes If not set then content of file license-groups.json is used Collection of license groups.
licenseGroupsFile File Yes If not set then file license-groups.json is used. If licenseGroups is also set then it has precedense before this property. Path to the license groups file.
policies Collection Yes Either this property or policiesFile must be set Collection of license policies.
policiesFile File Yes Either this property or policies must be set. If policies is also set, it has precedense before this property. Path to the license policies file.
customLicenses Collection Yes Either this property or customLicensesFile must be set Collection of custom licenses.
customLicensesFile File Yes Either this property or customLicenses must be set. If customLicenses is also set, it has precedense before this property. Path to the custom licenses file.

Policies

With policies, it's possible to define custom conditions for license validation. The plugin provides several built-in conditions:

  • AndCondition: Combines multiple conditions with a logical AND.
  • OrCondition: Combines multiple conditions with a logical OR.
  • LicenseGroupCondition: Validates if the license is part of a specific license group.
  • CoordinatesCondition: Validates if the dependency coordinates match a specific pattern.

There is always one root condition inside the policy, which could contain multiple nested conditions (in case AND or OR conditions). Policies can be defined inline or loaded from a file.

tasks.checkLicenses {
    policies = listOf(
        Policy (
            name = "Is not permissive besides com.example:example.*",
            rootCondition = AndCondition(
                conditions = listOf(
                    LicenseGroupCondition(
                        groupName = "Permissive",
                        operator = LicenseGroupCondition.Operator.IS_NOT
                    ),
                    CoordinatesCondition(
                        group = "com.example",
                        name = "example.*",
                        operator = CoordinatesCondition.Operator.DOES_NOT_MATCH
                    )
                )
            )
        )
    )
}
tasks.checkLicenses {
    policiesFile = file("path/to/your/policies.json")
}
LicenseGroupCondition

With policy LicenseGroupCondition it's possible to validate if license is/is not part of the license group. The operator can be set to either IS or IS_NOT. It's possible to use either inline definition of license groups or use the file with license groups. There is already a default configuration of license groups in the file license-groups.json.

tasks.checkLicenses {
    licenseGroups = listOf(
        LicenseGroup(
            name = "Permissive",
            riskWeight = 0,
            licenses = listOf("Apache-2.0", "Apache-1.1")
        ),
        LicenseGroup(
            name = "Weak Copyleft",
            riskWeight = 1,
            licenses = listOf("AFL-1.1", "LGPL-2.1", "LGPL-3.0", "MPL-2.0")
        )
    )
    policies = listOf(
        Policy(
            name = "Prohibit weak copyleft licenses",
            rootCondition = LicenseGroupCondition(
                groupName = "Weak Copyleft",
                operator = LicenseGroupCondition.Operator.IS
            )
        )
    )
}
tasks.checkLicenses {
    licenseGroupsFile = file("path/to/your/license-groups.json")
}

There is also a possibility to define a custom licenses in case the license is not party of any license or there's no license at all. This can be done using the customLicenses or customLicensesFile properties.

tasks.checkLicenses {
    customLicenses = listOf(
        ComponentBuilder().withGroup("com.eurofunk.*")
            .withExpression(ExpressionBuilder().withValue("Apache-2.0").build()).build()
    )
}
tasks.checkLicenses {
    customLicensesFile = file("path/to/your/custom-licenses.json")
}
CoordinatesCondition

With policy CoordinatesCondition it's possible to validate if dependency coordinates match a specific pattern. The pattern can be a simple string or a regex pattern. The operator can be set to either MATCHES or DOES_NOT_MATCH.

tasks.checkLicenses {
    policies = listOf(
        Policy(
            name = "Prohibit com.example:example.*",
            rootCondition = CoordinatesCondition(
                group = "com.example",
                name = "example.*",
                operator = CoordinatesCondition.Operator.MATCHES
            )
        )
    )
}
tasks.checkLicenses {
    policiesFile = file("path/to/your/policies.json")
}
LicenseCountCondition

With policy LicenseCountCondition it's possible to validate whether component contains desired number of licenses. This is useful for example when you want to ensure that each component has at least one license or to flag components with multiple licenses (dual licensing).

When evaluating SPDX expressions, all licenses mentioned in the expression are counted, regardless of the operators (OR, AND) used. For example, MIT OR Apache-2.0 and MIT AND Apache-2.0 both count as 2 licenses.

Operators:

  • EQUALS: Violation if the number of licenses is exactly equal to the configured count.
  • GREATER_THAN: Violation if the number of licenses is greater than the configured count.
  • LESS_THAN: Violation if the number of licenses is less than the configured count.
tasks.checkLicenses {
    policies = listOf(
        Policy(
            name = "Ensure at least one license",
            rootCondition = LicenseCountCondition(
                count = 1,
                operator = LicenseCountCondition.Operator.LESS_THAN
            )
        ),
        Policy(
            name = "Flag dual licensing",
            rootCondition = LicenseCountCondition(
                count = 1,
                operator = LicenseCountCondition.Operator.GREATER_THAN
            )
        )
    )
}

Releasing

The project JReleaser for publishing to Maven Central and creating GitHub releases.

Triggering a Release

Releases are triggered by creating and pushing a Git tag.

Release via GitHub UI

If you prefer to release directly from GitHub:

  1. Navigate to your repository on GitHub.
  2. Click on Releases -> Draft a new release.
  3. Click Choose a tag and type the new version (e.g., v1.0.0).
  4. Select Create new tag on publish.
  5. Enter a release title and description.
  6. Click Publish release.

Publishing Process

Automatic Publishing (GitHub Actions)

Once a tag is pushed (via either option above), the Gradle Package GitHub Action is triggered automatically. It performs the following:

  1. Builds the project.
  2. Stages the artifacts to a local directory.
  3. Uses JReleaser to:
    • Sign the artifacts with GPG.
    • Deploy artifacts to Maven Central Portal.
    • Create/Update a GitHub Release with the artifacts and changelog.
  4. Publishes the plugin to the Gradle Plugin Portal.

About

Gradle plugin to check licenses of dependencies using SBOM

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages