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

Merge branch 'feature/security-scan' into 'main'

feat: integrate SAST security-code-scan

Closes #12

See merge request to-be-continuous/dotnet!17
parents ed2bcba4 7bac4fc7
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -311,6 +311,32 @@ The following reports are generated:
| `reports/dotnet-infersharp-*.gitlab-sast.json` | [Gitlab SAST](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/sast-report-format.json?ref_type=heads) report format| [GitLab integration](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportssast) |
| `reports/dotnet-infersharp-*.gitlab-codequality.json` | [Code Climate](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types) | [GitLab integration](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportscodequality) |

### `dotnet-security-scan` job

This job runs the static code analysis using [security-code-scan](https://security-code-scan.github.io/). On big projects this analysis can take quite some time. Use `security-scan-mode` to control the branches on which to run this automatically.

It uses the following variables:

| Input / Variable | Description | Default value |
| ---------------- | ----------- | ------------- |
| `security-scan-disabled` / `DOTNET_SECURITY_SCAN_DISABLED` | Set to true to disable [security-code-scan](https://security-code-scan.github.io/) analysis. | `false` |
| `security-scan-opts` / `DOTNET_SECURITY_SCAN_OPTS` | Additional [security-code-scan options](https://github.com/security-code-scan/security-code-scan) to pass to the analysis. | _none_ |


**Output artifacts:**

This job produces a SARIF report `dotnet-security-scan-<project>.security-scan.sarif` containing the findings. This SARIF is converted to GitLab SAST and Code Quality formats for reporting depending upon available subscription feature.

The following reports are generated:

| Report         | Format                                                                       | Usage             |
| -------------- | ---------------------------------------------------------------------------- | ----------------- |
| `reports/dotnet-security-scan-<project>.sarif.json` | [OASIS Open Static Analysis Results Interchange Format (SARIF)](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif) | Converted to Gitlab reports |
| `reports/dotnet-security-scan-*.gitlab-sast.json` | [Gitlab SAST](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/sast-report-format.json?ref_type=heads) report | [GitLab integration](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportssast) |
| `reports/dotnet-security-scan-*.gitlab-codequality.json` | [Code Climate](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types) | [GitLab integration](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportscodequality) |



### `dotnet-sbom` job

This job creates a Software Bill Of Materials (SBOM) for the project, libraries and executables using [CycloneDX cdxgen](https://github.com/CycloneDX/cdxgen).
+13 −0
Original line number Diff line number Diff line
@@ -185,6 +185,19 @@
        }
      ]
    },
    {
      "id": "security-code-scan",
      "name": "Security Code Scan",
      "description": "Run [Security Code Scan](https://security-code-scan.github.io/) analysis during build to identify security vulnerabilities in your code.",
      "disable_with": "DOTNET_SECURITY_SCAN_DISABLED",
      "variables":[
        {
          "name": "DOTNET_SECURITY_SCAN_OPTS",
          "description": "Additional [security-code-scan options](https://github.com/security-code-scan/security-code-scan) to pass to the analysis.",
          "advanced": true
        }
      ]
    },
    {
      "id": "publish",
      "name": "dotnet publish",
+58 −7
Original line number Diff line number Diff line
@@ -101,6 +101,13 @@ spec:
    infersharp-blocklist:
      description: Space-separated list of partial path patterns to filter findings from SARIF output (e.g., suppress test framework false positives).
      default: "Microsoft.TestPlatform xunit nunit MSTest testhost testlogger"
    security-scan-disabled:
      description: Set to true to disable [security-code-scan](https://security-code-scan.github.io/) analysis.
      type: boolean
      default: false
    security-scan-opts:
      description: Additional [security-code-scan options](https://github.com/security-code-scan/security-code-scan) to pass to the analysis.
      default: ""
    package-configuration:
      description: The build configuration to use for packaging (Debug or Release).
      default: Release
@@ -230,6 +237,10 @@ variables:
  DOTNET_INFERSHARP_OPTS: $[[ inputs.infersharp-opts ]]
  DOTNET_INFERSHARP_BLOCKLIST: $[[ inputs.infersharp-blocklist ]]

  # Security Code Scan
  DOTNET_SECURITY_SCAN_DISABLED: $[[ inputs.security-scan-disabled ]]
  DOTNET_SECURITY_SCAN_OPTS: $[[ inputs.security-scan-opts ]]
  
  # SBOM
  DOTNET_SBOM_DISABLED: $[[ inputs.sbom-disabled ]]
  DOTNET_SBOM_SUPPLIER: $[[ inputs.sbom-supplier ]]
@@ -752,7 +763,7 @@ stages:
    if [[ "$report_type" == "codequality" ]]; then
      report_name="gitlab-codequality"
    elif [[ "$report_type" == "sast" ]]; then
      report_name="sast"
      report_name="gitlab-sast"
    else
      fail "Unsupported SARIF report type: ${report_type}"
    fi
@@ -1626,6 +1637,18 @@ stages:
    log_info "Infersharp analysis: ${before_count} total findings, ${filtered_count} blocklisted, ${after_count} reported"
  }

  function _dotnet_convert_sarif_to_gitlab_reports() {
    local report_type="$1"
    local input_sarif="$2"
    _dotnet_convert_sarif_reports "${report_type}" "${input_sarif}"
    sed -i "s|${CI_PROJECT_DIR}/||g" "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/${CI_JOB_NAME}-${DOTNET_PROJECT_NAME}.gitlab-${report_type}.json"
    if ! echo "$GITLAB_FEATURES" | grep -qE "sast_|security_advanced"; then
      log_warn "GitLab security dashboard feature is not enabled. Reporting to codequality."
      _dotnet_convert_sarif_reports codequality "${input_sarif}"
      sed -i "s|${CI_PROJECT_DIR}/||g" "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/${CI_JOB_NAME}-${DOTNET_PROJECT_NAME}.gitlab-codequality.json"
    fi
  }

  function dotnet_run_infersharp() {
    log_info "Running Infer# static analysis on project: ${DOTNET_PROJECT_DIR}"
    mkdir -p "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports"
@@ -1647,12 +1670,19 @@ stages:
    
    # Convert filtered SARIF to GitLab formats
    log_info "Converting filtered Infer# SARIF report to GitLab SAST and Code Quality formats"
    _dotnet_convert_sarif_reports sast "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-infersharp-${DOTNET_PROJECT_NAME}.sarif.json"
    _dotnet_convert_sarif_to_gitlab_reports sast "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-infersharp-${DOTNET_PROJECT_NAME}.sarif.json"
  }

    if ! echo "$GITLAB_FEATURES" | grep -qE "sast_|security_advanced"; then
      log_warn "GitLab security dashboard feature is not enabled. Reporting to codequality."
      _dotnet_convert_sarif_reports codequality "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-infersharp-${DOTNET_PROJECT_NAME}.sarif.json"
    fi
  function dotnet_run_security_code_scan {
    log_info "Running security-code-scan on project: ${DOTNET_PROJECT_DIR}/${DOTNET_PROJECT_SOLUTION:-${DOTNET_BUILD_FILE}}"
    _dotnet_run_restore
    mkdir -p "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports"
    dotnet_tool_install security-scan
    log_info "dotnet security-scan  ${DOTNET_PROJECT_DIR}/${DOTNET_PROJECT_SOLUTION:-${DOTNET_BUILD_FILE}} ${DOTNET_SECURITY_SCAN_OPTS} --cwe -x ${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-${DOTNET_PROJECT_NAME}.sarif.json"
    # shellcheck disable=SC2086
    dotnet security-scan "${DOTNET_PROJECT_DIR}/${DOTNET_PROJECT_SOLUTION:-${DOTNET_BUILD_FILE}}" ${DOTNET_SECURITY_SCAN_OPTS} --cwe -x "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-${DOTNET_PROJECT_NAME}.sarif.json"

    _dotnet_convert_sarif_to_gitlab_reports sast "${CI_PROJECT_DIR}/${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-${DOTNET_PROJECT_NAME}.sarif.json"
  }

  function _dotnet_install_glab() {
@@ -2071,6 +2101,27 @@ dotnet-infersharp:
      when: never
    - !reference [.test-policy, rules]

dotnet-security-scan:
  extends: .dotnet-env-base
  image: mcr.microsoft.com/dotnet/sdk:10.0
  stage: test
  variables:
    DOTNET_REQUIRES_SDK_INSTALL: "false"
  script:
    - dotnet_run_security_code_scan
  artifacts:
    reports:
      sast: '${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-*.gitlab-sast.json'
      codequality: '${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-*.gitlab-codequality.json'
    expire_in: 1 week
    when: always
    paths:
      - '${DOTNET_PROJECT_DIR}/reports/dotnet-security-scan-*'
  rules:
    - if: '$DOTNET_SECURITY_SCAN_DISABLED == "true"'
      when: never
    - !reference [.test-policy, rules]

dotnet-publish:
  extends: .dotnet-env-base
  stage: publish