The template will be triggered at each pipeline execution on your production branch (`main` or `master` by default) and each release pipeline (upon semver tag creation).
It will scan for all SBOM file in your project structure and will upload them to the configured Dependency Track server.\
:information_source: SBOM files should have been generated in the upstream pipeline with appropriate tools, and propagated as build artifacts. Most to-be-continuous templates already support - whenever possible - a job to produce a SBOM report.
### API Key permissions
In order to operate, this template needs a Dependency Track API Key.
Here are some details about mandatory and optional permissions used by the template:
| `BOM_UPLOAD` | **mandatory** | Required to publish SBOM files to the Dependency Track server |
| `PROJECT_CREATION_UPLOAD` | **optional** | This is required if you want to automatically create the project while uploading the SBOM files when the project does not exist (**but the parent project must exist**) |
| `VIEW_PORTFOLIO` and `PORTFOLIO_MANAGEMENT` | **optional** | Required if you want to automatically create one or several project ancestors prior to uploading the SBOM files.<br/>Granting those permissions is not recommended in the general case as they virtually give administration rights to the API Key owner |
### Project Path
Whenever a SBOM file is found, the template uploads it to the Dependency Track server under a certain project.\
The target project is determined by evaluating the `project-path` input / `$DEPTRACK_PROJECT_PATH` variable (see [configuration chapter](#configuration)).
The project path is a sequence of elements separated by forward slashes `/` (although the separator is also configurable with the `path-separator` input / `$DEPTRACK_PATH_SEPARATOR` variable).\
Each element is expected to be one of the following:
1.`#11111111-1111-1111-1111-111111111111`: a project [Universally Unique Identifier (UUID)](https://en.wikipedia.org/wiki/Universally_unique_identifier)(starting with a hash `#`)
2.`project-name@version`: a **project name** and a **version** (separated with a `@`)
3.`project-name`: a **project name** only (empty version)
Lastly, the project path supports some **expressions**, that will be dynamically replaced when being evaluated:
| `{file_prefix}` | SBOM filename prefix (before the first dot).<br/>Ex: when processing the file `reports/docker-sbom.cyclonedx.json`, `{file_prefix}` will be `docker-sbom`. |
| `{sbom_name}` | `Metadata > Component > Name` info extracted from the SBOM file (json or xml) |
| `{sbom_version}` | `Metadata > Component > Version` info extracted from the SBOM file (json or xml) |
| `{sbom_type}` | `Metadata > Component > Type` info extracted from the SBOM file (json or xml) |
#### Default project path
By default, the Dependency Track project path is set to `$CI_PROJECT_PATH/$CI_PROJECT_NAME-{file_prefix}@{sbom_version}`.
That means:
- The project structure in Dependency Track will **match exactly** the GitLab groups, sub-groups and projects hierarchy.
- Each SBOM file found will be uploaded to a sub-project with same name as the project, suffixed with the SBOM file prefix and with project version extracted from the SBOM file.
- If the API key has only the `BOM_UPLOAD` permission, then all the projects hierarchy must pre-exist down to the parent project and even SBOM sub-projects.
- If the API key has the extra `PROJECT_CREATION_UPLOAD` permission, then all the projects hierarchy must pre-exist down to the parent project (hosting the SBOM sub-projects).
- If the API key has the extra `VIEW_PORTFOLIO` and `PORTFOLIO_MANAGEMENT` permissions (not recommanded), then the project hierarchy will be automatically created by the template if it doesn't exist.
Example: Let's imagine a GitLab project located in `acme-program/acme-services/acme-user-api` with 2 SBOM files generated by the pipeline:
-`py-sbom.cyclonedx.json`: the SBOM of the Python application implementation, with version `1.1.0`
-`docker-sbom.cyclonedx.json`: the SBOM of the container image, with version `main`
Then the corresponding Dependency Track project structure will be:
```
| Project name | Version |
| ---------------------------------- | ------- |
| 📂 acme-program | |
| ├─📂 acme-services | |
| │ ├─📂 acme-user-api | |
| │ │ ├─📄 acme-user-api-py-sbom | 1.1.0 |
| │ │ └─📄 acme-user-api-docker-sbom | main |
| ...
```
#### Other use cases
The default template behavior can be changed by overridding the `project-path` input / `$DEPTRACK_PROJECT_PATH` variable.
Examples:
-`#550e8400-e29b-41d4-a716-446655440000`: every SBOM found will be published to the project with UUID `550e8400-e29b-41d4-a716-446655440000`<br/>
:information_source: as Dependency Track is only able to store one SBOM per project, this configuration is suitable only if exactly one SBOM file is found (otherwise each one will overwrite the previous one)
-`my-project@v1.1.0`: every SBOM found will be published to the project with name `my-project` and version `v1.1.0`<br/>
:information_source: depending on your API key permissions, `sbom-scanner` might try to automatically create the project if it doesn't exist<br/>
:information_source: as in the previous example, this configuration is suitable only if exactly one SBOM file is found
-`#550e8400-e29b-41d4-a716-446655440000/my-project-{file_prefix}@{sbom_version}`: every SBOM found will be published to a project named `my-project-{file_prefix}` and version `{sbom_version}` (extracted from the SBOM file),
direct child of project with UUID `550e8400-e29b-41d4-a716-446655440000`<br/>
:information_source: depending on your API key permissions, `sbom-scanner` might try to automatically create the project if it doesn't exist
-`acme-program@v2/acme-services@v1.3/acme-user-api@v1.3/acme-user-api-{file_prefix}`: complete project path only defined by project names and versions<br/>
:information_source: depending on your API key permissions, `sbom-scanner` might try to automatically create the project and its ancestors if they don't exist
> :bulb: you may decide to overwrite the path separator (ex: double slash `//`) if you want your project names to contain slashes.
>
> Example:
>
> ```yaml
> variables:
> DEPTRACK_PATH_SEPARATOR: "//"
> # flaten the projects hierarchy to depth 2 (full GitLab project namespace is mapped to one single DT project)