From 91a2547d15db5abc45501734cfad7b70660d9380 Mon Sep 17 00:00:00 2001 From: Anais Urlichs <33576047+AnaisUrlichs@users.noreply.github.com> Date: Mon, 22 Jan 2024 07:44:16 +0000 Subject: [PATCH] docs: update cosign tutorial and commands, update kyverno policy (#5929) Signed-off-by: AnaisUrlichs Co-authored-by: saso --- docs/docs/supply-chain/attestation/vuln.md | 7 +- docs/tutorials/kubernetes/kyverno.md | 63 ++++------ docs/tutorials/signing/vuln-attestation.md | 135 +++++++++++++++++++-- 3 files changed, 150 insertions(+), 55 deletions(-) diff --git a/docs/docs/supply-chain/attestation/vuln.md b/docs/docs/supply-chain/attestation/vuln.md index c17164f0f30b..b1484387266a 100644 --- a/docs/docs/supply-chain/attestation/vuln.md +++ b/docs/docs/supply-chain/attestation/vuln.md @@ -179,13 +179,14 @@ You can use Cosign to sign without keys by authenticating with an OpenID Connect ``` $ trivy image --format cosign-vuln -o vuln.json -$ COSIGN_EXPERIMENTAL=1 cosign attest --type vuln --predicate vuln.json +$ cosign attest --type vuln --predicate vuln.json ``` +This will provide a certificate in the output section. -You can verify attestations. +You can verify attestations: ``` -$ COSIGN_EXPERIMENTAL=1 cosign verify-attestation --type vuln +$ cosign verify-attestation --certificate=path-to-the-certificate --type vuln --certificate-identity Email-used-to-sign --certificate-oidc-issuer='the-issuer-used' ``` [vuln-attest-spec]: https://github.com/sigstore/cosign/blob/95b74db89941e8ec85e768f639efd4d948db06cd/specs/COSIGN_VULN_ATTESTATION_SPEC.md \ No newline at end of file diff --git a/docs/tutorials/kubernetes/kyverno.md b/docs/tutorials/kubernetes/kyverno.md index 4dc9633212a2..f2e9d12006a7 100644 --- a/docs/tutorials/kubernetes/kyverno.md +++ b/docs/tutorials/kubernetes/kyverno.md @@ -7,8 +7,9 @@ This tutorial details - Verify the container image has an attestation with Kyverno ### Prerequisites -1. [Attestation of the vulnerability scan uploaded][vuln-attestation] -2. A running Kubernetes cluster that kubectl is connected to +1. A running Kubernetes cluster that kubectl is connected to +2. A Container image signed with Cosign and an attestation generated for a Trivy Vulnerability scan. + [Follow this tutorial for more information.][vuln-attestation] ### Kyverno Policy to check attestation @@ -24,11 +25,12 @@ kind: ClusterPolicy metadata: name: check-vulnerabilities spec: - validationFailureAction: enforce - webhookTimeoutSeconds: 10 + validationFailureAction: Enforce + background: false + webhookTimeoutSeconds: 30 failurePolicy: Fail rules: - - name: not-older-than-one-week + - name: checking-vulnerability-scan-not-older-than-one-hour match: any: - resources: @@ -36,14 +38,23 @@ spec: - Pod verifyImages: - imageReferences: - - "CONTAINER-REGISTRY/*:*" + - "*" attestations: - - predicateType: cosign.sigstore.dev/attestation/vuln/v1 + - type: https://cosign.sigstore.dev/attestation/vuln/v1 conditions: - all: - - key: "{{ time_since('','{{metadata.scanFinishedOn}}','') }}" + - key: "{{ time_since('','{{ metadata.scanFinishedOn }}', '') }}" operator: LessThanOrEquals - value: "168h" + value: "1h" + attestors: + - count: 1 + entries: + - keys: + publicKeys: |- + -----BEGIN PUBLIC KEY----- + abc + xyz + -----END PUBLIC KEY----- ``` {% endraw %} @@ -57,38 +68,12 @@ Next, apply the above policy: kubectl apply -f vuln-attestation.yaml ``` -To ensure that the policy worked, we can deploye an example deployment file with our container image: +To ensure that the policy worked, we can deploy an example Kubernetes Pod with our container image: -deployment.yaml ``` -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cns-website - namespace: app -spec: - replicas: 2 - selector: - matchLabels: - run: cns-website - template: - metadata: - labels: - run: cns-website - spec: - containers: - - name: cns-website - image: docker.io/anaisurlichs/cns-website:0.0.6 - ports: - - containerPort: 80 - imagePullPolicy: Always - resources: - limits: - memory: 512Mi - cpu: 200m - securityContext: - allowPrivilegeEscalation: false +kubectl run app-signed --image= docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd  ``` +Note that the image is based on the [signing tutorial.][vuln-attestation] Once we apply the deployment, it should pass since our attestation is available: ``` @@ -98,7 +83,7 @@ deployment.apps/cns-website created However, if we try to deploy any other container image, our deployment will fail. We can verify this by replacing the image referenced in the deployment with `docker.io/anaisurlichs/cns-website:0.0.5` and applying the deployment: ``` -kubectl apply -f deployment-two.yaml +kubectl run app-unsigned --image=docker.io/anaisurlichs/cns-website:0.1.1  Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment" Name: "cns-website", Namespace: "app" diff --git a/docs/tutorials/signing/vuln-attestation.md b/docs/tutorials/signing/vuln-attestation.md index f0721c9d3223..2e4b487306c6 100644 --- a/docs/tutorials/signing/vuln-attestation.md +++ b/docs/tutorials/signing/vuln-attestation.md @@ -1,36 +1,145 @@ # Vulnerability Scan Record Attestation -This tutorial details +This tutorial details how to -- Scan your container image for vulnerabilities -- Generate an attestation with Cosign +- Scan container images for vulnerabilities +- Generate an attestation, using Cosign, with and without generating a separate key pair #### Prerequisites -1. Trivy CLI installed -2. Cosign installed +1. [Trivy CLI](../../getting-started/installation.md) installed +2. [Cosign CLI](https://docs.sigstore.dev/system_config/installation/) installed +3. Ensure that you have access to a container image in a remote container registry that you own/within your account. In this tutorial, we will use DockerHub. -#### Scan Container Image for vulnerabilities +## Scan Container Image for vulnerabilities Scan your container image for vulnerabilities and save the scan result to a scan.json file: ``` -trivy image --ignore-unfixed --format json --output scan.json anaisurlichs/cns-website:0.0.6 +trivy image --ignore-unfixed --format cosign-vuln --output scan.json DockerHubID/imagename:imagetag ``` -* --ignore-unfixed: Ensures that only the vulnerabilities are displayed that have a already a fix available -* --output scan.json: The scan output is saved to a scan.json file instead of being displayed in the terminal. +For example: +``` +trivy image --ignore-unfixed --format cosign-vuln --output scan.json anaisurlichs/signed-example:0.1 +``` -Note: Replace the container image with the container image that you would like to scan. +* `--ignore-unfixed`: Ensures only the vulnerabilities, which have a already a fix available, are displayed +* `--output scan.json`: The scan output is saved to a scan.json file instead of being displayed in the terminal. + +Note: Replace the container image with the container image that you want to scan. + +## Option 1: Signing and Generating an attestation without new key pair + +#### Signing + +Sign the container image: +``` +cosign sign DockerHubID/imagename@imageSHA +``` + +The `imageSHA` can be obtained through the following docker command: +``` +docker image ls --digests +``` +The SHA will be displayed next to the image name and tag. + +Note that it is better practice to sign the image SHA rather than the tag as the SHA will remain the same for the particular image that we have signed. + +For example: +``` +cosign sign docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd +``` -#### Attestation of the vulnerability scan with Cosign +#### Attestation -The following command generates an attestation for the vulnerability scan and uploads it to our container image: +The following command generates an attestation for the vulnerability scan and uploads it to the container image used: ``` -cosign attest --replace --predicate scan.json --type vuln anaisurlichs/cns-website:0.0.6 +cosign attest --predicate scan.json --type vuln docker.io/DockerHubID/imagename:imageSHA +``` + +For example: +``` +cosign attest --predicate scan.json --type vuln docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd ``` Note: Replace the container image with the container image that you would like to scan. +Next, Sigstore will ask you to verify with an account -- Microsoft, GitHub, or Google. + +Once done, the user will be provided with a certificate in the terminal where they ran the command. Example certificate: +``` +-----BEGIN CERTIFICATE----- +MIIC1TCCAlygAwIBAgIUfSXI7xTWSLq4nuygd8YPuhPZlEswCgYIKoZIzj0EAwMw +NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl +cm1lZGlhdGUwHhcNMjQwMTExMTMzODUzWhcNMjQwMTExMTM0ODUzWjAAMFkwEwYH +KoZIzj0CAQYIKoZIzj0DAQcDQgAETcUNnK76mfo9G3j1c7NN6Vcn6yQPDX5rd3QB +unkHs1Uk59CWv3qm6sUyRNYaATs9zdHAZqLck8G4P/Pj7+GzCKOCAXswggF3MA4G +........ +-----END CERTIFICATE----- +``` + + +## Option 2: Signing and Generating an attestation with a new Cosign key pair + +To generate an attestation for the container image with a separate key pair, we can use Cosign to generate a new key pair: +``` +cosign generate-key-pair  +``` + +This will generate a `cosign.key` and a `cosign.pub` file. The `cosign.key` file is your private key that should be kept confidential as it is used to sign artefacts. However, the `cosign.pub` file contains the information of the corresponding public key. This key can be used by third parties to verify the attestation -- basically that this person who claims to have signed the attestation actually is the one who signed it. + +#### Signing + +Sign the container image: +``` +cosign sign --key cosign.key docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd +``` + +#### Attestation + +To generate the attestation with the specific key pairs, run the following command: +``` +cosign attest --key cosign.key --type vuln --predicate scan.json docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd  +``` + +## Verify the attestation + +### Option 1 -- No separate key pair + +If you have not generated a key pair but received a certificate after the container image was signed, use the following command to verify the attestation: + +``` +cosign verify-attestation --type vuln --certificate-identity Email-used-to-sign --certificate-oidc-issuer='the-issuer-used' docker.io/DockerHubID/imagename:imageSHA +``` + +For example, the command could be like this: +``` +cosign verify-attestation --type vuln --certificate-identity urlichsanais@gmail.com --certificate-oidc-issuer='https://github.com/login/oauth' anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd +``` + +### Option 2 -- Separate key pair + +If you have used a new cosign key pair, the attestation can be verified through the following command: +``` +cosign verify-attestation --key cosign.pub --type vuln anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd  +``` + +
+Output + +The output should look similar to the following: +``` +Verification for anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd -- +The following checks were performed on each of these signatures: + - The cosign claims were validated + - Existence of the claims in the transparency log was verified offline + - The signatures were verified against the specified public key +{"payloadType":"application/vnd.in-toto+json","payload": +``` +
+ +## More information + See [here][vuln-attestation] for more details. [vuln-attestation]: ../../docs/supply-chain/attestation/vuln.md \ No newline at end of file