From 4c56888e589c11ac60edf79f2aa9dcd23bda9062 Mon Sep 17 00:00:00 2001 From: Clement Bois <clement.bois@orange.com> Date: Tue, 13 Dec 2022 10:40:14 +0000 Subject: [PATCH] feat: add a job generating software bill of materials --- README.md | 18 +++++++++++++ kicker.json | 19 ++++++++++++++ templates/gitlab-ci-python.yml | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/README.md b/README.md index 92d94c9..9fd089a 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,24 @@ In addition to a textual report in the console, this job produces the following | -------------- | ---------------------------------------------------------------------------- | ----------------- | | `$PYTHON_PROJECT_DIR/reports/py-trivy.trivy.json` | [JSON](https://aquasecurity.github.io/trivy/latest/docs/vulnerability/examples/report/#json) | [DefectDojo integration](https://defectdojo.github.io/django-DefectDojo/integrations/parsers/#trivy)<br/>_This report is generated only if DefectDojo template is detected_ | +### `py-sbom` job + +This job generates a [SBOM](https://cyclonedx.org/) file listing all dependencies using [syft](https://github.com/anchore/syft). + +It is bound to the `test` stage, and uses the following variables: + +| Name | description | default value | +| --------------------- | -------------------------------------- | ----------------- | +| `PYTHON_SBOM_DISABLED` | Set to `true` to disable this job | _none_ | +| `PYTHON_SBOM_SYFT_URL` | Url to the `tar.gz` package for `linux_amd64` of Syft to use (ex: `https://github.com/anchore/syft/releases/download/v0.62.3/syft_0.62.3_linux_amd64.tar.gz`)<br/>_When unset, the latest version will be used_ | _none_ | +| `PYTHON_SBOM_OPTS` | Options for syft used for SBOM analysis | `--catalogers python-index-cataloger` | + +In addition to logs in the console, this job produces the following reports, kept for one week: + +| Report | Format | Usage | +| -------------- | ---------------------------------------------------------------------------- | ----------------- | +| `$PYTHON_PROJECT_DIR/reports/py-sbom.cyclonedx.json` | [CycloneDX JSON](https://cyclonedx.org/docs/latest/json/) | [Security & Compliance integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscyclonedx) | + ### SonarQube analysis If you're using the SonarQube template to analyse your Python code, here is a sample `sonar-project.properties` file: diff --git a/kicker.json b/kicker.json index af096f6..9c36e8d 100644 --- a/kicker.json +++ b/kicker.json @@ -150,6 +150,25 @@ } ] }, + { + "id": "sbom", + "name": "Software Bill of Materials", + "description": "This job generates a file listing all dependencies using [syft](https://github.com/anchore/syft)", + "disable_with": "PYTHON_SBOM_DISABLED", + "variables": [ + { + "name": "PYTHON_SBOM_SYFT_URL", + "description": "Url to the `tar.gz` package for `linux_amd64` of Syft to use\n\n_When unset, the latest version will be used_", + "advanced": true + }, + { + "name": "PYTHON_SBOM_OPTS", + "description": "Options for syft used for SBOM analysis", + "default": "--catalogers python-index-cataloger", + "advanced": true + } + ] + }, { "id": "release", "name": "Release", diff --git a/templates/gitlab-ci-python.yml b/templates/gitlab-ci-python.yml index a10b0d9..87a295e 100644 --- a/templates/gitlab-ci-python.yml +++ b/templates/gitlab-ci-python.yml @@ -76,6 +76,8 @@ variables: PYTHON_TRIVY_IMAGE: aquasec/trivy:latest PYTHON_TRIVY_ARGS: "--vuln-type library" + PYTHON_SBOM_OPTS: "--catalogers python-index-cataloger" + PYTHON_RELEASE_NEXT: "minor" # By default, publish on the Packages registry of the project @@ -835,6 +837,50 @@ py-trivy: when: never - !reference [.test-policy, rules] +py-sbom: + extends: .python-base + stage: test + # force no dependency + dependencies: [] + needs: [] + script: + - mkdir -p -m 777 reports + - install_requirements + - | + case "$PYTHON_BUILD_SYSTEM" in + setuptools* | reqfile) + _pip freeze > "${PYTHON_REQS_FILE}" + ;; + esac + - | + if [[ -z "$PYTHON_SBOM_SYFT_URL" ]] + then + log_info "Syft version unset: retrieve latest version..." + PYTHON_SBOM_SYFT_URL=$(curl -sSf "https://api.github.com/repos/anchore/syft/releases?per_page=1" | \ + python3 -c 'import json,sys;resp=json.load(sys.stdin);print(next(filter(lambda a: a["browser_download_url"].endswith("_linux_amd64.tar.gz"),resp[0]["assets"]))["browser_download_url"]);') + log_info "... use latest Syft version: \\e[32m$PYTHON_SBOM_SYFT_URL\\e[0m" + fi + python_sbom_syft="$PIP_CACHE_DIR/syft-$(echo "$PYTHON_SBOM_SYFT_URL" | md5sum | cut -d" " -f1)" + if [ ! -f $python_sbom_syft ]; then + wget -q -O syft.tar.gz $PYTHON_SBOM_SYFT_URL + tar zxf syft.tar.gz syft + mkdir -p $PIP_CACHE_DIR + mv ./syft $python_sbom_syft + fi + - $python_sbom_syft dir:${PYTHON_PROJECT_DIR} $PYTHON_SBOM_OPTS -o cyclonedx-json > reports/py-sbom.cyclonedx.json + - chmod a+r reports/py-sbom.cyclonedx.json + artifacts: + name: "Python SBOM from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG" + expire_in: 1 week + when: always + paths: + - "$PYTHON_PROJECT_DIR/reports/py-sbom.cyclonedx.json" + rules: + # exclude if disabled + - if: '$PYTHON_SBOM_DISABLED == "true"' + when: never + - !reference [.test-policy, rules] + # (manual from master branch): triggers a release (tag creation) py-release: extends: .python-base -- GitLab