PageSourceSearch

https://ratify.dev/assets/js/ec161984.e5ea1e78.js

js ratify.dev collected 2026-09-24 19:29:19 UTC 17,317 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkratify=globalThis.webpackChunkratify||[]).push([[4308],{24177(e,n,i){i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});const t=JSON.parse('{"id":"quickstarts/ratify-with-venafi","title":"Ratify with Venafi CodeSign Protect","description":"This guide will explain how to get started with Ratify and the Venafi CodeSign Protect notation plugin. This will involve setting up the necessary components, and configuring them properly. Once everything is set up we will walk through a simple scenario of verifying the signature on a container image at deployment time.","source":"@site/versioned_docs/version-1.3/quickstarts/ratify-with-venafi.md","sourceDirName":"quickstarts","slug":"/quickstarts/ratify-with-venafi","permalink":"/docs/1.3/quickstarts/ratify-with-venafi","draft":false,"unlisted":false,"editUrl":"https://github.com/ratify-project/ratify-web/blob/main/versioned_docs/version-1.3/quickstarts/ratify-with-venafi.md","tags":[],"version":"1.3","sidebarPosition":4,"frontMatter":{"sidebar_position":4},"sidebar":"tutorialSidebar","previous":{"title":"Ratify with AWS Signer","permalink":"/docs/1.3/quickstarts/ratify-with-aws-signer"},"next":{"title":"Install Ratify for High Availability","permalink":"/docs/1.3/quickstarts/ratify-high-availability"}}');var a=i(74848),s=i(28453);const r={sidebar_position:4},o="Ratify with Venafi CodeSign Protect",l={},c=[{value:"Table of Contents",id:"table-of-contents",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Prepare Container Image",id:"prepare-container-image",level:2},{value:"Sign Container Image",id:"sign-container-image",level:2},{value:"Deploy Gatekeeper",id:"deploy-gatekeeper",level:2},{value:"Deploy Ratify",id:"deploy-ratify",level:2},{value:"Deploy Container Image",id:"deploy-container-image",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"ratify-with-venafi-codesign-protect",children:"Ratify with Venafi CodeSign Protect"})}),"\n",(0,a.jsxs)(n.p,{children:["This guide will explain how to get started with Ratify and the ",(0,a.jsx)(n.a,{href:"https://venafi.com/codesign-protect/",children:"Venafi CodeSign Protect notation plugin"}),". This will involve setting up the necessary components, and configuring them properly. Once everything is set up we will walk through a simple scenario of verifying the signature on a container image at deployment time."]}),"\n",(0,a.jsx)(n.p,{children:"By the end of this guide you will have a Kubernetes cluster with Gatekeeper and Ratify installed, and have validated that only images signed by an authorized Venafi CodeSign Protect signing identity can be deployed."}),"\n",(0,a.jsxs)(n.p,{children:["This guide assumes you have a working Kubernetes cluster and ",(0,a.jsx)(n.a,{href:"https://venafi.com/codesign-protect/",children:"Venafi CodeSign Protect"})," platform.  Portions of this guide can be skipped if you have an existing cluster and/or repository."]}),"\n",(0,a.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"#ratify-with-venafi-codesign-protect",children:"Ratify with Venafi CodeSign Protect"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#table-of-contents",children:"Table of Contents"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#prerequisites",children:"Prerequisites"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#prepare-container-image",children:"Prepare Container Image"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#sign-container-image",children:"Sign Container Image"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#deploy-gatekeeper",children:"Deploy Gatekeeper"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#deploy-ratify",children:"Deploy Ratify"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#deploy-container-image",children:"Deploy Container Image"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(n.p,{children:"There are a number of tools that you will need locally to complete this guide:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://kubernetes.io/docs/tasks/tools/",children:"kubectl"}),": This is used to interact with the cluster"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://helm.sh/docs/intro/quickstart/",children:"helm"}),": This is used to install ratify components into the cluster"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://www.docker.com/get-started",children:"docker"}),": This is used to build the container image we will deploy in this guide"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/ratify-project/ratify/releases",children:"ratify"}),": This is used to check images from ECR locally"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://stedolan.github.io/jq/",children:"jq"}),": This is used to capture variables from json returned by commands"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/notaryproject/notation",children:"notation"}),": This is used to sign the container image we will deploy in this guide"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://github.com/Venafi/notation-venafi-csp",children:"Venafi CodeSign Protect notation plugin"}),": this is required to use ",(0,a.jsx)(n.code,{children:"notation"})," with ",(0,a.jsx)(n.a,{href:"https://venafi.com/codesign-protect/",children:"Venafi CodeSign Protect"})," signing identities"]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"prepare-container-image",children:"Prepare Container Image"}),"\n",(0,a.jsx)(n.p,{children:"For this guide we will create a basic container image we can use to simulate deployments of a service. We will start by\nbuilding the container image:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"docker build -t $REPO_URI:v1 https://github.com/wabbit-networks/net-monitor.git#main\n"})}),"\n",(0,a.jsx)(n.p,{children:"After the container is built we need to push it to a repository such as ECR:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"aws ecr-public get-login-password --region us-east-1 | docker login --u
1sername AWS --password-stdin $REPO_URI\n\ndocker push $REPO_URI:v1\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can also push to other OCI-compatible registries such as GitHub:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin\n\ndocker push ghcr.io/myorg/net-monitor:v1\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For more information on provisioning ECR repositories check the ",(0,a.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonECR/latest/public/public-getting-started.html",children:"documentation"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"sign-container-image",children:"Sign Container Image"}),"\n",(0,a.jsxs)(n.p,{children:["For this guide, we will sign the image using ",(0,a.jsx)(n.code,{children:"notation"})," with the Venafi CodeSign Protect platform and plugin resources."]}),"\n",(0,a.jsxs)(n.p,{children:["To use signing identity in ",(0,a.jsx)(n.code,{children:"notation"}),", we will add the certificate label as the signing key:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:'notation key add \\\n    --plugin venafi-csp \\\n    --id "venafi-csp-cert-label" \\\n    --default "venafi-csp-cert-label" \\\n    --plugin-config "config"="/path/to/vsign/config.ini"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["After the signing identity has been added, we will use ",(0,a.jsx)(n.code,{children:"notation"})," to sign the image:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"notation sign $REPO_URI:v1\n"})}),"\n",(0,a.jsx)(n.p,{children:"Both the container image and the signature should now be in the public ECR repository. We can also inspect the signature information using notation:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"notation inspect $REPO_URI:v1\n"})}),"\n",(0,a.jsxs)(n.p,{children:["More information on signing with Venafi CodeSign Protect can be found in the ",(0,a.jsx)(n.a,{href:"https://github.com/Venafi/notation-venafi-csp",children:"Venafi Notation Plugin"})," and ",(0,a.jsx)(n.a,{href:"https://github.com/notaryproject/notation",children:"notation"})," documentation."]}),"\n",(0,a.jsx)(n.h2,{id:"deploy-gatekeeper",children:"Deploy Gatekeeper"}),"\n",(0,a.jsxs)(n.p,{children:["The Ratify container will perform the actual validation of images and their artifacts, but ",(0,a.jsx)(n.a,{href:"https://github.com/open-policy-agent/gatekeeper",children:"Gatekeeper"})," is used as the policy controller for Kubernetes."]}),"\n",(0,a.jsx)(n.p,{children:"We first need to install Gatekeeper into the cluster. We will use the Gatekeeper helm chart with some customizations:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts\n\nhelm install gatekeeper/gatekeeper  \\\n    --name-template=gatekeeper \\\n    --namespace gatekeeper-system --create-namespace \\\n    --set enableExternalData=true \\\n    --set validatingWebhookTimeoutSeconds=5 \\\n    --set mutatingWebhookTimeoutSeconds=2 \\\n    --set externaldataProviderResponseCacheTTL=10s\n"})}),"\n",(0,a.jsx)(n.p,{children:"Next, we need to deploy a Gatekeeper policy and constraint. For this guide, we will use a sample policy and constraint that requires images to have at least one trusted signature."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"kubectl apply -f https://raw.githubusercontent.com/deislabs/ratify/main/library/notation-validation/template.yml\nkubectl apply -f https://raw.githubusercontent.com/deislabs/ratify/main/library/notation-validation/samples/constraint.yaml\n"})}),"\n",(0,a.jsxs)(n.p,{children:["More complex combinations of regos and Ratify verifiers can be used to accomplish many types of checks. See the ",(0,a.jsx)(n.a,{href:"https://open-policy-agent.github.io/gatekeeper/website/docs/",children:"Gatekeeper docs"})," for more information on rego authoring."]}),"\n",(0,a.jsx)(n.h2,{id:"deploy-ratify",children:"Deploy Ratify"}),"\n",(0,a.jsx)(n.p,{children:"Now we can deploy Ratify to our cluster:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"helm install ratify \\\n    ratify/ratify --atomic \\\n    --namespace gatekeeper-system \\\n    --set featureFlags.RATIFY_EXPERIMENTAL_DY
1NAMIC_PLUGINS=true \\\n    --set featureFlags.RATIFY_CERT_ROTATION=true\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Refer to the Ratify ",(0,a.jsx)(n.a,{href:"https://ratify.dev/docs/1.0/quickstarts/quickstart-manual/",children:"documentation"})," if you need to customize the helm chart installation."]}),"\n",(0,a.jsxs)(n.p,{children:["After deploying Ratify, we will download the Venafi CodeSign Protect notation plugin to the Ratify pod using the ",(0,a.jsx)(n.a,{href:"/docs/1.3/reference/dynamic-plugins",children:"Dynamic Plugins feature"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"cat > venafi-notation-plugin.yaml << EOF\napiVersion: config.ratify.deislabs.io/v1beta1\nkind: Verifier\nmetadata:\n  name: notation-venafi-csp-plugin\nspec:\n  name: notation-venafi-csp\n  artifactTypes: application/vnd.oci.image.manifest.v1+json\n  source:\n    artifact: ghcr.io/venafi/notation-venafi-csp:linux-amd64-latest\nEOF\n\nkubectl apply -f venafi-notation-plugin.yaml\n"})}),"\n",(0,a.jsx)(n.p,{children:"Next we will need to deploy the trusted Root certificate used to issue the signing identity referenced above:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"cat > venafi_root.yaml << EOF\napiVersion: config.ratify.deislabs.io/v1beta1\nkind: CertificateStore\nmetadata:\n  name: ratify-notation-inline-cert\n  namespace: gatekeeper-system\nspec:\n  provider: inline\n  parameters:\n    value: |\n      -----BEGIN CERTIFICATE-----\n      ...\n      -----END CERTIFICATE-----\nEOF\n\nkubectl apply -f venafi_root.yaml\n"})}),"\n",(0,a.jsx)(n.p,{children:"Finally, we will create a verifier that specifies the trust policy to use when verifying signatures. In this guide, we will use a trust policy that only trusts images signed by the Venafi CodeSign Protect signing identity we created earlier:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:'cat > notation-verifier.yaml << EOF\napiVersion: config.ratify.deislabs.io/v1beta1\nkind: Verifier\nmetadata:\n  name: verifier-notation\nspec:\n  name: notation\n  artifactTypes: application/vnd.cncf.notary.signature\n  parameters:\n    verificationCertStores:\n      signingAuthority:\n        certs:\n          - ratify-notation-inline-cert\n    trustPolicyDoc:\n      version: "1.0"\n      trustPolicies:\n        - name: default\n          registryScopes:\n            - "*"\n          signatureVerification:\n            level: strict\n          trustStores:\n            - signingAuthority:certs\n          trustedIdentities:\n            - "x509.subject: CN=signer.example.com,O=Acme,L=Cupertino,ST=CA,C=US"\nEOF\n\nkubectl apply -f notation-verifier.yaml\n'})}),"\n",(0,a.jsxs)(n.p,{children:["More complex trust policies can be used to customize verification. See ",(0,a.jsx)(n.a,{href:"https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md",children:"notation documentation"})," for more information on writing trust policies."]}),"\n",(0,a.jsx)(n.h2,{id:"deploy-container-image",children:"Deploy Container Image"}),"\n",(0,a.jsx)(n.p,{children:"Now that the signed container image is in the registry and Ratify is installed into the Kubernetes cluster we can deploy our\ncontainer image:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"kubectl run demosigned -n default --image $REPO_URI:v1\n"})}),"\n",(0,a.jsx)(n.p,{children:"We should be able to see from the Ratify and Gatekeeper logs that the container signature was validated. The pod for the container should also be running."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"kubectl logs -n gatekeeper-system deployment/ratify\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'time=2023-11-15T18:24:22.104435502Z level=info msg=verify result for subject ghcr.io/myorg/net-monitor@sha256:fcc8a5d24fcc9619b80e2e86695d2a792108add778439ac0a0647c9cae745176: {\n  "isSuccess": true,\n  "verifierReports": [\n    {\n      "subject": "ghcr.io/myorg/net-monitor@sha256:fcc8a5d24fcc9619b80e2e86695d2a792108add778439ac0a0647c9cae745176",\n      "isSuccess": true,\n      "name": "notation",\n      "message": "signature verification success",\n      "extensions": {\n        "Issuer": "CN=Issuer,O=Example,C=US",\n        "SN": "CN=signer.example.com,O=Example,L=San Jose,ST=CA,C=US"\n      },\n      "artifactType": "application/vnd.cncf.notary.signature"\n    }\n  ]\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"We can also test that an image without a valid signature is not able to run:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:'kubectl run demounsigned -n default --image busybox\nError from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [ratify-constraint] Subject failed verification: docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79\n'})}),"\n",(0,a.jsx)(n.p,{children:"The command should fail with an error and we should be able to see from the Ratify and Gate
1keeper logs that the signature validation failed."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'time=2023-11-15T18:24:08.110678426Z level=info msg=verify result for subject docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79: {\n  "verifierReports": [\n    {\n      "subject": "docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79",\n      "isSuccess": false,\n      "message": "verification failed: Error: referrers not found, Code: REFERRERS_NOT_FOUND, Component Type: executor"\n    }\n  ]\n}\n'})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},28453(e,n,i){i.d(n,{R:()=>r,x:()=>o});var t=i(96540);const a={},s=t.createContext(a);function r(e){const n=t.useContext(s);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.