mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 07:10:41 -08:00
docs: update cosign tutorial and commands, update kyverno policy (#5929)
Signed-off-by: AnaisUrlichs <urlichsanais@gmail.com> Co-authored-by: saso <sasoakira6114@gmail.com>
This commit is contained in:
@@ -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 <IMAGE>
|
$ trivy image --format cosign-vuln -o vuln.json <IMAGE>
|
||||||
$ COSIGN_EXPERIMENTAL=1 cosign attest --type vuln --predicate vuln.json <IMAGE>
|
$ cosign attest --type vuln --predicate vuln.json <IMAGE>
|
||||||
```
|
```
|
||||||
|
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 <IMAGE>
|
$ cosign verify-attestation --certificate=path-to-the-certificate --type vuln --certificate-identity Email-used-to-sign --certificate-oidc-issuer='the-issuer-used' <IMAGE>
|
||||||
```
|
```
|
||||||
|
|
||||||
[vuln-attest-spec]: https://github.com/sigstore/cosign/blob/95b74db89941e8ec85e768f639efd4d948db06cd/specs/COSIGN_VULN_ATTESTATION_SPEC.md
|
[vuln-attest-spec]: https://github.com/sigstore/cosign/blob/95b74db89941e8ec85e768f639efd4d948db06cd/specs/COSIGN_VULN_ATTESTATION_SPEC.md
|
||||||
@@ -7,8 +7,9 @@ This tutorial details
|
|||||||
- Verify the container image has an attestation with Kyverno
|
- Verify the container image has an attestation with Kyverno
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
1. [Attestation of the vulnerability scan uploaded][vuln-attestation]
|
1. A running Kubernetes cluster that kubectl is connected to
|
||||||
2. 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
|
### Kyverno Policy to check attestation
|
||||||
|
|
||||||
@@ -24,11 +25,12 @@ kind: ClusterPolicy
|
|||||||
metadata:
|
metadata:
|
||||||
name: check-vulnerabilities
|
name: check-vulnerabilities
|
||||||
spec:
|
spec:
|
||||||
validationFailureAction: enforce
|
validationFailureAction: Enforce
|
||||||
webhookTimeoutSeconds: 10
|
background: false
|
||||||
|
webhookTimeoutSeconds: 30
|
||||||
failurePolicy: Fail
|
failurePolicy: Fail
|
||||||
rules:
|
rules:
|
||||||
- name: not-older-than-one-week
|
- name: checking-vulnerability-scan-not-older-than-one-hour
|
||||||
match:
|
match:
|
||||||
any:
|
any:
|
||||||
- resources:
|
- resources:
|
||||||
@@ -36,14 +38,23 @@ spec:
|
|||||||
- Pod
|
- Pod
|
||||||
verifyImages:
|
verifyImages:
|
||||||
- imageReferences:
|
- imageReferences:
|
||||||
- "CONTAINER-REGISTRY/*:*"
|
- "*"
|
||||||
attestations:
|
attestations:
|
||||||
- predicateType: cosign.sigstore.dev/attestation/vuln/v1
|
- type: https://cosign.sigstore.dev/attestation/vuln/v1
|
||||||
conditions:
|
conditions:
|
||||||
- all:
|
- all:
|
||||||
- key: "{{ time_since('','{{metadata.scanFinishedOn}}','') }}"
|
- key: "{{ time_since('','{{ metadata.scanFinishedOn }}', '') }}"
|
||||||
operator: LessThanOrEquals
|
operator: LessThanOrEquals
|
||||||
value: "168h"
|
value: "1h"
|
||||||
|
attestors:
|
||||||
|
- count: 1
|
||||||
|
entries:
|
||||||
|
- keys:
|
||||||
|
publicKeys: |-
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
abc
|
||||||
|
xyz
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
```
|
```
|
||||||
|
|
||||||
{% endraw %}
|
{% endraw %}
|
||||||
@@ -57,38 +68,12 @@ Next, apply the above policy:
|
|||||||
kubectl apply -f vuln-attestation.yaml
|
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
|
kubectl run app-signed --image= docker.io/anaisurlichs/signed-example@sha256:c5911ac313e0be82a740bd726dc290e655800a9588424ba4e0558c705d1287fd
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
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:
|
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:
|
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"
|
Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment"
|
||||||
Name: "cns-website", Namespace: "app"
|
Name: "cns-website", Namespace: "app"
|
||||||
|
|||||||
@@ -1,36 +1,145 @@
|
|||||||
# Vulnerability Scan Record Attestation
|
# Vulnerability Scan Record Attestation
|
||||||
|
|
||||||
This tutorial details
|
This tutorial details how to
|
||||||
|
|
||||||
- Scan your container image for vulnerabilities
|
- Scan container images for vulnerabilities
|
||||||
- Generate an attestation with Cosign
|
- Generate an attestation, using Cosign, with and without generating a separate key pair
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
1. Trivy CLI installed
|
1. [Trivy CLI](../../getting-started/installation.md) installed
|
||||||
2. Cosign 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:
|
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
|
For example:
|
||||||
* --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 would like to scan.
|
|
||||||
|
|
||||||
#### Attestation of the vulnerability scan with Cosign
|
|
||||||
|
|
||||||
The following command generates an attestation for the vulnerability scan and uploads it to our container image:
|
|
||||||
```
|
```
|
||||||
cosign attest --replace --predicate scan.json --type vuln anaisurlichs/cns-website:0.0.6
|
trivy image --ignore-unfixed --format cosign-vuln --output scan.json anaisurlichs/signed-example:0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
* `--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
|
||||||
|
|
||||||
|
The following command generates an attestation for the vulnerability scan and uploads it to the container image used:
|
||||||
|
```
|
||||||
|
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.
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Output</summary>
|
||||||
|
|
||||||
|
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":
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## More information
|
||||||
|
|
||||||
See [here][vuln-attestation] for more details.
|
See [here][vuln-attestation] for more details.
|
||||||
|
|
||||||
[vuln-attestation]: ../../docs/supply-chain/attestation/vuln.md
|
[vuln-attestation]: ../../docs/supply-chain/attestation/vuln.md
|
||||||
Reference in New Issue
Block a user