diff --git a/README.md b/README.md index 3f9bcb7..e0ace4d 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ --- -PodSalsa is a simple web application that only displays information about the release version of the application, the Git commit and the build date. -The goal of this project is to provide a simple example of a Go application on GitHub with GitHub Actions for building and releasing the application in a secure way. The focus is on providing a summary/documentation of GitHub Actions best practices, code scanning workflows, vulnerability scanning, and techniques for releasing secure software to improve the security of the software supply chain. +PodSalsa is a simple web application that only displays information about the release version of the application, the Git commit, and the build date. +The goal of this project is to provide a simple example of a Go application on GitHub with GitHub Actions for building and releasing the application in a secure way. The focus is on providing a summary/documentation of GitHub Actions best practices, code scanning workflows, vulnerability scanning, and techniques for releasing secure software to improve the security of the software supply chain. This project serves as a starting point for developers interested in supply chain security, artifact provenance, and verification. ## Release @@ -35,7 +35,7 @@ The release workflow creates provenance for its builds using the [SLSA standard] ## Documentation -> [!TIP] +> [!NOTE] > All the used workflows, security best practices and more related themes (e.g. component analysis, enforcement on Kubernetes) are documented in this repository. > Have a look at the [documentation](./docs/) for more information. diff --git a/SECURITY.md b/SECURITY.md index 6e99cfe..8f6b3ba 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,8 +12,7 @@ The contributor will send a response indicating the next steps in handling your 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. - +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. An overview how the keyless signing works can be found [here](./docs/slsa/sigstore/). ### 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/slsa/prerequisites-verification.md) for installation instructions. diff --git a/docs/assets/guac/guac-search-package.png b/docs/assets/guac/guac-search-package.png new file mode 100644 index 0000000..d95b002 Binary files /dev/null and b/docs/assets/guac/guac-search-package.png differ diff --git a/docs/assets/sbom-operator/sbom-operator.png b/docs/assets/sbom-operator/sbom-operator.png new file mode 100644 index 0000000..a382493 Binary files /dev/null and b/docs/assets/sbom-operator/sbom-operator.png differ diff --git a/docs/component-analysis/dependency-track/README.md b/docs/component-analysis/dependency-track/README.md index 32ece63..4afe998 100644 --- a/docs/component-analysis/dependency-track/README.md +++ b/docs/component-analysis/dependency-track/README.md @@ -22,7 +22,7 @@ Go to [http://localhost:8080](http://localhost:8080) and login with the default Create a new API key for the `Automation` team in the `Configuration/Access Management/Teams` section. You mus add the `PROJECT_CREATION_UPLOAD` permission to the team. Export the API key as an environment variable. -![Create API-Key](../assets/dependency-track/create-api-key.png) +![Create API-Key](../../assets/dependency-track/create-api-key.png) ```bash export API_TOKEN=xxx @@ -40,13 +40,13 @@ You can search for components in the "Component Search" section. You can search An example search for the PURL `pkg:golang/github.com/gorilla/mux@v1.8.1`: -![Component Search](../assets/dependency-track/component-search.png) +![Component Search](../../assets/dependency-track/component-search.png) ## Vulnerability Audit In the "Vulnerability Audit" section, you can see all vulnerabilities of the components in the projects. You can filter by severity, status, and more. -![Vulnerability Audit](../assets/dependency-track/vulnerability-audit.png) +![Vulnerability Audit](../../assets/dependency-track/vulnerability-audit.png) ## Policy Management @@ -54,7 +54,7 @@ In the "Policy Management" section, you can create and enforce security, operati For example you can create a policy that checks if the component has a vulnerability with a severity of `HIGH` and create notifications for it. There are several notification channels available like Slack, Email, Webhook, etc. -![Policy Management](../assets/dependency-track/policy-management.png) +![Policy Management](../../assets/dependency-track/policy-management.png) ## Further steps diff --git a/docs/component-analysis/dependency-track/manual-sbom-import.md b/docs/component-analysis/dependency-track/manual-sbom-import.md index ebf522f..a977b4f 100644 --- a/docs/component-analysis/dependency-track/manual-sbom-import.md +++ b/docs/component-analysis/dependency-track/manual-sbom-import.md @@ -49,14 +49,7 @@ COSIGN_REPOSITORY=ghcr.io/janfuhrer/sbom cosign verify-attestation \ --type cyclonedx \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ --certificate-identity-regexp '^https://github.com/janfuhrer/podsalsa/.github/workflows/release.yml@refs/tags/v[0-9]+.[0-9]+.[0-9]+(-rc.[0-9]+)?$' \ - $IMAGE | jq -r '.payload' | base64 -d | jq -r '.predicate' > podsalsa-$VERSION-dirty.sbom -``` - -There is a bug in the Dependency-Track API that does not allow to upload a SBOM which has not the specific format (`specVersion` must be after `bomFormat`). To fix this, we need to restructure the json of the container SBOM. - -```bash -jq '{ "$schema", "bomFormat", "specVersion", components, dependencies, metadata, serialNumber, version }' podsalsa-$VERSION-dirty.sbom > podsalsa-$VERSION.sbom -rm podsalsa-$VERSION-dirty.sbom + $IMAGE | jq -r '.payload' | base64 -d | jq -r '.predicate' > podsalsa-$VERSION.sbom ``` If we do this for multiple versions, we can upload them in a loop: @@ -89,7 +82,7 @@ Example output: The uploaded SBOMs are now accessible in the "Projects" section: -![Projects](../assets/dependency-track/project-view.png) +![Projects](../../assets/dependency-track/project-view.png) ## Import SBOMs via API (without provenance) @@ -136,10 +129,10 @@ for ARTIFACT in *.sbom; do \ ; done ``` -![Projects](../assets/dependency-track/project-view.png) +![Projects](../../assets/dependency-track/project-view.png) ## Import SBOMs manually You can also import the SBOMs manually via the frontend. Go to the "Projects" section and click on "Create Project". Fill in the project name and version and click on "Create". Then click on "Upload BOM" in the "Components" section and select the SBOM file. -![Upload via UI](../assets/dependency-track/upload-ui.png) +![Upload via UI](../../assets/dependency-track/upload-ui.png) diff --git a/docs/component-analysis/dependency-track/sbom-operator.md b/docs/component-analysis/dependency-track/sbom-operator.md index 4f95f72..17c5714 100644 --- a/docs/component-analysis/dependency-track/sbom-operator.md +++ b/docs/component-analysis/dependency-track/sbom-operator.md @@ -3,3 +3,7 @@ The [sbom-operator](https://github.com/ckotzbauer/sbom-operator) watches for new pods in the cluster and extracts the container image names. It then uses [Syft](https://github.com/anchore/syft) to create an SBOM for each container. All SBOMs are then uploaded to Dependency-Track and scanned for vulnerabilities. With this solution, it is possible to have an overview of all components used in a Kubernetes cluster and monitor them for vulnerabilities. The deployment of the sbom-operator is described in the [deployment](deployment/README.md) section. + +An overview of the components is shown in the following picture: + +![sbom-operator](../../assets/sbom-operator/sbom-operator.png) diff --git a/docs/component-analysis/guac/README.md b/docs/component-analysis/guac/README.md index 026a3fd..717beee 100644 --- a/docs/component-analysis/guac/README.md +++ b/docs/component-analysis/guac/README.md @@ -53,6 +53,8 @@ Inspect the imported SBOMs: guacone query known package "pkg:golang/github.com/janfuhrer/podsalsa@$VERSION" ``` +![guac-search-package](../../assets/guac/guac-search-package.png) + ## Mark a package as vulnerable Vulnerabilities are scanned against the [OSV](https://osv.dev/) database. To mark a package manually as vulnerable (e.g. in case of a zero day), use the following command: @@ -71,6 +73,6 @@ guacone query bad This returns a "Visualizer url" which can be opened in a browser to see the affected packages in the `guac-visualizer` running on `localhost:8080`. -![guac-visualizer](../assets/guac/guac-visualizer.png) +![guac-visualizer](../../assets/guac/guac-visualizer.png) More information can be found in the [GUAC Docs](https://docs.guac.sh/). diff --git a/docs/gh-actions/README.md b/docs/gh-actions/README.md index f74d7e7..0f6cbe2 100644 --- a/docs/gh-actions/README.md +++ b/docs/gh-actions/README.md @@ -191,7 +191,8 @@ Dependabot can be enabled in the repository settings under `Code security and an The scheduled updates can be configured in the `dependabot.yml` file. All configuration options can be found [here](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file). -ℹ️ See the [dependabot.yml](../../.github/dependabot.yml) in this repository for an example of how to configure Dependabot version updates for GitHub Actions, docker and gomod. +> [!NOTE] +> See the [dependabot.yml](../../.github/dependabot.yml) in this repository for an example of how to configure Dependabot version updates for GitHub Actions, docker and gomod. ### Using code scanning workflows @@ -211,7 +212,8 @@ If you choose `Advanced`, you can edit the workflow file and customize it to you After committing the workflow file, the code scanning will start automatically. You can see the results in the `Code scanning alerts` tab. -ℹ️ See the [CodeQL Workflow Example](../../.github/workflows/codeql.yml) in this repository. +> [!NOTE] +> See the [CodeQL Workflow Example](../../.github/workflows/codeql.yml) in this repository. ## OpenSSF Scorecards @@ -221,29 +223,33 @@ After activating the scorecard workflow, the results are uploaded to the reposit ![scorecard results](../assets/gh-actions/scorecard-results.png) -ℹ️ See the [OpenSSF Workflow Example](../../.github/workflows/scorecard.yml) in this repository. +> [!NOTE] +> See the [OpenSSF Workflow Example](../../.github/workflows/scorecard.yml) in this repository. ### Additional checks ## Workflow examples -ℹ️ Have a look at the [workflows](../../.github/workflows/) in this repository for general workflows to improve the security of your repository and specific go-related workflows. +> [!NOTE] +> Have a look at the [workflows](../../.github/workflows/) in this repository for general workflows to improve the security of your repository and specific go-related workflows. ## OpenSSF Best Practices Badge -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. +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 criterias](https://www.bestpractices.dev/en/criteria/0). To get the badge, you need to register at the [OpenSSF Best Practices website](https://www.bestpractices.dev/en) 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). +> [!NOTE] +> 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. +> [!NOTE] +> The Allstar configuration for this repository can be found in the [.allstar](../../.allstar) directory. ## Dependency graph diff --git a/docs/slsa/enforcement-kubernetes/README.md b/docs/slsa/enforcement-kubernetes/README.md index 80058b1..4c736f2 100644 --- a/docs/slsa/enforcement-kubernetes/README.md +++ b/docs/slsa/enforcement-kubernetes/README.md @@ -34,13 +34,13 @@ First, we deploy the [Kyverno policy](./kyverno/clusterpolicy-slsa.yaml) which e ```bash # install kyverno policies -kubectl apply -f kyverno/clusterpolicy-slsa.yaml +curl -sSL https://raw.githubusercontent.com/janfuhrer/podsalsa/main/docs/slsa/enforcement-kubernetes/kyverno/clusterpolicy-slsa.yaml | kubectl apply -f - ``` Next, we deploy the podsalsa application with a valid SLSA verification. ```bash -kubectl apply -f deployment.yaml +curl -sSL https://raw.githubusercontent.com/janfuhrer/podsalsa/main/docs/slsa/enforcement-kubernetes/deployment.yaml | kubectl apply -f - deployment.apps/podsalsa created ``` @@ -48,11 +48,11 @@ deployment.apps/podsalsa created Now, we deploy the podsalsa application with an invalid SLSA verification (version `v0.1.0` has no provenance). ```bash -kubectl apply -f deployment-fail.yaml +curl -sSL https://raw.githubusercontent.com/janfuhrer/podsalsa/main/docs/slsa/enforcement-kubernetes/deployment-fail.yaml | kubectl apply -f - -Error from server: error when creating "deployment-fail.yaml": admission webhook "mutate.kyverno.svc-fail" denied the request: +Error from server: error when creating "STDIN": admission webhook "mutate.kyverno.svc-fail" denied the request: -resource Deployment/default/podsalsa-fail was blocked due to the following policies +resource Deployment/default/podsalsa was blocked due to the following policies verify-slsa-provenance-keyless: autogen-check-slsa-keyless: 'image attestations verification failed, verifiedCount: diff --git a/docs/slsa/enforcement-kubernetes/deployment-fail.yaml b/docs/slsa/enforcement-kubernetes/deployment-fail.yaml index 763e584..9d9c08f 100644 --- a/docs/slsa/enforcement-kubernetes/deployment-fail.yaml +++ b/docs/slsa/enforcement-kubernetes/deployment-fail.yaml @@ -1,7 +1,7 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: podsalsa + name: podsalsa-fail spec: replicas: 1 selector: @@ -13,7 +13,7 @@ spec: app.kubernetes.io/name: podsalsa spec: containers: - - image: v0.1.0@sha256:91bda05305b8ba6ef6a2494d02e409a6968de008b09f77fb0c9c8dcc3f24054e + - image: ghcr.io/janfuhrer/podsalsa:v0.1.0@sha256:91bda05305b8ba6ef6a2494d02e409a6968de008b09f77fb0c9c8dcc3f24054e imagePullPolicy: Always name: podsalsa resources: diff --git a/docs/slsa/enforcement-kubernetes/deployment.yaml b/docs/slsa/enforcement-kubernetes/deployment.yaml index 8d02d93..128993f 100644 --- a/docs/slsa/enforcement-kubernetes/deployment.yaml +++ b/docs/slsa/enforcement-kubernetes/deployment.yaml @@ -13,7 +13,7 @@ spec: app.kubernetes.io/name: podsalsa spec: containers: - - image: v0.4.1@sha256:ff954525227a38ec863328f3d8c974cdcb3997ac038e29df3b0c4151d878a712 + - image: ghcr.io/janfuhrer/podsalsa:v0.4.1@sha256:ff954525227a38ec863328f3d8c974cdcb3997ac038e29df3b0c4151d878a712 imagePullPolicy: Always name: podsalsa resources: diff --git a/docs/slsa/sigstore/README.md b/docs/slsa/sigstore/README.md index bd5dfb7..aaad02f 100644 --- a/docs/slsa/sigstore/README.md +++ b/docs/slsa/sigstore/README.md @@ -4,12 +4,13 @@ The [Sigstore project](https://www.sigstore.dev/) was founded in 2021 to create The following are the major components of the Sigstore project: -- **Rekor**: An immutable, tamper-resistant ledger of metadata that acts as a transparency log for storing signatures. -- **Cosign**: A tool for signing and verifying artifacts and containers. -- **Sigstore**: A free-to-use certification authority for code signing certificates. +- **[Rekor](https://github.com/sigstore/rekor)**: An immutable, tamper-resistant ledger of metadata that acts as a transparency log for storing signatures. +- **[Cosign](https://github.com/sigstore/cosign)**: A tool for signing and verifying artifacts and containers. +- **[Fulcio](https://github.com/sigstore/fulcio)**: A free-to-use certification authority for code signing certificates. **Sigstore Trust Root** -Sigstore's trust model originates from the Trust Root and chains down to the short-lived certificates issued by Fulcio. The Trust Root was established during a public root key signing ceremony ([link](https://www.youtube.com/watch?v=GEuFsc8Zm9U) in 2021. + +Sigstore's trust model originates from the Trust Root and chains down to the short-lived certificates issued by Fulcio. The Trust Root was established during a public root key signing ceremony ([link](https://www.youtube.com/watch?v=GEuFsc8Zm9U)) in 2021. ## Signing @@ -34,7 +35,7 @@ To verify, a Sigstore client downloads the artifact and provenance (e.g., go bin ![Verification](../../assets/sigstore/verification.png) -The whole verification process is automated and can be done with the Sigstore Cosign or the slsa-verifier tool. +The whole verification process is automated and can be done with the Sigstore `cosign` or the `slsa-verifier` tool. ## Examples diff --git a/docs/slsa/sigstore/rekor.md b/docs/slsa/sigstore/rekor.md index b8f6d49..fc83513 100644 --- a/docs/slsa/sigstore/rekor.md +++ b/docs/slsa/sigstore/rekor.md @@ -4,7 +4,11 @@ It is possible to communicate with the Rekor transparency log using the `rekor-c ## Pre-requisites -- [rekor-cli](https://github.com/sigstore/rekor/releases) +You can download the `rekor-cli` from the [Rekor releases page](https://github.com/sigstore/rekor/releases) or use Homebrew: + +```bash +brew install rekor-cli +``` ## Usage @@ -32,5 +36,7 @@ rekor-cli get --format json --uuid ${UUID} | jq To retrieve the short-lived certificate from the Rekor log entry, you can use the following command: ```bash -rekor-cli get --format json --uuid ${UUID} | jq -r '.Body.DSSEObj.signatures[].verifier' | base64 -d | openssl x509 -text -noout +rekor-cli get --format json --uuid ${UUID} | \ + jq -r '.Body.DSSEObj.signatures[].verifier' | \ + base64 -d | openssl x509 -text -noout ```