From 01d5225a3a342aa29ed397e0540a7b20597ee612 Mon Sep 17 00:00:00 2001 From: Jan Fuhrer Date: Fri, 26 Apr 2024 22:05:47 +0200 Subject: [PATCH 1/4] feat: add .allstar config files --- .allstar/binary_artifacts.yaml | 3 +++ .allstar/branch_protection.yaml | 8 ++++++++ .allstar/dangerous_workflow.yaml | 3 +++ .allstar/outside.yaml | 5 +++++ .allstar/scorecard.yaml | 17 +++++++++++++++++ .allstar/security.yaml | 3 +++ 6 files changed, 39 insertions(+) create mode 100644 .allstar/binary_artifacts.yaml create mode 100644 .allstar/branch_protection.yaml create mode 100644 .allstar/dangerous_workflow.yaml create mode 100644 .allstar/outside.yaml create mode 100644 .allstar/scorecard.yaml create mode 100644 .allstar/security.yaml diff --git a/.allstar/binary_artifacts.yaml b/.allstar/binary_artifacts.yaml new file mode 100644 index 0000000..3856fb0 --- /dev/null +++ b/.allstar/binary_artifacts.yaml @@ -0,0 +1,3 @@ +optConfig: + OptIn: true +action: issue diff --git a/.allstar/branch_protection.yaml b/.allstar/branch_protection.yaml new file mode 100644 index 0000000..03609d6 --- /dev/null +++ b/.allstar/branch_protection.yaml @@ -0,0 +1,8 @@ +optConfig: + OptIn: true +action: issue +enforceDefault: true +requireApproval: false +blockForce: true +requireSignedCommits: true +enforceOnAdmins: true diff --git a/.allstar/dangerous_workflow.yaml b/.allstar/dangerous_workflow.yaml new file mode 100644 index 0000000..3856fb0 --- /dev/null +++ b/.allstar/dangerous_workflow.yaml @@ -0,0 +1,3 @@ +optConfig: + OptIn: true +action: issue diff --git a/.allstar/outside.yaml b/.allstar/outside.yaml new file mode 100644 index 0000000..4d8a9e7 --- /dev/null +++ b/.allstar/outside.yaml @@ -0,0 +1,5 @@ +optConfig: + OptIn: true +action: issue +pushAllowed: true +adminAllowed: false diff --git a/.allstar/scorecard.yaml b/.allstar/scorecard.yaml new file mode 100644 index 0000000..805acab --- /dev/null +++ b/.allstar/scorecard.yaml @@ -0,0 +1,17 @@ +optConfig: + OptIn: true +action: issue +checks: +- Binary-Artifacts +- CI-Tests +- Dangerous-Workflow +- Dependency-Update-Tool +- License +- Packaging +- Pinned-Dependencies +- Signed-Releases +- SAST +- Security-Policy +- Token-Permissions +- Webhooks +threshold: 8 diff --git a/.allstar/security.yaml b/.allstar/security.yaml new file mode 100644 index 0000000..3856fb0 --- /dev/null +++ b/.allstar/security.yaml @@ -0,0 +1,3 @@ +optConfig: + OptIn: true +action: issue From 9be1f6bf0d072fc2412780d619e3fe01648aade2 Mon Sep 17 00:00:00 2001 From: Jan Fuhrer Date: Fri, 26 Apr 2024 22:06:13 +0200 Subject: [PATCH 2/4] feat: add SECURITY-INSIGHTS.yml --- SECURITY-INSIGHTS.yml | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 SECURITY-INSIGHTS.yml diff --git a/SECURITY-INSIGHTS.yml b/SECURITY-INSIGHTS.yml new file mode 100644 index 0000000..2d52d5c --- /dev/null +++ b/SECURITY-INSIGHTS.yml @@ -0,0 +1,54 @@ +header: + schema-version: 1.0.0 + expiration-date: '2025-04-25T10:00:00.000Z' + last-updated: '2024-04-26' + last-reviewed: '2024-04-26' + project-url: https://github.com/janfuhrer/podsalsa + changelog: https://github.com/janfuhrer/podsalsa/blob/main/CHANGELOG.md + license: https://github.com/janfuhrer/podsalsa/blob/main/LICENSE +project-lifecycle: + bug-fixes-only: false + core-team: + - name: Jan Fuhrer + contact: janfuhrer@mailbox.org + status: concept +contribution-policy: + accepts-pull-requests: true + accepts-automated-pull-requests: true + contributing-policy: https://github.com/janfuhrer/podsalsa/blob/main/CONTRIBUTING.md + code-of-conduct: https://github.com/janfuhrer/podsalsa/blob/main/CODE_OF_CONDUCT.md +distribution-points: + - https://github.com/janfuhrer/podsalsa/releases + - https://github.com/janfuhrer?tab=packages&repo_name=podsalsa +security-testing: +- tool-type: sca + tool-name: Dependabot + tool-version: latest + integration: + ad-hoc: false + ci: true + before-release: true + comment: | + Dependabot is enabled for this repo. +security-contacts: +- type: email + value: janfuhrer@mailbox.org + primary: true +vulnerability-reporting: + accepts-vulnerability-reports: true + bug-bounty-available: false + email-contact: janfuhrer@mailbox.org + security-policy: https://github.com/janfuhrer/podsalsa/blob/main/SECURITY.md + comment: | + Report security vulnerabilities via GitHub Security Advisory in this repository. +dependencies: + third-party-packages: true + dependencies-lists: + - https://github.com/janfuhrer/podsalsa/blob/main/go.mod + sbom: + - sbom-file: https://github.com/janfuhrer/podsalsa/releases + sbom-format: CycloneDX + sbom-url: https://github.com/janfuhrer/podsalsa/blob/main/SECURITY.md#sbom + - sbom-file: https://github.com/janfuhrer/podsalsa/pkgs/container/podsalsa + sbom-format: CycloneDX + sbom-url: https://github.com/janfuhrer/podsalsa/blob/main/SECURITY.md#sbom From 6f0126b2bd1eb43740cf86624fe849679af0616b Mon Sep 17 00:00:00 2001 From: Jan Fuhrer Date: Fri, 26 Apr 2024 22:06:48 +0200 Subject: [PATCH 3/4] docs: improve security documentation --- .github/workflows/README.md | 2 +- README.md | 18 +++-- SECURITY.md | 119 ++++++++++++++++++++++++++++- docs/best-practices.md | 14 +++- docs/prerequisites_verification.md | 91 ++++++++++++++++++++++ 5 files changed, 233 insertions(+), 11 deletions(-) create mode 100644 docs/prerequisites_verification.md diff --git a/.github/workflows/README.md b/.github/workflows/README.md index af1c372..347b147 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -1,4 +1,4 @@ -# PodSalsa Github Workflows +# PodSalsa GitHub Workflows ## Overview diff --git a/README.md b/README.md index a8fc4e6..dbf190e 100644 --- a/README.md +++ b/README.md @@ -24,19 +24,23 @@ The goal of this project is to provide a simple example of a Go application on G - [x] OpenSSF best practices - [x] Resolve "Code Scanning" alerts (as far as possible) - [x] Document GitHub Actions Best Practices -- [ ] Implement the release workflow for sbom, docker images, code scanning, and signing +- [x] Implement the release workflow for sbom, docker images, code scanning, and signing - [x] Create the go binaries for multiple platforms - [x] Go lint and security scans - - [ ] Generates a Software Bill of Materials (SBOM) - - [ ] Create multi-arch docker images - - [ ] Signs the sbom, the binaries checksum and the container images with Cosign and GitHub OIDC - - [ ] Upload the sbom, binaires, checksums to GitHub Releases - - [ ] Pushes the container images to GitHub Container Registry and Harbor registry + - [x] Generates a Software Bill of Materials (SBOM) + - [x] Create multi-arch docker images + - [x] Signs the sbom, the binaries checksum and the container images with Cosign and GitHub OIDC + - [x] Upload the sbom, binaires, checksums to GitHub Releases + - [x] Pushes the container images to GitHub Container Registry and Harbor registry - [ ] Document Security Policy (Verifying the release artifacts) +- [ ] Document Release Workflow ## Documentation All the used workflows and security best practices are documented in the following files: -- [PodSalsa Github Workflows](./.github/workflows/README.md) +- [PodSalsa GitHub Workflows](./.github/workflows/README.md) +- [Verifying the release artifacts](./SECURITY.md#release-verification) - [GitHub Actions Best Practices](./docs/best-practices.md) + +More documentation will be added in the future. diff --git a/SECURITY.md b/SECURITY.md index 496a388..0a6ff90 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,6 +8,121 @@ To report a security issue, please use the GitHub Security Advisory ["Report a V The contributor will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. -## Release +## Release verification -TODO: Describe how to verify the release artifacts +The release workflow creates provenance for its builds using the [SLSA standard](https://slsa.dev), which conforms to the [Level 3 specification](https://slsa.dev/spec/v1.0/levels#build-l3). The provenance is stored in the `multiple.intoto.jsonl` file of each release and can be used to verify the integrity and authenticity of the release artifacts. + +All signatures are created by [Cosign](https://github.com/sigstore/cosign) using the [keyless signing](https://docs.sigstore.dev/verifying/verify/#keyless-verification-using-openid-connect) method. + +### Prerequisites + +To verify the release artifacts, you will need the [slsa-verifier](https://github.com/slsa-framework/slsa-verifier), [cosign](https://github.com/sigstore/cosign) and [crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md) binaries. See the [prerequisites verification](docs/prerequisites_verification.md) for installation instructions. + +### Inspect Provenance + +You can manually inspect the provenance of the release artifacts by decoding the `multiple.intoto.jsonl` file. + +```bash +# get the latest release +export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name') + +# download the provenance file +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/multiple.intoto.jsonl + +# decode the payload +cat multiple.intoto.jsonl | jq -r '.payload' | base64 -d | jq +``` + +### Verify Provenance of Release Artifacts + +To verify the release artifacts (go binaries and sbom files), you can use the `slsa-verifier`. This verification works for all release artifcats (`*.tar.gz`, `*.zip`, `*.sbom`). + +```bash +# example for the "podsalsa-darwin-amd64.tar.gz" artifact +export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name') +export ARTIFACT=podsalsa-darwin-amd64.tar.gz + +# download the artifact +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/$ARTIFACT + +# download the provenance file +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/multiple.intoto.jsonl + +# verify the artifact +slsa-verifier verify-artifact \ + --provenance-path multiple.intoto.jsonl \ + --source-uri github.com/janfuhrer/podsalsa \ + --source-tag $VERSION \ + $ARTIFACT + +Verifying artifact podsalsa-darwin-amd64.tar.gz: PASSED +PASSED: Verified SLSA provenance +``` + +### Verify Provenance of Container Images + +The `slsa-verifier` can also verify docker images. Verification can be done by tag or by digest. We recommend to always use the digest to prevent [TOCTOU attacks](https://github.com/slsa-framework/slsa-verifier?tab=readme-ov-file#toctou-attacks), as an image tag is not immutable. + +```bash +export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name') +IMAGE=ghcr.io/janfuhrer/podsalsa:$VERSION + +# get the image digest and append it to the image name +# e.g. ghcr.io/janfuhrer/podsalsa:v0.2.0@sha256:... +IMAGE="${IMAGE}@"$(crane digest "${IMAGE}") + +# verify the image +slsa-verifier verify-image "$IMAGE" \ + --source-uri github.com/janfuhrer/podsalsa \ + --source-versioned-tag $VERSION + +PASSED: Verified SLSA provenance +``` + +As an alternative to the SLSA Verifier, you can use `cosign` to verify the docker images. Cosign also supports validating the attestation against `CUE` policies (see [Validate In-Toto Attestation](https://docs.sigstore.dev/verifying/attestation/#validate-in-toto-attestations) for more information), which is useful to ensure that some specific requirements are met. We provide a [policy.cue](./policy.cue) file to verify the correct workflow has triggered the release and that the image was generated from the correct source repository. + +```bash +# download policy.cue +curl -L -O https://raw.githubusercontent.com/janfuhrer/podsalsa/main/policy.cue + +# verify the image with cosign +cosign verify-attestation \ + --type slsaprovenance \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + --certificate-identity-regexp '^https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+$' \ + --policy policy.cue \ + $IMAGE | jq +``` + +### Verify Signature of Checksum file + +Since all release artifacts can be verified with the `slsa-verifier`, a checksum file is not necessary (the integrity is already verified by the SLSA Verifier). A use case might be to verify the integrity of downloaded files and only rely on Cosign instead of the SLSA Verifier. + +The checksum file can be verified with `cosign` as follows: + +```bash +export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name') + +# download the checksum, signature and certificate files +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt.sig +curl -L -O https://github.com/janfuhrer/podsalsa/releases/download/$VERSION/checksums.txt.pem + +# verify the checksum file +cosign verify-blob \ + --certificate checksums.txt.pem \ + --signature checksums.txt.sig \ + --certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+$' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + checksums.txt +``` + +### SBOM + +The Software Bill of Materials (SBOM) is generated for each release and can be used to verify the dependencies of the project. + +The SBOM of the Go binaries is available in the `*.sbom` files of the release and can be verified with the `slsa-verifier` (see [Verify Provenance of Release Artifacts](#verify-provenance-of-release-artifacts)). + + + +TODO: add SBOM verification for container images diff --git a/docs/best-practices.md b/docs/best-practices.md index 6fc2e19..01ec95d 100644 --- a/docs/best-practices.md +++ b/docs/best-practices.md @@ -100,7 +100,7 @@ Private vulnerability reporting can be enabled in the repository settings. (see ### Prevent script injection -A GitHub Actions workflow can be triggered by specific events such as push, pull request, new release, and so on. Each workflow trigger provides a [Github context](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context) which contains information about the event. This can be the branch name, username, user email, pull request title and body, etc. All this input should be treated as potentially untrusted data, and make sure it doesn't flow into shell or API calls where it can be interpreted as code. +A GitHub Actions workflow can be triggered by specific events such as push, pull request, new release, and so on. Each workflow trigger provides a [GitHub context](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context) which contains information about the event. This can be the branch name, username, user email, pull request title and body, etc. All this input should be treated as potentially untrusted data, and make sure it doesn't flow into shell or API calls where it can be interpreted as code. #### Example of a script injection attack with inline script @@ -233,6 +233,18 @@ After activating the scorecard workflow, the results are uploaded to the reposit The [Open Source Security Foundation (OpenSSF)](https://openssf.org/) provides a badge that indicates a project's security best practices score. The badge is generated based on the [OpenSSF Best Practices](https://www.bestpractices.dev/en/criteria/0) criteria. To get the badge, you need to register at the [OpenSSF Best Practices](https://www.bestpractices.dev/en) website and submit your repository. You will then need to answer a questionnaire about the project's security practices. The badge is generated based on the answers and is available once you have started answering the questionnaire. The badge can then be added to the repository's README file. +## OpenSSF Security Insights Specification + +In order to report information about the security status of a project in a machine-processable way, OpenSSF has created the [Security Insights Specification](https://github.com/ossf/security-insights-spec/blob/main/specification.md). The specification defines a format for the `SECURITY-INSIGHTS.yml` file, which can be used to report project status (e.g. whether the project is actively maintained or not), contribution policies, security artifacts (e.g. threat model, self-assessment) and other security-related information. + +ℹ️ The security insights file for this repository can be found in the file [SECURITY-INSIGHTS.yml](../SECURITY-INSIGHTS.yml). + +## OpenSSF Allstar + +[Allstar](https://github.com/ossf/allstar) is an OpenSSF project that continuously monitors GitHub organisations or repositories for security best practices. It can create issues in the repositories or fix them automatically. This can be useful to ensure that all repositories in an organisation are following the same security practices. It makes more sense to use Allstar at the organisation level rather than for personal repositories, since most of the checks are already covered by the OpenSSF Scorecard workflow and the OpenSSF Best Practices badge. + +ℹ️ The Allstar configuration for this repository can be found in the [.allstar](../.allstar) directory. + ## Dependency graph By default, GitHub enables the dependency graph for public repositories. The dependency graph shows the *direct* and *transitive* dependencies of a repository, and is updated automatically. The graph is generated based on the package manifest files in the repository. It can be useful to see which packages are used in the repository, and which repositories depend on the repository. The dependency graph can be found in the `Insights` tab of the repository. diff --git a/docs/prerequisites_verification.md b/docs/prerequisites_verification.md new file mode 100644 index 0000000..5c2b3ad --- /dev/null +++ b/docs/prerequisites_verification.md @@ -0,0 +1,91 @@ +# Prerequisites verification + +## SLSA-Verifier + +To verify the SLSA provenance, you need the [slsa-verifier](https://github.com/slsa-framework/slsa-verifier) binary. You can install it via Homebrew or download it from GitHub. + +Download with Hombrew: + +```bash +brew install slsa-verifier +``` + +Download binary from GitHub and verify checksum: + +```bash +# get the latest release +export VERSION=$(curl -s "https://api.github.com/repos/slsa-framework/slsa-verifier/releases/latest" | jq -r '.tag_name') +export ARCH=darwin-arm64 # linux-amd64 + +# download binary and shasum file +curl -L -O https://github.com/slsa-framework/slsa-verifier/releases/download/$VERSION/slsa-verifier-$ARCH +curl -L -O https://raw.githubusercontent.com/slsa-framework/slsa-verifier/main/SHA256SUM.md + +# simplify shasum file since it has all hashes for all versions in it +sed -n "/### \[${VERSION}\]/,/^### /p" SHA256SUM.md | grep -vE '^###|^$' > sha256sum_filtered + +# shasum check on macOS +shasum -a 256 -c --ignore-missing --strict sha256sum_filtered + +# shasum check on linux +sha256sum -c --strict --ignore-missing sha256sum_filtered + +# make binary executable and move it to a location in your $PATH +chmod +x slsa-verifier-$ARCH +sudo mv slsa-verifier-$ARCH /usr/local/bin/slsa-verifier +``` + +## Cosign + +As an alternative to the SLSA-Verifier, you can use the [Cosign](https://github.com/sigstore/cosign) CLI to verify the docker images and the checksum file. + +Install Cosign via Homebrew or have a look at the [installation instructions](https://docs.sigstore.dev/system_config/installation/). + +```bash +brew install cosign +``` + +## Crane + +[Crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md) is a tool for interacting with remote images and registries. We use it to get the image digest for the verification. + +Download with Hombrew: + +```bash +brew install crane +``` + +Download binary from GitHub and verify SLSA provenance: + +```bash +# get the latest release +VERSION=$(curl -s "https://api.github.com/repos/google/go-containerregistry/releases/latest" | jq -r '.tag_name') +ARCH=Darwin_arm64 # Linux_amd64 + +# download binary package and provenance file +curl -sL "https://github.com/google/go-containerregistry/releases/download/$VERSION/go-containerregistry_$ARCH.tar.gz" > go-containerregistry.tar.gz +curl -sL https://github.com/google/go-containerregistry/releases/download/$VERSION/multiple.intoto.jsonl > provenance.intoto.jsonl + +# verify SLSA provenance +slsa-verifier verify-artifact \ + --provenance-path provenance.intoto.jsonl \ + --source-uri github.com/google/go-containerregistry \ + --source-tag $VERSION \ + go-containerregistry.tar.gz + +Verifying artifact go-containerregistry.tar.gz: PASSED +PASSED: Verified SLSA provenance + +# unpack crane in the $PATH +tar -zxvf go-containerregistry.tar.gz crane +chmod +x crane +sudo mv crane /usr/local/bin/crane +``` + +## jq + +[jq](https://github.com/jqlang/jq) is a lightweight and flexible command-line JSON processor. We use it to inspect the provenance files. You can install it via Homebrew or see the [installation instructions](https://jqlang.github.io/jq/download/). + +```bash +brew install jq +``` From c692bcacaa203137b5a8daa293d13b691d2758b3 Mon Sep 17 00:00:00 2001 From: Jan Fuhrer Date: Sat, 27 Apr 2024 10:12:21 +0200 Subject: [PATCH 4/4] docs: add container sbom verification --- README.md | 2 +- SECURITY.md | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dbf190e..3ab0be9 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The goal of this project is to provide a simple example of a Go application on G - [x] Signs the sbom, the binaries checksum and the container images with Cosign and GitHub OIDC - [x] Upload the sbom, binaires, checksums to GitHub Releases - [x] Pushes the container images to GitHub Container Registry and Harbor registry -- [ ] Document Security Policy (Verifying the release artifacts) +- [x] Document Security Policy (Verifying the release artifacts) - [ ] Document Release Workflow ## Documentation diff --git a/SECURITY.md b/SECURITY.md index 0a6ff90..31c7aeb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -123,6 +123,13 @@ The Software Bill of Materials (SBOM) is generated for each release and can be u The SBOM of the Go binaries is available in the `*.sbom` files of the release and can be verified with the `slsa-verifier` (see [Verify Provenance of Release Artifacts](#verify-provenance-of-release-artifacts)). +The SBOM of the container images can be downloaded with `cosign`. You have to specify the platform of the image to download the correct SBOM. +```bash +export VERSION=$(curl -s "https://api.github.com/repos/janfuhrer/podsalsa/releases/latest" | jq -r '.tag_name') +IMAGE=ghcr.io/janfuhrer/podsalsa:$VERSION + +cosign download sbom ghcr.io/janfuhrer/podsalsa:$IMAGE --platform linux/arm64 +``` -TODO: add SBOM verification for container images +The `cosign download sbom` command will be deprecated in the future. At the moment, I have not found another way to download the SBOM of the container images. There are open issues in the [cosign repository](https://github.com/sigstore/cosign/issues/2307) to provide a better way to download the SBOM.