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

Merge branch 'trivy-scan' into 'master'

feat(Trivy): add trivy-scan job

See merge request to-be-continuous/cnb!29
parents c2d2a3ec 904bf69f
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -197,7 +197,39 @@ Examples or User-Provided variables:
* [`MAVEN_SETTINGS_PATH`](https://devcenter.heroku.com/articles/using-a-custom-maven-settings-xml#defining-the-maven_settings_path-config-variable) (supported by the Heroku Maven buildpack) must be declared as `CNB_X_MAVEN_SETTINGS_PATH`,
* [`GOOGLE_GOLDFLAGS`](https://github.com/GoogleCloudPlatform/buildpacks#go-buildpacks) (supported by the Google Go buildpack) must be declared as `CNB_X_GOOGLE_GOLDFLAGS`.

### `docker-publish` job
### `cnb-trivy` job

This job performs a Vulnerability Static Analysis with [Trivy](https://github.com/aquasecurity/trivy) on your built image.

Without any configuration Trivy will run in [standalone](https://aquasecurity.github.io/trivy/v0.28.0/docs/references/modes/standalone/) mode.

If you want to run Trivy in client/server mode, you need to set the `CNB_TRIVY_ADDR` environment variable.

```yaml
variables:
  CNB_TRIVY_ADDR: "https://trivy.acme.host"
```

It is bound to the `package-test` stage, and uses the following variables:

| Input / Variable | Description                            | Default value     |
| ---------------------- | -------------------------------------- | ----------------- |
| `trivy-image` / `CNB_TRIVY_IMAGE` | The docker image used to scan images with Trivy | `registry.hub.docker.com/aquasec/trivy:latest` |
| `trivy-addr` / `CNB_TRIVY_ADDR` | The Trivy server address (for client/server mode)              | _(none: standalone mode)_  |
| `trivy-security-level-threshold` / `CNB_TRIVY_SECURITY_LEVEL_THRESHOLD` | Severities of vulnerabilities to be displayed (comma separated values: `UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`) | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL`  |
| `trivy-disabled` / `CNB_TRIVY_DISABLED` | Set to `true` to disable Trivy analysis          | _(none)_ |
| `trivy-args` / `CNB_TRIVY_ARGS` | Additional [`trivy client` arguments](https://aquasecurity.github.io/trivy/v0.27.1/docs/references/cli/client/)  | `--ignore-unfixed --vuln-type os` |
| `trivy-db-repository` / `CNB_TRIVY_DB_REPOSITORY` | OCI repository to retrieve Trivy Database from | _none_ (use Trivy default `ghcr.io/aquasecurity/trivy-db`) |
| `trivy-java-db-repository` / `CNB_TRIVY_JAVA_DB_REPOSITORY` | OCI repository to retrieve Trivy Java Database from | _none_ (use Trivy default `ghcr.io/aquasecurity/trivy-java-db:1`)_ |

In addition to a textual report in the console, this job produces the following reports, kept for one day:

| Report                            | Format                                                                       | Usage             |
|-----------------------------------| ---------------------------------------------------------------------------- | ----------------- |
| `reports/cnb-trivy-*.native.json` | native Trivy report format (json) | [DefectDojo integration](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/#trivy)<br/>_This report is generated only if DefectDojo template is detected_ |
| `reports/cnb-trivy-*.gitlab.json` | [Trivy report format for GitLab](https://aquasecurity.github.io/trivy/v0.30.4/docs/integrations/gitlab-ci/) format | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscontainer_scanning) |

### `cnb-publish` job

This job pushes (_promotes_) the built image as the _release_ image using [skopeo](https://github.com/containers/skopeo).

+42 −0
Original line number Diff line number Diff line
@@ -41,6 +41,48 @@
    }
  ],
  "features": [
    {
      "id": "trivy",
      "name": "Trivy",
      "description": "[Trivy](https://github.com/aquasecurity/trivy) vulnerability analysis",
      "disable_with": "CNB_TRIVY_DISABLED",
      "variables": [
        {
          "name": "CNB_TRIVY_IMAGE",
          "description": "The docker image used to scan images with Trivy",
          "default": "registry.hub.docker.com/aquasec/trivy:latest",
          "advanced": true
        },
        {
          "name": "CNB_TRIVY_ADDR",
          "type": "url",
          "description": "The Trivy server address"
        },
        {
          "name": "CNB_TRIVY_SECURITY_LEVEL_THRESHOLD",
          "type": "enum",
          "values": ["UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL", "LOW,MEDIUM,HIGH,CRITICAL", "MEDIUM,HIGH,CRITICAL", "HIGH,CRITICAL", "CRITICAL"],
          "description": "Severities of vulnerabilities to be displayed (comma separated values: `UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`)",
          "default": "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
        },
        {
          "name": "CNB_TRIVY_ARGS",
          "description": "Additional `trivy client` arguments",
          "default": "--ignore-unfixed --vuln-type os --exit-on-eol 1",
          "advanced": true
        },
        {
          "name": "CNB_TRIVY_DB_REPOSITORY",
          "description": "OCI repository to retrieve Trivy Database from",
          "advanced": true
        },
        {
          "name": "CNB_TRIVY_JAVA_DB_REPOSITORY",
          "description": "OCI repository to retrieve Trivy Java Database from",
          "advanced": true
        }
      ]
    },
    {
      "id": "publish",
      "name": "Publish",
+88 −0
Original line number Diff line number Diff line
@@ -50,6 +50,34 @@ spec:
      - manual
      - auto
      default: manual
    trivy-disabled:
      description: Disable Trivy
      type: boolean
      default: false
    trivy-image:
      description: The docker image used to scan images with Trivy
      default: registry.hub.docker.com/aquasec/trivy:latest
    trivy-addr:
      description: The Trivy server address
      default: ''
    trivy-security-level-threshold:
      description: 'Severities of vulnerabilities to be displayed (comma separated values: `UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`)'
      options:
        - UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
        - LOW,MEDIUM,HIGH,CRITICAL
        - MEDIUM,HIGH,CRITICAL
        - HIGH,CRITICAL
        - CRITICAL
      default: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
    trivy-args:
      description: Additional `trivy client` arguments
      default: --ignore-unfixed --vuln-type os --exit-on-eol 1
    trivy-db-repository:
      description: Custom OCI repository to retrieve Trivy Database from
      default: ''
    trivy-java-db-repository:
      description: Custom Java DB repository path
      default: ''
---
workflow:
  rules:
@@ -114,6 +142,16 @@ variables:
  CNB_PROD_PUBLISH_STRATEGY: $[[ inputs.prod-publish-strategy ]]
  CNB_PUBLISH_ARGS: $[[ inputs.publish-args ]]

  # default trivy
  CNB_TRIVY_SECURITY_LEVEL_THRESHOLD: $[[ inputs.trivy-security-level-threshold ]]
  CNB_TRIVY_IMAGE: $[[ inputs.trivy-image ]]
  CNB_TRIVY_ARGS: $[[ inputs.trivy-args ]]
  CNB_TRIVY_DB_REPOSITORY: $[[ inputs.trivy-db-repository ]]
  CNB_TRIVY_JAVA_DB_REPOSITORY: $[[ inputs.trivy-java-db-repository ]]

  CNB_TRIVY_DISABLED: $[[ inputs.trivy-disabled ]]
  CNB_TRIVY_ADDR: $[[ inputs.trivy-addr ]]
  
  # default production ref name (pattern)
  PROD_REF: /^(master|main)$/
  # default integration ref name (pattern)
@@ -453,6 +491,56 @@ cnb-build:
      dotenv:
        - cnb.env

# Security audit with trivy
cnb-trivy:
  extends: .cnb-base
  image:
    name: $CNB_TRIVY_IMAGE
    entrypoint: [""]
  stage: package-test
  variables:
    TRIVY_CACHE_DIR: ".trivycache/"
  script: |
    # cache cleanup is needed when scanning images with the same tags, it does not remove the database
    trivy image --clear-cache
    export TRIVY_USERNAME=${CNB_REGISTRY_SNAPSHOT_USER:-${CNB_REGISTRY_USER:-$CI_REGISTRY_USER}}
    export TRIVY_PASSWORD=${CNB_REGISTRY_SNAPSHOT_PASSWORD:-${CNB_REGISTRY_PASSWORD:-$CI_REGISTRY_PASSWORD}}
    basename=$(echo "${CNB_SNAPSHOT_IMAGE}" | sed 's|[/:]|_|g')
    mkdir -p ./reports
    if [[ -z "${CNB_TRIVY_ADDR}" ]]; then
      log_warn "\\e[93mYou are using Trivy in standalone mode. To get faster scans, consider setting the CNB_TRIVY_ADDR variable to the address of a Trivy server. More info here: https://aquasecurity.github.io/trivy/latest/docs/references/modes/client-server/\\e[0m"
      trivy image --download-db-only ${CNB_TRIVY_DB_REPOSITORY:+--db-repository $CNB_TRIVY_DB_REPOSITORY} ${CNB_TRIVY_JAVA_DB_REPOSITORY:+--java-db-repository $CNB_TRIVY_JAVA_DB_REPOSITORY}
      export trivy_opts="image"
    else
      log_info "You are using Trivy in client/server mode with the following server: ${CNB_TRIVY_ADDR}"
      export trivy_opts="image --server ${CNB_TRIVY_ADDR}"
    fi
    # Add common trivy arguments
    # The Java DB is downloaded client-side in client/server mode (https://github.com/aquasecurity/trivy/issues/3560), so we need to specify the Java DB repository
    export trivy_opts="${trivy_opts} ${CNB_TRIVY_JAVA_DB_REPOSITORY:+--java-db-repository $CNB_TRIVY_JAVA_DB_REPOSITORY} --no-progress --severity ${CNB_TRIVY_SECURITY_LEVEL_THRESHOLD} ${CNB_TRIVY_ARGS}"
    # GitLab format (no fail)
    trivy ${trivy_opts} --format template --exit-code 0 --template "@/contrib/gitlab.tpl" --output reports/cnb-trivy-${basename}.gitlab.json $CNB_SNAPSHOT_IMAGE
    # JSON format (no fail)
    if [[ "$DEFECTDOJO_TRIVY_REPORTS" ]]
    then
      trivy ${trivy_opts} --format json --exit-code 0 --output reports/cnb-trivy-${basename}.native.json $CNB_SNAPSHOT_IMAGE
    fi
    # console output (fail)
    trivy ${trivy_opts} --format table --exit-code 1 $CNB_SNAPSHOT_IMAGE
  artifacts:
    when: always
    paths:
      - "reports/cnb-trivy-*"
    reports:
      container_scanning: "reports/cnb-trivy-*.gitlab.json"
  cache:
    paths:
      - .trivycache/
  rules:
    - if: '$CNB_TRIVY_DISABLED == "true"'
      when: never
    - !reference [.test-policy, rules]

cnb-publish:
  extends: .cnb-base
  image: