diff --git a/README.md b/README.md index 691d5146e615a2694299774ca51641d6a7581a92..c4aceec0a83e7ee9624e44476c8820b44ca13db0 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,34 @@ In addition to a textual report in the console, this job produces the following | `$GO_PROJECT_DIR/reports/go-ci-lint.codeclimate.json` | [Code Climate](https://docs.codeclimate.com/docs/pylint) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) | | `$GO_PROJECT_DIR/reports/go-ci-lint.checkstyle.xml` | Checkstyle | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/) | +### `go-semgrep` job + +This job 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` / `GO_SEMGREP_DISABLED` | Set to `true` to disable this job | _none_ | +| `semgrep-image` / `GO_SEMGREP_IMAGE` | The Docker image used to run [Semgrep](https://semgrep.dev/docs/) | `registry.hub.docker.com/semgrep/semgrep:latest` | +| `semgrep-args` / `GO_SEMGREP_ARGS` | Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | `--metrics off --disable-version-check` | +| `semgrep-rules` / `GO_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 [Segmrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix). | `p/golang p/gosec` | +| `semgrep-download-rules-enabled` / `GO_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` / `GO_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: + +| Report | Format | Usage | +| ------ | ------ | ----- | +| `$GO_PROJECT_DIR/reports/golang-semgrep.gitlab.json` | [GitLab's SAST format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportssast) | +| `$GO_PROJECT_DIR/reports/golang-semgrep.native.json` | [Semgrep's JSON format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | [DefectDojo integration](https://documentation.defectdojo.com/integrations/parsers/file/semgrep)<br/>_This report is generated only if DefectDojo template is detected_ | + ### `go-mod-outdated` job This job enables a manual [Go-mod-outdated](https://github.com/psampaz/go-mod-outdated) analysis. @@ -249,4 +277,4 @@ It is bound to the `test` stage, and uses the following variables: | Input / Variable | Description | Default value | | --------------------- | -------------------------------------- | ----------------- | | `vulncheck-disabled` / `GO_VULNCHECK_DISABLED` | Set to `true` to disable this job | _none_ -| `vulncheck-args` / `GO_VULNCHECK_ARGS` | `govulncheck` [command line arguments](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck#hdr-Flags) | `./...` | \ No newline at end of file +| `vulncheck-args` / `GO_VULNCHECK_ARGS` | `govulncheck` [command line arguments](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck#hdr-Flags) | `./...` | diff --git a/kicker.json b/kicker.json index 3d1e9cc12cac36ba39360b0abcc90cedb93c680c..df960da1ff442cda4674a2f6ff14807617b75a4c 100644 --- a/kicker.json +++ b/kicker.json @@ -152,6 +152,35 @@ } ] }, + { + "id": "go-semgrep", + "name": "Semgrep", + "description": "[Semgrep](https://semgrep.dev/docs/) analysis", + "disable_with": "GO_SEMGREP_DISABLED", + "variables": [ + { + "name": "GO_SEMGREP_IMAGE", + "description": "The Docker image used to run [Semgrep](https://semgrep.dev/docs/)", + "default": "registry.hub.docker.com/semgrep/semgrep:latest" + }, + { + "name": "GO_SEMGREP_ARGS", + "description": "Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)", + "default": "--metrics off --disable-version-check" + }, + { + "name": "GO_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/golang p/gosec" + }, + { + "name": "GO_SEMGREP_DOWNLOAD_RULES_ENABLED", + "description": "Download Semgrep remote rules", + "type": "boolean", + "default": "true" + } + ] + }, { "id": "govulncheck", "name": "Govulncheck", diff --git a/templates/gitlab-ci-golang.yml b/templates/gitlab-ci-golang.yml index b3c300c5c14f3f6728d869c85fd5f5cc80ecb2ee..14b9045058649bba24461aa149b07bbd62b2ce50 100644 --- a/templates/gitlab-ci-golang.yml +++ b/templates/gitlab-ci-golang.yml @@ -81,6 +81,26 @@ spec: ci-lint-args: description: '`golangci-lint` [command line arguments](https://github.com/golangci/golangci-lint#command-line-options)' default: -E gosec,goimports ./... + semgrep-image: + description: The Docker image used to run [Semgrep](https://semgrep.dev/docs/) + default: registry.hub.docker.com/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 + semgrep-rules: + description: |- + Space-separeted 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/golang p/gosec + semgrep-download-rules-enabled: + description: Download Semgrep remote rules + type: boolean + default: true mod-outdated-args: description: '`god-mod-outdated` [command line arguments](https://github.com/psampaz/go-mod-outdated#usage' default: -update -direct @@ -196,6 +216,11 @@ variables: GO_CI_LINT_DISABLED: $[[ inputs.ci-lint-disabled ]] GO_SBOM_DISABLED: $[[ inputs.sbom-disabled ]] GO_VULNCHECK_DISABLED: $[[ inputs.vulncheck-disabled ]] + GO_SEMGREP_IMAGE: $[[ inputs.semgrep-image ]] + GO_SEMGREP_DISABLED: $[[ inputs.semgrep-disabled ]] + GO_SEMGREP_ARGS: $[[ inputs.semgrep-args ]] + GO_SEMGREP_RULES: $[[ inputs.semgrep-rules ]] + GO_SEMGREP_DOWNLOAD_RULES_ENABLED: $[[ inputs.semgrep-download-rules-enabled ]] # Image of cyclonedx-gomod used for SBOM analysis GO_SBOM_IMAGE: $[[ inputs.sbom-image ]] @@ -534,6 +559,31 @@ stages: fi } + function setup_semgrep_rules() { + if [[ "${GO_SEMGREP_DOWNLOAD_RULES_ENABLED}" == "true" ]] + then + log_info "Download Semgrep rule files..." + for rule in $GO_SEMGREP_RULES + do + if [[ -r $rule ]] + then + log_info "... rule file $rule found: skip" + SEMGREP_RULES="${SEMGREP_RULES} $rule" + else + log_info "... rule file $rule not found : download (https://semgrep.dev/c/$rule)" + dest_file="semgrep-${rule/p\//}.yml" + wget "https://semgrep.dev/c/$rule" -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 $GO_SEMGREP_RULES + export SEMGREP_RULES="${GO_SEMGREP_RULES}" + fi + } + unscope_variables eval_all_secrets @@ -675,6 +725,38 @@ go-ci-lint: when: never - !reference [.test-policy, rules] +# SAST: semgrep +go-semgrep: + extends: .go-base + image: $GO_SEMGREP_IMAGE + # unset cache from parent job + cache : {} + dependencies: [] + stage: test + before_script: + - *go-scripts + - cd $GO_PROJECT_DIR + - mkdir -p -m 777 reports + - setup_semgrep_rules + script: + - >- + semgrep ci ${TRACE+--verbose} ${GO_SEMGREP_ARGS} + --gitlab-sast-output=reports/golang-semgrep.gitlab.json + ${DEFECTDOJO_SEMGREP_REPORTS:+--json-output=reports/golang-semgrep.native.json} + artifacts: + name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $ĈI_COMMIT_REF_SLUG" + when: "always" + expire_in: 1 week + reports: + sast: $GO_PROJECT_DIR/reports/golang-semgrep.gitlab.json + paths: + - $GO_PROJECT_DIR/reports/golang-semgrep.* + rules: + # exclude if disable + - if: '$GO_SEMGREP_DISABLED == "true"' + when: never + - !reference [.test-policy, rules] + go-mod-outdated: extends: .go-base stage: test