Commit 3d15d017 authored by Girija Saint-Ange's avatar Girija Saint-Ange Committed by Bertrand Goareguer
Browse files

feat: add a semgrep job

parent d698f200
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -350,6 +350,35 @@ It is bound to the `test` stage.

The job generates an outdated report that you will find here: `NG_WORKSPACE_DIR/reports/ng-outdated.txt`.

### `ng-semgrep` job

The Angular template features a job `ng-semgrep` that performs a [Semgrep](https://semgrep.dev/docs/) analysis.

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

| Input / Variable                                                         | Description                                                                                                                                                                                                              | Default value                                                |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ |
| `semgrep-disabled` / `NG_SEMGREP_DISABLED`                             | Set to `true` to disable this job                                                                                                                                                                                        | _none_                                                       |
| `semgrep-image` / `NG_SEMGREP_IMAGE`                                   | The Docker image used to run [Semgrep](https://semgrep.dev/docs/)                                                                                                                                                        | `docker.io/semgrep/semgrep:latest`             <br/>[![Trivy Badge](https://to-be-continuous.gitlab.io/doc/secu/trivy-badge-NG_SEMGREP_IMAGE.svg)](https://to-be-continuous.gitlab.io/doc/secu/trivy-NG_SEMGREP_IMAGE) |
| `semgrep-args` / `NG_SEMGREP_ARGS`                                     | Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)                                                                                                                              | `--metrics off --disable-version-check --no-suppress-errors` |
| `semgrep-rules` / `NG_SEMGREP_RULES`                                   | Space-separated list of [Semgrep rules](https://semgrep.dev/docs/running-rules).<br/>Can be both local YAML files or remote rules from the [Semgrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix). | `p/javascript p/eslint p/gitlab-eslint`                      |
| `semgrep-registry-base-url` / `NG_SEMGREP_REGISTRY_BASE_URL`           | The Semgrep Registry base URL that is used to download the rules. No trailing slash.                                                                                                                                     | `https://semgrep.dev/c`                                      |
| `semgrep-download-rules-enabled` / `NG_SEMGREP_DOWNLOAD_RULES_ENABLED` | Download Semgrep remote rules                                                                                                                                                                                            | `true`                                                       |

> :information_source: Semgrep may [collect some metrics](https://semgrep.dev/docs/metrics), especially when using rules from the Semgrep Registry.
> To protect your privacy and let you run Semgrep in air-gap environments, this template disables all Semgrep metrics by default:
>
> - rules from the Semgrep registry are pre-downloaded and passed to Semgrep as local rule files (can be disabled by setting `semgrep-download-rules-enabled` / `NG_SEMGREP_DOWNLOAD_RULES_ENABLED` to `false`),
> - the `--metrics` option is set to `off`,
> - the `--disable-version-check` option is set.

In addition to a textual report in the console, this job produces the following reports, kept for one week and only available for download by users with the Developer role or higher:

| Report                                               | Format                                                                                       | Usage                                                                                                                                                                   |
| ---------------------------------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `$NG_WORKSPACE_DIR/reports/ng-semgrep.gitlab.json` | [GitLab's SAST format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)  | [GitLab integration](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportssast)                                                                    |
| `$NG_WORKSPACE_DIR/reports/ng-semgrep.native.json` | [Semgrep's JSON format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | [DefectDojo integration](https://docs.defectdojo.com/supported_tools/parsers/file/semgrep/)<br/>_This report is generated only if DefectDojo template is detected_ |

### `ng-sbom` job

This job generates a [SBOM](https://cyclonedx.org/) file listing installed packages using [@cyclonedx/cyclonedx-npm](https://www.npmjs.com/package/@cyclonedx/cyclonedx-npm).
+34 −0
Original line number Diff line number Diff line
@@ -123,6 +123,40 @@
        }
      ]
    },
    {
      "id": "ng-semgrep",
      "name": "Semgrep",
      "description": "[Semgrep](https://semgrep.dev/docs/) analysis",
      "disable_with": "NG_SEMGREP_DISABLED",
      "variables": [
        {
          "name": "NG_SEMGREP_IMAGE",
          "description": "The Docker image used to run [Semgrep](https://semgrep.dev/docs/)",
          "default": "docker.io/semgrep/semgrep:latest"
        },
        {
          "name": "NG_SEMGREP_ARGS",
          "description": "Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)",
          "default": "--metrics off --disable-version-check --no-suppress-errors"
        },
        {
          "name": "NG_SEMGREP_RULES",
          "description": "Space-separated list of [Semgrep rules](https://semgrep.dev/docs/running-rules).\n\nCan be both local YAML files or remote rules from the [Semgrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix).",
          "default": "p/javascript p/eslint p/gitlab-eslint"
        },
        {
          "name": "NG_SEMGREP_REGISTRY_BASE_URL",
          "description": "The Semgrep Registry base URL that is used to download the rules. No trailing slash.",
          "default": "https://semgrep.dev/c"
        },
        {
          "name": "NG_SEMGREP_DOWNLOAD_RULES_ENABLED",
          "description": "Download Semgrep remote rules",
          "type": "boolean",
          "default": "true"
        }
      ]
    },
    {
      "id": " ng-audit",
      "name": "ng-audit",
+92 −0
Original line number Diff line number Diff line
@@ -67,6 +67,30 @@ spec:
    audit-args:
      description: npm [audit](https://docs.npmjs.com/cli/v8/commands/npm-audit) arguments
      default: --audit-level=low
    semgrep-image:
      description: The Docker image used to run [Semgrep](https://semgrep.dev/docs/)
      default: docker.io/semgrep/semgrep:latest
    semgrep-disabled:
      description: Disable Semgrep
      type: boolean
      default: false
    semgrep-args:
      description: Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)
      default: --metrics off --disable-version-check --no-suppress-errors
    semgrep-rules:
      description: |-
        Space-separated list of [Semgrep rules](https://semgrep.dev/docs/running-rules).
        
        Can be both local YAML files or remote rules from the [Semgrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix).
      default: p/javascript p/eslint p/gitlab-eslint
    semgrep-registry-base-url:
      description: |-
        The Semgrep Registry base URL that is used to download the rules. No trailing slash.
      default: https://semgrep.dev/c
    semgrep-download-rules-enabled:
      description: Download Semgrep remote rules
      type: boolean
      default: true
    outdated-disabled:
      description: Set to `true` to disable npm outdated job
      type: boolean
@@ -172,8 +196,17 @@ variables:
  # Angular test
  NG_TEST_ARGS: $[[ inputs.test-args ]]
  NG_E2E_ARGS: $[[ inputs.e2e-args ]]
  # Audit
  NG_AUDIT_DISABLED: $[[ inputs.audit-disabled ]]
  NG_AUDIT_ARGS: $[[ inputs.audit-args ]]
  # Semgrep
  NG_SEMGREP_IMAGE: $[[ inputs.semgrep-image ]]
  NG_SEMGREP_DISABLED: $[[ inputs.semgrep-disabled ]]
  NG_SEMGREP_ARGS: $[[ inputs.semgrep-args ]]
  NG_SEMGREP_RULES: $[[ inputs.semgrep-rules ]]
  NG_SEMGREP_REGISTRY_BASE_URL: $[[ inputs.semgrep-registry-base-url ]]
  NG_SEMGREP_DOWNLOAD_RULES_ENABLED: $[[ inputs.semgrep-download-rules-enabled ]]
  # Outdated
  NG_OUTDATED_DISABLED: $[[ inputs.outdated-disabled ]]
  NG_OUTDATED_ALLOW_FAILURE: $[[ inputs.outdated-allow-failure ]]
  NG_OUTDATED_ARGS: $[[ inputs.outdated-args ]]
@@ -639,6 +672,32 @@ stages:
    done
  }

  function setup_semgrep_rules() {
    if [[ "${NG_SEMGREP_DOWNLOAD_RULES_ENABLED}" == "true" ]]
    then
      log_info "Download Semgrep rule files..."
      for rule in $NG_SEMGREP_RULES
      do
        if [[ -r "$rule" ]]
        then
          log_info "... rule file $rule found: skip"
          SEMGREP_RULES="${SEMGREP_RULES} $rule"
        else
          rule_url="${NG_SEMGREP_REGISTRY_BASE_URL}/$rule"
          log_info "... rule file $rule not found: downloading from $rule_url"
          dest_file="semgrep-${rule/p\//}.yml"
          wget "$rule_url" -O "$dest_file"
          SEMGREP_RULES="${SEMGREP_RULES} $dest_file"
        fi
      done
      SEMGREP_RULES="${SEMGREP_RULES:1}"
      export SEMGREP_RULES
    else
      # download not enabled: simply use $NG_SEMGREP_RULES
      export SEMGREP_RULES="${NG_SEMGREP_RULES}"
    fi
  }

  unscope_variables
  eval_all_secrets

@@ -724,6 +783,7 @@ ng-build:
#                                        - ng-sbom                                            #
#                                        - ng-audit                                           #
#                                        - ng-outdated                                        #
#                                        - ng-semgrep                                         #
###############################################################################################
ng-e2e:
  extends: .ng-cli-base
@@ -806,6 +866,38 @@ ng-outdated:
    - when: manual
      allow_failure: true

# SAST: Semgrep
ng-semgrep:
  extends: .ng-cli-base
  image: $NG_SEMGREP_IMAGE
  # unset cache from parent job
  cache: {}
  dependencies: []
  stage: test
  before_script:
    - !reference [.ng-cli-scripts]
    - mkdir -p -m 777 ${NG_WORKSPACE_DIR}/reports
    - setup_semgrep_rules
  script:
    - >- 
      semgrep ci ${TRACE+--verbose} ${NG_SEMGREP_ARGS} --subdir ${NG_WORKSPACE_DIR}
      --gitlab-sast-output=${NG_WORKSPACE_DIR}/reports/ng-semgrep.gitlab.json
      ${DEFECTDOJO_SEMGREP_REPORTS:+--json-output=${NG_WORKSPACE_DIR}/reports/ng-semgrep.native.json}
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    when: always
    expire_in: 1 week
    access: developer
    reports:
      sast: $NG_WORKSPACE_DIR/reports/ng-semgrep.gitlab.json
    paths:
      - $NG_WORKSPACE_DIR/reports/ng-semgrep.*
  rules:
    # exclude if disable
    - if: '$NG_SEMGREP_DISABLED == "true"'
      when: never
    - !reference [.test-policy, rules]

ng-sbom:
  extends: .ng-cli-base
  stage: test