***This bug bash focuses on verify with CRL*** ## Overview [Ratify v1.4.0-rc] Supports CRL based on notation-core-go v1.2.0-rc1 and notation-go v1.3.0-rc1 ## Intro Certificate validation is an essential step during signature validation. Currently Ratify supports checking for revoked certificates through OCSP supported by notation-go library. However, OCSP validation requires internet connection for each validation while CRL could be cached for better performance. As notary-project added the CRL support for notation signature validation, Ratify utilized it. ### CRL Download CRL download location (URL) can be obtained from the certificate's CRL Distribution Point (CDP) extension. If the certificate contains multiple CDP locations then each location download is attempted in sequential order, until a 200 response is received for any of the location. For each CDP location, Notary Project verification workflow will try to download the CRL. If the CRL cannot be downloaded within the timeout threshold the revocation result will be "revocation unavailable". ### Prerequisite This instruction based on Ubuntu 22.04 LTS Please install `notation` following the instruction [here](https://notaryproject.dev/docs/user-guides/installation/cli/) Please install `docker engine` following the instruction [here](https://docs.docker.com/engine/install/ubuntu/) Pleaes install `kubectl` following the instruction [here](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) Please install `minikube` following the instruction [here](https://minikube.sigs.k8s.io/docs/start/?arch=%2Flinux%2Fx86-64%2Fstable%2Fbinary+download) Please install helm and helmfile from [here](https://helm.sh/docs/intro/install/#from-script) helmfile with the following commands: ``` curl -LO https://github.com/helmfile/helmfile/releases/download/v0.169.2/helmfile_0.169.2_linux_amd64.tar.gz tar xvzf <ARCHIVE_FILE> -C /usr/bin/ helmfile ``` ### Prepare the Test Scripts 1. Script A is used to generate testing certificates for CRL testing in Ratify CLI and the Ratify K8s. https://raw.githubusercontent.com/ratify-project/ratify/refs/heads/dev/scripts/generate-crl-testing-certs.sh The generated files are: - `certchain_with_crl.pem`: the fullchain file that includes the leaf certificate with CRL, intermediate certificate with invalid OCSP and valid CRL, and the root certificate. - `leaf.crl`: the CRL file that includes the leaf certificate. - `leaf.key`: the private key of the leaf certificate. - `leaf_revoked.crl`: the CRL file that includes the revoked leaf certificate. - `intermediate.crl`: the CRL file that includes the intermediate certificate. - `intermediate_revoked.crl`: the CRL file that includes the revoked intermediate - `root.crt`: the root certificate. 2. Script B is used to start a CRL server: https://raw.githubusercontent.com/ratify-project/ratify/refs/heads/dev/scripts/crl_server.py ### Prepare an Image ``` docker build -t YOURREGISTY/net-monitor:v1 https://github.com/wabbit-networks/net-monitor.git#main docker push YOURREGISTY/net-monitor:v1 ``` ### Sign the Image with the Generated Cert and Prepare CRL Server ``` # Generate NOTATION SIGNING KEY mkdir -p .staging/notation/crl-test . ./generate-crl-testing-certs.sh .staging/notation/crl-test # Create signingkeys.json notation cert generate-test --default "wabbit-networks.io" jq '.keys += [{"name":"crl-test","keyPath":"$HOME/.staging/notation/crl-test/leaf.key","certPath":"$HOME/.staging/notation/crl-test/certchain_with_crl.pem"}]' ~/.config/notation/signingkeys.json > tmp && mv tmp ~/.config/notation/signingkeys.json notation sign --key "crl-test" YOURREGISTY/net-monitor:v1 # Set yourhost to local ip address sudo sed -i '$a 127.0.0.1 yourhost' /etc/hosts # Following command can be use to check if there is any other python script running in the background ps aux | grep python # Start Serving python3 ./crl_server.py & echo "started crl server" ``` Reference: https://notaryproject.dev/docs/user-guides/how-to/notation-config-file/#sample-of-signingkeysjson ## Ratify CLI ### Install Ratify CLI Download the latest Ratify code base and build CLI ``` git clone https://github.com/ratify-project/ratify.git cd ratify make build-cli ``` ### Prepare Configuration file ``` cat <<EOF > ./config.json { "store": { "version": "1.0.0", "plugins": [ { "name": "oras", "cosignEnabled": true, "useHttp": true } ] }, "policy": { "version": "1.0.0", "plugin": { "name": "configPolicy" } }, "verifier": { "version": "1.0.0", "plugins": [ { "name": "notation", "artifactTypes": "application/vnd.cncf.notary.signature", "verificationCerts": [ "~/.staging/notation/crl-test/root.crt" ], "trustPolicyDoc": { "version": "1.0", "trustPolicies": [ { "name": "default", "registryScopes": [ "*" ], "signatureVerification": { "level": "strict" }, "trustStores": [ "ca:certs" ], "trustedIdentities": [ "*" ] } ] } } ] } } EOF ``` ### Scenario 1: Verify Image with Revocation Check ``` # Please make sure that you are using the newly build CLI ./bin/ratify verify -c config.json -s YOURREGISTY/net-monitor:v1 ``` ### Scenario 2: Verify Image with Revocation Check with Leaf Cert Revoked - Expected Failure ``` URL_LEAF="http://localhost:10086/leaf/revoke" curl -X POST "$URL_LEAF" -H "Content-Type: application/json" URL_INTER=http://localhost:10086/intermediate/unrevoke curl -X POST "$URL_INTER" -H "Content-Type: application/json" rm -rf ~/.cache/notation/crl ratify verify -c config.json -s YOURREGISTY/net-monitor:v1 ``` ### Reset the CRL Server ``` URL_LEAF="http://localhost:10086/leaf/unrevoke" curl -X POST "$URL_LEAF" -H "Content-Type: application/json" URL_INTER=http://localhost:10086/intermediate/unrevoke curl -X POST "$URL_INTER" -H "Content-Type: application/json" ``` ## Ratify K8S ### Deploy using Dev Helmfile Development charts + images are published weekly and latest versions are tagged with rolling tags referenced in dev helmfile. Deploy to cluster: ```shell minikube start helmfile sync -f git::https://github.com/ratify-project/ratify.git@dev.helmfile.yaml ``` Update `hostAliases` with following commands. The default deployment name is `ratify` and `RATIFY_NAMESPACE` is `gatekeeper-system` ``` TARGET_IP=$(ip -4 addr show "eth0" | awk '/inet/ {print $2}' | cut -d'/' -f1) kubectl patch deployment ${RATIFY_NAME} -n ${RATIFY_NAMESPACE} --type='merge' -p '{"spec":{"template":{"spec":{"hostAliases":[{"ip":"'"${TARGET_IP}"'","hostnames":["yourhost"]}]}}}}' ``` ### Update KeymanagedProvider and Trust Policy Upgrade `ratify-notation-inline-cert-0` to load `root.crt` created from the script. ```yml apiVersion: config.ratify.deislabs.io/v1beta1 kind: KeyManagementProvider metadata: name: ratify-notation-inline-cert-0 spec: type: inline parameters: contentType: certificate value: | -----BEGIN CERTIFICATE----- PLEASE INPUT THE ROOT CERT -----END CERTIFICATE----- ``` ```bash kubectl replace -f kmp.yaml --namespace gatekeeper-system ``` Update Trust Policy and Apply ```yaml apiVersion: config.ratify.deislabs.io/v1beta1 kind: Verifier metadata: name: verifier-notation spec: name: notation artifactTypes: application/vnd.cncf.notary.signature parameters: verificationCertStores: ca: ca-certs: - ratify-notation-inline-cert-0 trustPolicyDoc: version: "1.0" trustPolicies: - name: default registryScopes: - "*" signatureVerification: level: permissive trustStores: - ca:ca-certs trustedIdentities: - "*" ``` ```bash kubectl replace -f verifier.yaml --namespace gatekeeper-system ``` ### See Ratify in action Test Case 1. Successfully create the pod demo and pass revocation check ``` kubectl run demo1 --image=YOURREGISTY/net-monitor:v1 -n default kubectl get pods demo1 -n default # clean resource to delete cache kubectl delete pod <ratify-pod-name> -n gatekeeper-system ``` Test Case 2. Deploy fail due to revocation check ``` # revoke certificate by update CRL in CRL server. These commands are running in local env. URL_LEAF="http://localhost:10086/leaf/revoke" curl -X POST "$URL_LEAF" -H "Content-Type: application/json" URL_INTER=http://localhost:10086/intermediate/unrevoke curl -X POST "$URL_INTER" -H "Content-Type: application/json" kubectl run demo2 --image=YOURREGISTY/net-monitor:v1 -n default ``` Test Case 3. Shut down CRL server revocation check fail by checking cache ``` # stop CRL server # DefaultCacheTTL for verifier result is 10s # Deploy image again kubectl run demo3 --image=YOURREGISTY/net-monitor:v1 -n default ``` ## CRL (Cache) Configuration Ratify added support for caching CRLs response to improve availability, latency and avoid network overhead. 1. CLI To enable or disable CRL cache with CLI, simply edit the `crl.cache.enabled` in [config.json]. 2. K8s For Kubernetes scenarios, update the `crl.cache.enabled` in `values.yaml` of Ratify Helm Chart. ## Reference For bug bash focuses on Helm chart rendering of the Notation verifier: https://hackmd.io/@-Kl8GpDUT7WroKlFboALHw/HktQaDX8kl We have the dev image ready for test: The ratify image and ratify-crds image for dev builds exist as separate packages on Github [here](https://github.com/ratify-project/ratify/pkgs/container/ratify-dev) and [here](https://github.com/ratify-project/ratify/pkgs/container/ratify-crds-dev) dev helm chart: Package [ratify-chart-dev/ratify](https://github.com/ratify-project/ratify/pkgs/container/ratify-chart-dev%2Fratify)