Commit cec93612 authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

feat: add SBOM merge support

- add merge support
- support PURLs trimming
- autodetect PURL max len based on DT server version
parent e62afdf4
Loading
Loading
Loading
Loading
+48 −24
Original line number Diff line number Diff line
@@ -58,9 +58,18 @@ Here are some details about mandatory and optional permissions used by the templ
| `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 |

### Multiple SBOM strategy

When collecting several SBOM files in a project, this template supports two strategies:

- publish each SBOM independently in **separate projects** (default),
- or **merge** all SBOM files and publish the result into a single project.

The merge strategy can be simply enabled by setting the `merge` / `$DEPTRACK_MERGE` configuration to `true` (see [below](#configuration)).

### Project Path

Whenever a SBOM file is found, the template uploads it to the Dependency Track server under a certain project.\
Whenever a SBOM file is published, 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 double slashes `//` (the separator is also configurable with the `path-separator` input / `$DEPTRACK_PATH_SEPARATOR` variable).\
@@ -72,12 +81,12 @@ Each element is expected to be one of the following:

Lastly, the project path supports some **expressions**, that will be dynamically replaced when being evaluated:

| Expression       | Description                                                                                                                                                |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `{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)                                                                              |
| Expression       | Value for separate SBOM files                                                                                                                              | Value for merged SBOM |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `{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`. | `merged`              |
| `{sbom_name}`    | `Metadata > Component > Name` info extracted from the SBOM file (json or xml)                                                                              | `unk`                 |
| `{sbom_version}` | `Metadata > Component > Version` info extracted from the SBOM file (json or xml)                                                                           | _empty string_        |
| `{sbom_type}`    | `Metadata > Component > Type` info extracted from the SBOM file (json or xml)                                                                              | `unk`                 |

#### Default project path

@@ -104,7 +113,7 @@ Example: Let's imagine a GitLab project located in `acme-program/acme-services/a

Lastly, let's suppose the project production branch is `main`, and 2 software versions have been released so far: `1.0.0` and `1.1.0`.

Then the corresponding Dependency Track project structure will be:
The corresponding Dependency Track project structure **with separate SBOMs strategy** will be:

```
| Project name                                              | Version |
@@ -119,6 +128,17 @@ Then the corresponding Dependency Track project structure will be:
| ...
```

The corresponding Dependency Track project structure **with merged SBOMs strategy** will be:

```
| Project name                                         | Version |
| ---------------------------------------------------- | ------- |
| 📂 acme-program/acme-services                        |         |
| ├─📄 acme-program/acme-services/acme-user-api-merged | main    |
| ├─📄 acme-program/acme-services/acme-user-api-merged | 1.0.0   |
| ├─📄 acme-program/acme-services/acme-user-api-merged | 1.1.0   |
| ...

> :bulb: this default configuration handles the Dependency Track constraint that each project name has to be globally
> unique in the server.

@@ -144,13 +164,16 @@ Examples:
The Dependency Track template uses the following configuration.

| Input / Variable                                     | Description                                                                                                              | Default value                                                               |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| `sbom-scanner-image` / `DEPTRACK_SBOM_SCANNER_IMAGE` | The container image with [Dependency Track SBOM Scanner](https://gitlab.com/to-be-continuous/tools/dt-sbom-scanner) tool | `registry.gitlab.com/to-be-continuous/tools/dt-sbom-scanner:latest`         |
| `base-api-url` / `DEPTRACK_BASE_API_URL`             | Dependency Track server base API url (includes `/api`)                                                                   | _none_ (required)                                                           |
| :lock: `DEPTRACK_API_KEY`                            | Dependency Track API key                                                                                                 | _none_ (required)                                                           |
| `project-path` / `DEPTRACK_PROJECT_PATH`             | Dependency Track target project path to publish SBOM files to                                                            | `$CI_PROJECT_NAMESPACE//$CI_PROJECT_PATH-{file_prefix}@$CI_COMMIT_REF_NAME` |
| `path-separator` / `DEPTRACK_PATH_SEPARATOR`         | Separator to use in project path                                                                                         | `//`                                                                        |
| `sbom-patterns` / `DEPTRACK_SBOM_PATTERNS`           | SBOM file patterns to publish (supports glob patterns)                                                                   | `**/*.cyclonedx.json **/*.cyclonedx.xml`                                    |
| `merge` / `DEPTRACK_MERGE`                          | Merge all SBOM files into one (default `false`)                                                                          | _none_ (disabled)                                                           |
| `merge-output` / `DEPTRACK_MERGE_OUTPUT`            | Output merged SBOM file (only used with merge enabled) - _for debugging purpose_                                         | `reports/deptrack-merged.cyclonedx.json`                                    |
| `purl-max-len` / `DEPTRACK_PURL_MAX_LEN`            | PURLs max length (`-1`: auto, `0`: no trim, `>0`: trim to size - default: `-1`)                                          | `-1` (auto)                                                                 |

### Secrets management

@@ -169,3 +192,4 @@ Here are some advices about your **secrets** (variables marked with a :lock:):
   simply define its value as the [Base64](https://en.wikipedia.org/wiki/Base64) encoded value prefixed with `@b64@`:
   it will then be possible to mask it and the template will automatically decode it prior to using it.
3. Don't forget to escape special characters (ex: `$` -> `$$`).
```
+19 −0
Original line number Diff line number Diff line
@@ -35,6 +35,25 @@
      "default": "//",
      "advanced": true
    },
    {
      "name": "DEPTRACK_MERGE",
      "description": "Merge all SBOM files into one",
      "type": "boolean",
      "default": "false"
    },
    {
      "name": "DEPTRACK_MERGE_OUTPUT",
      "description": "Output merged SBOM file (only used with merge enabled) - _for debugging purpose_",
      "advanced": true,
      "default": "reports/deptrack-merged.cyclonedx.json"
    },
    {
      "name": "DEPTRACK_PURL_MAX_LEN",
      "description": "PURLs max length (`-1`: auto, `0`: no trim, `>0`: trim to size - default: `-1`)",
      "type": "number",
      "advanced": true,
      "default": "-1"
    },
    {
      "name": "DEPTRACK_SBOM_PATTERNS",
      "description": "SBOM file patterns to publish (supports glob patterns)",
+19 −0
Original line number Diff line number Diff line
@@ -27,6 +27,17 @@ spec:
    path-separator:
      description: Separator to use in project path
      default: '//'
    merge:
      description: Merge all SBOM files into one
      type: boolean
      default: false
    merge-output:
      description: Output merged SBOM file (only used with merge enabled) - _for debugging purpose_
      default: 'reports/deptrack-merged.cyclonedx.json'
    purl-max-len:
      description: 'PURLs max length (`-1`: auto, `0`: no trim, `>0`: trim to size - default: `-1`)'
      type: number
      default: -1
    sbom-patterns:
      description: SBOM file patterns to publish (supports glob patterns)
      default: '**/*.cyclonedx.json **/*.cyclonedx.xml'
@@ -64,6 +75,9 @@ variables:
  DEPTRACK_BASE_API_URL: $[[ inputs.base-api-url ]]
  DEPTRACK_PROJECT_PATH: $[[ inputs.project-path ]]
  DEPTRACK_PATH_SEPARATOR: $[[ inputs.path-separator ]]
  DEPTRACK_MERGE: $[[ inputs.merge ]]
  DEPTRACK_MERGE_OUTPUT: $[[ inputs.merge-output ]]
  DEPTRACK_PURL_MAX_LEN: $[[ inputs.purl-max-len ]]
  DEPTRACK_SBOM_PATTERNS: $[[ inputs.sbom-patterns ]]

  # default production ref name (pattern)
@@ -323,6 +337,11 @@ dependency-track:
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
  script:
    - sbom-scanner
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    paths:
      - "reports/deptrack-*"
  rules:
    # on production branch: auto
    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF'