diff --git a/building.md b/building.md new file mode 100644 index 000000000..16cef244a --- /dev/null +++ b/building.md @@ -0,0 +1,34 @@ +# Building NV2 + +The nv2 repo contains the following: + +- `nv2` - A CLI for signing and verifying with Notary v2 +- `docker-generate` - Extends docker with `docker generate` to create locally persisted manifest for signing, without having to push to a registry. +- `docker-nv2` - Extends docker with `docker nv2 notary` to enable, sign and verify Notary v2 signatures on `docker pull` + +This plugin requires [golang](https://golang.org/dl/) with version `>= 1.16`. + +## Windows with WSL + +- Build the binaries, installing them to: + - `~/bin/nv2` + - `~/.docker/cli-plugins/docker-generate` + - `~/.docker/cli-plugins/docker-nv2` + ```shell + git clone https://github.com/notaryproject/nv2.git + cd nv2 + git checkout prototype-2 + make install + ``` +- Verify binaries are installed + ```bash + docker --help + # look for + Management Commands: + generate* Generate artifacts (github.com/shizhMSFT, 0.1.0) + nv2* Notary V2 Signature extension (Sajay Antony, Shiwei Zhang, 0.2.3) + + which nv2 + # output + /home/]/bin/nv2 + ``` diff --git a/docs/nv2/README.md b/docs/nv2/README.md index 987b78a04..b9252fb94 100644 --- a/docs/nv2/README.md +++ b/docs/nv2/README.md @@ -12,24 +12,7 @@ ### Build and Install -This plugin requires [golang](https://golang.org/dl/) with version `>= 1.16`. - -To build and install, run - -```shell -go install github.com/notaryproject/nv2/cmd/nv2 -``` - -To build and install to an optional path, run - -```shell -go build -o nv2 ./cmd/nv2 -``` - -Next, install optional components: - -- Install [docker-generate](https://github.com/shizhMSFT/docker-generate) for local Docker manifest generation and local signing. -- Install [OpenSSL](https://www.openssl.org/) for key generation. +`nv2`: see [building.md](/building.md) ### Self-signed certificate key generation diff --git a/docs/nv2/demo-script-detailed.md b/docs/nv2/demo-script-detailed.md deleted file mode 100644 index cdb8e8754..000000000 --- a/docs/nv2/demo-script-detailed.md +++ /dev/null @@ -1,380 +0,0 @@ -# Detailed Demo Steps - -The following demonstrates the underlying details of **prototype-2**. - -> At this point, this is a target experience, that is still being developed. - -## Demo Setup - -Perform the following steps prior to the demo: - -- Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for local docker operations -- [Install and Build the nv2 Prerequisites](./README.md#prerequisites) -- Create an empty working directory: - ```bash - mkdir nv2-demo - cd nv2-demo/ - ``` -- Generate the Wabbit Networks Public and Private Keys: - ```bash - openssl req \ - -x509 \ - -sha256 \ - -nodes \ - -newkey rsa:2048 \ - -days 365 \ - -subj "/CN=registry.wabbit-networks.io/O=wabbit-networks inc/C=US/ST=Washington/L=Seattle" \ - -addext "subjectAltName=DNS:registry.wabbit-networks.io" \ - -keyout ./wabbit-networks.key \ - -out ./wabbit-networks.crt - ``` -- Start a local registry instance: - ```bash - # NOTE: the nv2-prototype-2 image does not yet exist - docker run -d -p 80:5000 --restart always --name registry notaryv2/registry:nv2-prototype-2 - ``` -- Add a `etc/hosts` entry to simulate pushing to registry.wabbit-networks.io - - If running on windows, _even if using wsl_, add the following entry to: `C:\Windows\System32\drivers\etc\hosts` - ```hosts - 127.0.0.1 registry.wabbit-networks.io - ``` - -## Demo Reset - -If iterating through the demo, these are the steps required to reset to a clean state: - -- Remove docker alias: - ```bash - unalias docker - ``` -- Reset the local registry: - ```bash - docker rm -f $(docker ps -a -q) - docker run -d -p 80:5000 --restart always --name registry notaryv2/registry:nv2-prototype-1 - ``` -- Remove the `net-monitor:v1` image: - ```bash - docker rmi -f registry.wabbit-networks.io/net-monitor:v1 - ``` -- Remove `wabbit-networks.crt` from `"verificationCerts"`: - ```bash - code ~/.docker/nv2.json - ``` - -## The End to End Experience - -![](../../media/notary-e2e-scenarios.svg) - -- Wabbit Networks is a small software company that produces network monitoring software. -- ACME Rockets wishes to acquire network monitoring software. -- ACME Rockets doesn't know about Wabbit Networks, but finds their [net-monitor software in Docker Hub](https://hub.docker.com/r/wabbitnetworks/net-monitor) -- Since they've never heard of Wabbit Networks, they're a little reluctant to run network software without some validations. -- ACME Rockets has a policy to only import Docker Hub certified software, or approved vendors. -- Wabbit Networks works with Docker Hub to get certified, to help with their customer confidence. -- ACME Rockets will only deploy software that's been scanned and approved by the ACME Rockets security team. They know it's been approved because all approved software has been signed by the ACME Rockets security team. - -## Wabbit Networks Build, Sign, Promote Process - -Let's walk through the sequence of operations Wabbit Networks takes to build, sign and promote their software. - -Within the automation of Wabbit Networks, the following steps are completed: - -1. Build the container image -1. Sign the container image -1. Create an SBoM -1. Sign the SBoM -1. Push the image, sbom, and the associated signatures to the registry - -### Summary of artifacts - -The following graph of artifacts will be created and pushed to the registry - -![](../../media/net-monitor-sbom-signed-detailed.svg) - -- the `net-monitor:v1` image - - the blob content of the `net-monitor:v1` image -- a wabbit-networks signature of the `net-monitor:v1` image - - the blob content of the signature -- an SBoM for the `net-monitor:v1` image - - the blob content of the sbom -- a wabbit-networks signature of the `net-monitor:v1 sbom` - - the blob content of the signature for the sbom - -![](../../media/net-monitor-sbom-signed-artifacts.svg) - -Viewed with less detail, the above image represents 4 artifacts connected through linked manifests: - -1. the `net-monitor:v1` image -1. a wabbit-networks signature of the `net-monitor:v1` image -1. an SBoM for the `net-monitor:v1` image -1. a wabbit-networks signature of the `net-monitor:v1 sbom` - -### Build the `net-monitor` image - - ```bash - docker build \ - -t registry.wabbit-networks.io/net-monitor:v1 \ - https://github.com/wabbit-networks/net-monitor.git#main - ``` - -### Generate the manifest - -Notary v2 signs the manifests of the content as they're represented within a registry. In normal docker operations, the image manifest is a hidden element the user doesn't have to deal with. For the sake full transparency, we'll highlight the full workflow by generating the manifest to sign the digest. - -```bash -docker generate manifest registry.wabbit-networks.io/net-monitor:v1 \ - > net-monitor_v1-manifest.json - -# view the manifest -cat ./net-monitor_v1-manifest.json -``` - -### Acquire the private key - -> TODO: Add any key management prototype steps here: - -- As a best practice, we'll always build on an ephemeral client, with no previous state. -- The ephemeral client will retrieve the private signing key from the companies secured key vault provider. - -These specific steps are product/cloud specific, so we'll assume these steps have been completed and we have the required keys. - -### Sign and Push - -Using the private key, we'll sign the `net-monitor:v1` image. Note, we're signing the image with a registry name that we haven't yet pushed to. This enables offline signing scenarios. This is important as the image will eventually be published on `registry.wabbit-networks.io/`, however their internal staging and promotion process may publish to internal registries before promotion to the public registry. - -- Generates an [nv2 signature][nv2-signature], persisted locally as `net-monitor_v1-signature.jwt` - - ```shell - nv2 sign -m x509 \ - -o net-monitor_v1-signature.jwt \ - -k ~/.ssh/wabbit-networks.key \ - -r registry.wabbit-networks.io/net-monitor:v1 \ - file:./net-monitor_v1-manifest.json - - # view the signature - cat ./net-monitor_v1-signature.jwt - ``` - -- Push the container image - - ```bash - docker push registry.wabbit-networks.io/net-monitor:v1 - ``` - -- Push the `net-monitor:v1` signature to the registry using ORAS - - ```bash - # implies a new means to push an artifact to a repo, without a tag - # need a good design for how to declare content is pushed, where the digest is computed by ORAS, or the underlying tool - # linked-manifest uses digests to assure links are established to the specific artifact, avoiding conflicts to updating tags - # artifact-type replaces - oras push registry.wabbit-networks.io/net-monitor \ - --push-as-digest \ - --artifact-type application/vnd.cncf.notary.v2 \ - --manifest-type application/vnd.oci.artifact.manifest.v1 \ - --manifests registry.wabbit-networks.io/net-monitor@sha256:12as1201... \ - --plain-http \ - ./net-monitor_v1.signature.jwt - ``` - -## Generate an SBoM - -This demo focuses on the signing of additional content, including an SBoM. It doesn't focus on a specific SBoM format. As a result, we'll generate the most basic, and _admittedly_ useless SBoM document: - -```bash -echo '{"version": "0.0.0.0", "image": "registry.wabbit-networks.io/net-monitor:v1", "contents": "good"}' > sbom_v1.json -``` - -### Sign the SBoM - -This is where some of the Notary v2 signature and persistance formats come through. Notary v2 signs a _**Registry Manifest**_. Registry manifests are things that describe the content that's persisted in the registry. There are two manifest formats today: [image-manifest][oci-image-manifest] and [image-index][oci-image-index]. These manifests describe self-contained content, for container images. Since Notary v2 signatures are enhancements to exiting content, we need a way to describe self-contained content that references existing content. An SBoM is yet another type of reference content. The [oci.artifact.manifest][oci-artifact-manifest] provides the ability to describe self-contained content, and link to existing content. - -To enable a Notary v2 signature of an [oci.artifact.manifest][oci-artifact-manifest], we first need to generate that manifest. In the container scenarios, we used the [docker-generate][docker-generate] plug-in to generate a manifest for container images. - -- For non-container images, we'll use the [ORAS cli][oras] to generate an [oci.artifact.manifest][oci-artifact-manifest]. - ```bash - oras generate-manifest \ - --manifest-type application/vnd.oci.artifact.manifest.v1 \ - --artifact-type application/vnd.example.sbom.v0 \ - --manifests oci://registry.wabbit-networks.io/net-monitor@sha256:1a0a0a89a \ - --output sbom_v1-manifest.json \ - ./sbom_v1.json - - # view the manifest - cat sbom_v1-manifest.json - ``` - -- Sign the manifest that represents the SBoM. - - ```bash - nv2 sign -m x509 \ - -k ~/.ssh/wabbit-networks.key \ - -r registry.wabbit-networks.io/net-monitor:v1 \ - -o net-monitor_v1-sbom.signature.jwt \ - file:sbom_v1-manifest.json - - # view the signature - cat ./net-monitor_v1-sbom.signature.jwt - ``` - -- Push the `net-monitor:v1` **sbom** to the registry using ORAS - - ```bash - oras push registry.wabbit-networks.io/net-monitor \ - --push-as-digest \ - --artifact-type application/vnd.example.sbom.v0 \ - --manifest-type application/vnd.oci.artifact.manifest.v1 \ - --manifests oci://registry.wabbit-networks.io/net-monitor@sha256:1a0a0a89a \ - --plain-http \ - ./sbom_v1-manifest.json - # Note: need to capture the digest of the pushed SBoM, for the linkage of the signature - ``` - -- Push the `net-monitor:v1` **sbom signature** to the registry using ORAS - - ```bash - oras push registry.wabbit-networks.io/net-monitor \ - --push-as-digest \ - --artifact-type application/vnd.cncf.notary.v2 \ - --manifest-type application/vnd.oci.artifact.manifest.v1 \ - --manifests oci://registry.wabbit-networks.io/net-monitor@${NET_MONITOR_SBOM_DIGEST} \ - --plain-http \ - ./net-monitor_v1-sbom.signature.jwt - ``` - -## Pulling Validated Content - -To represent a deployed, ephemeral node, we'll pull the `net-monitor:v1` image, validating the signature of the image and the sbom. - -### Clear the build content - -To simulate another client, we'll clear out the `net-monitor:v1` image and signature, simulating a new environment. - -> Note: The public and private keys are maintained, deferring to key management prototypes for how keys should be acquired. - -```bash -docker rmi -f registry.wabbit-networks.io/net-monitor:v1 -rm *.jwt -rm *.json -``` - -### Attempt, and fail to pull the image - -Simulate a notary enabled client, which doesn't yet have the public keys configured. - -- Get the digest for the `net-monitor:v1` image: - ```bash - NET_MONITOR_DIGEST=$(curl -v -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ - registry.wabbit-networks.io/v2/net-monitor/manifests/v1 2>&1 | \ - grep -i 'Docker-Content-Digest:' | \ - awk '{print $3}') - ``` -- Query for Notary v2 linked artifacts - ```bash - curl -v -H "Accept: artifactType=application/vnd.cncf.notary.v2" \ - registry.wabbit-networks.io/v2/_ext/oci-artifacts/net-monitor/manifests/${NET_MONITOR_DIGEST}/links - NET_MONITOR_SIG_DIGEST=^ - ``` -- Retrieve the `net-monitor:v1` notary v2 signature - ```bash - oras pull registry.wabbit-networks.io/net-monitor@sha256:${NET_MONITOR_SIG_DIGEST} \ - --plain-http - ``` -- Validate the signature - ```bash - nv2 verify \ - -c ./wabbit-networks.crt \ - -f net-monitor_v1.signature.jwt \ - oci://registry.wabbit-networks.io/net-monitor:v1 - ``` - The above validation will fail, as we haven't yet configured notary to find the `wabbit-networks.crt` public key. -- Configure Notary access to the wabbit-networks key - ```bash - code ~/.docker/nv2.json - ``` -- Add the path to the cert: - ```json - "verificationCerts": [ - "/home/stevelas/nv2-demo/wabbit-networks.crt" - ] - ``` -- Validate the signature - ```bash - nv2 verify \ - -c ./wabbit-networks.crt \ - -f net-monitor_v1.signature.jwt \ - oci://registry.wabbit-networks.io/net-monitor:v1 - ``` - -- Pull the image, as the signature validation succeeded - ```bash - docker pull $image - ``` - -## Appendix - -### Convert the tag to a digest - -```bash -curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -vvv -k registry.wabbit-networks.io/v2/net-monitor/manifests/v1 -curl -H "Accept: application/vnd.oci.image.manifest.v2+json" -vvv -k registry.wabbit-networks.io/v2/net-monitor/manifests/v1 -curl -vvv -k registry.wabbit-networks.io/v2/net-monitor/manifests/v1 - -curl -v -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ - https://mcr.microsoft.com/v2/aks/hcp/etcd-azure/manifests/v3.1.19 2>&1 | \ - grep -i 'Docker-Content-Digest:' | \ - awk '{print $3}' -curl -v -H "Accept: application/vnd.oci.image.manifest.v2+json" \ - https://mcr.microsoft.com/v2/aks/hcp/etcd-azure/manifests/v3.1.19 2>&1 | \ - grep -i 'Docker-Content-Digest:' | \ - awk '{print $3}' - -curl -v -H "Accept: application/vnd.oci.image.manifest.v2+json" \ - https://mcr.microsoft.com/v2/aks/hcp/etcd-azure/manifests/v3.1.19 2>&1 | \ - grep -i 'Docker-Content-Digest:' | \ - awk '{print $3}' - - - -curl -v -H "Accept: application/vnd.oci.image.manifest.v2+json" \ - registry.wabbit-networks.io/v2/net-monitor/manifests/v1 2>&1 | \ - grep -i 'Docker-Content-Digest:' | \ - awk '{print $3}' -``` - -### Query for linked artifacts - -```bash -GET /v2/_ext/{repository}/manifests/{digest}/links?artifactType=application/vnd.oci.notary.v2.config+json&n=10 -GET registry.wabbit-networks.io/v2/_ext/net-monitor/manifests/{digest}/links?artifactType=application/vnd.oci.notary.v2.config+json - -``` - -#### Validate the image - -To validate an image, we need the signature, which can be pulled prior to the image. We want to avoid pulling images we haven't validated, as this could be a trojan horse type exploit. - -```bash -oras pull registry.wabbit-networks.io/net-monitor:v1-signature -a --plain-http -``` -> TODO: Fix CN validation -```bash -nv2 verify \ - -c ~/.ssh/wabbit-networks.crt \ - -f net-monitor_v1.signature.jwt \ - file:net-monitor_v1-manifest.json - -nv2 verify \ - -c ~/.ssh/wabbit-networks.crt \ - -f net-monitor_v1.signature.jwt \ - oci://registry.wabbit-networks.io/net-monitor:v1 - -2021/03/02 14:27:38 verification failure: x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0 -``` - -[docker-generate]: https://github.com/shizhMSFT/docker-generate -[nv2-signature]: ../signature/README.md -[oci-image-manifest]: https://github.com/opencontainers/image-spec/blob/master/manifest.md -[oci-image-index]: https://github.com/opencontainers/image-spec/blob/master/image-index.md -[oci-artifact-manifest]: https://github.com/opencontainers/artifacts/blob/3e34f029537052639eed59b469cb6c43706ac3d0/artifact-manifest.md -[oras]: https://github.com/deislabs/oras \ No newline at end of file diff --git a/docs/nv2/demo-script.md b/docs/nv2/demo-script.md index 66b867b87..1aa71abf9 100644 --- a/docs/nv2/demo-script.md +++ b/docs/nv2/demo-script.md @@ -1,18 +1,27 @@ -# nv2 Demo Script +# Demo Steps -The following is a summary when presenting a demo of Notary v2 - prototype-2. +The following demonstrates the capabilities of [Notary v2 - Prototype-2][nv2-prototype-2]. ## Demo Setup Perform the following steps prior to the demo: - Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for local docker operations -- [Install and Build the nv2 Prerequisites](./README.md#prerequisites) -- Create an empty working directory: +- [Install and Build nv2](../../building.md) +- [Install and Build the ORAS Prototype-2 branch](https://github.com/deislabs/oras/blob/prototype-2/docs/artifact-manifest.md) +- Generate the `~/.docker/nv2.json` config file ```bash - mkdir nv2-demo - cd nv2-demo/ + docker nv2 notary --enabled ``` +- Setup names and variables with `localhost:5000` + >**NOTE:** See [Simulating a Registry DNS Name](#simulating-a-registry-dns-name) for using `registry.wabbit-networks.io` + ```bash + export PORT=5000 + export REGISTRY=localhost:${PORT} + export REPO=${REGISTRY}/net-monitor + export IMAGE=${REPO}:v1 + ``` + - Generate the Wabbit Networks Public and Private Keys: ```bash openssl req \ @@ -21,48 +30,17 @@ Perform the following steps prior to the demo: -nodes \ -newkey rsa:2048 \ -days 365 \ - -subj "/CN=registry.wabbit-networks.io/O=wabbit-networks inc/C=US/ST=Washington/L=Seattle" \ - -addext "subjectAltName=DNS:registry.wabbit-networks.io" \ + -subj "/CN=${REGISTRY}/O=wabbit-networks inc/C=US/ST=Washington/L=Seattle" \ + -addext "subjectAltName=DNS:${REGISTRY}" \ -keyout ./wabbit-networks.key \ -out ./wabbit-networks.crt ``` -- Start a local registry instance: - ```bash - docker run -d -p 80:5000 --restart always --name registry notaryv2/registry:nv2-prototype-1 - ``` -- Add a `etc/hosts` entry to simulate pushing to registry.wabbit-networks.io - - If running on windows, _even if using wsl_, add the following entry to: `C:\Windows\System32\drivers\etc\hosts` - ```hosts - 127.0.0.1 registry.wabbit-networks.io - ``` - -## Demo Reset - -If iterating through the demo, these are the steps required to reset to a clean state: - -- Remove docker alias: - ```bash - unalias docker - ``` -- Reset the local registry: - ```bash - docker rm -f $(docker ps -a -q) - docker run -d -p 80:5000 --restart always --name registry notaryv2/registry:nv2-prototype-1 - ``` -- Remove the `net-monitor:v1` image: +### Start a Local Registry Instance ```bash - docker rmi -f registry.wabbit-networks.io/net-monitor:v1 + docker run -d -p ${PORT}:5000 notaryv2/registry:nv2-prototype-2 ``` -- Remove `wabbit-networks.crt` from `"verificationCerts"`: - ```bash - code ~/.docker/nv2.json - ``` - -## Demo Steps -### Explain the end to end experience being presented - -![](../../media/notary-e2e-scenarios.svg) +## Demo The End to End Experience - Wabbit Networks is a small software company that produces network monitoring software. - ACME Rockets wishes to acquire network monitoring software. @@ -72,40 +50,14 @@ If iterating through the demo, these are the steps required to reset to a clean - Wabbit Networks works with Docker Hub to get certified, to help with their customer confidence. - ACME Rockets will only deploy software that's been scanned and approved by the ACME Rockets security team. They know it's been approved because all approved software has been signed by the ACME Rockets security team. -### Show Notary Extension - -To demonstrate a clean end to end experience, using the docker cli, we're using the [docker-generate][docker-generate] extension. - -To see the extension capabilities, review the `Management Commands:`: - -```bash -docker --help - -Management Commands: - ... - generate* Generate artifacts (github.com/shizhMSFT, 0.1.0) - nv2* Notary V2 Signature extension (Sajay Antony, Shiwei Zhang, 0.1.0) - -``` - -To see the sub commands of `nv2` and `nv2 notary`: - -```bash -docker nv2 --help -docker nv2 notary --help -``` - -To avoid having to type `docker nv2` each time, we'll create an alias to mask over this: - -```bash -alias docker="docker nv2" -``` +![](../../media/notary-e2e-scenarios.svg) -To avoid having to type the fully qualified registry name, we'll create an environment variable: +### Alias `nv2` Commands -```bash -export image=registry.wabbit-networks.io/net-monitor:v1 -``` +- To avoid having to type `docker nv2` each time, create an alias: + ```bash + alias docker="docker nv2" + ``` ## Wabbit Networks Build, Sign, Promote Process @@ -113,13 +65,20 @@ Let's walk through the sequence of operations Wabbit Networks takes to build, si Within the automation of Wabbit Networks, the following steps are completed: +1. Building the `net-monitor` image +1. Sign the `net-monitor` image +1. Push the image and signature +1. Create and push a signed SBoM + ### Build the `net-monitor` image -```bash -docker build \ - -t $image \ +- Build the image, directly from GitHub to simplify the sequence. + ```bash + docker build \ + -t $IMAGE \ https://github.com/wabbit-networks/net-monitor.git#main -``` + ``` + _To represent an ephemeral client in an air-gapped environment, git clone, then build with `.` as the context_ ### Acquire the private key @@ -128,44 +87,42 @@ docker build \ These specific steps are product/cloud specific, so we'll assume these steps have been completed. -### Sign the image +### Sign and Push the Image and Signature -Using the private key, we'll sign the net-monitor image. Note, we're signing the image with a registry name that we haven't yet pushed to. This enables offline signing scenarios. This is important as the image will eventually be published on `registry.wabbit-networks.io/`, however their internal staging and promotion process may publish to internal registries before promotion to the public registry. +Using the private key, we'll sign the `net-monitor:v1` image. Note, we're signing the image with a registry name that we haven't yet pushed to. This enables offline signing scenarios. This is important as the image will eventually be published on `registry.wabbit-networks.io/`, however their internal staging and promotion process may publish to internal registries before promotion to the public registry. -- Generate an [nv2 signature][nv2-signature], persisted locally as `net-monitor_v1.signature.config.jwt` +- Generate an [nv2 signature][nv2-signature], persisted locally as `net-monitor_v1.signature.jwt` +- Enable notary, for the nv2 extension to account for signing and verification steps ```shell docker notary --enabled - + ``` +- Generate an [nv2 signature][nv2-signature], persisted within the `/.docker/nv2/sha256/` directory: + ```shell docker notary sign \ --key ./wabbit-networks.key \ --cert ./wabbit-networks.crt \ - $image + $IMAGE ``` -- view the signature referenced from docker notary sign +- Push the image, with the signature ```bash - cat + docker push $IMAGE ``` - -- View the manifest the signature is based upon: +- View the output, which includes pushing the signature as a reference: ```bash - docker generate manifest $image + The push refers to repository [registry.wabbit-networks.io/net-monitor] + 8ea3b23f387b: Preparing + 8ea3b23f387b: Pushed + v1: digest: sha256:31c6d76b9a0af8d2c0a7fc16b43b7d8d9b324aa5ac3ef8c84dc48ab5ba5c0f49 size: 527 + Pushing signature + signature manifest: digest: sha256:8eb7394c8f287ebd0e84a4659f37a2688c6e07e39906933ccb83d9011fb29034 size: 2534 + refers to manifests: digest: sha256:31c6d76b9a0af8d2c0a7fc16b43b7d8d9b324aa5ac3ef8c84dc48ab5ba5c0f49 size: 527 ``` - -### Push the image & signature to the registry - -Push the image, and its signature in one user gesture. Note the push links the signature to the image for later retrevial by a `:tag` or `digest`. - -```shell -docker push $image -``` - -### Clear the local image - -- To simulate another client, we'll clear out the `net-monitor:v1` image +- Discover the references using the [oras prototype-2 branch](https://github.com/deislabs/oras/tree/prototype-2). ```bash - docker rmi -f registry.wabbit-networks.io/net-monitor:v1 - rm ~/.docker/nv2/sha256/*.* + oras discover \ + --plain-http \ + $IMAGE ``` ### Validate the image @@ -174,7 +131,7 @@ To validate an image, `docker pull` with `docker notary --enabled` will attempt - Attempt to pull the `net-monitor:v1` image: ```bash - docker pull $image + docker pull $IMAGE ``` - The above command will fail, as we haven't configured the `nv2` client access to the public keys. @@ -194,14 +151,14 @@ To validate an image, `docker pull` with `docker notary --enabled` will attempt { "enabled": true, "verificationCerts": [ - "/home/stevelas/nv2-demo/wabbit-networks.crt" + "/home//nv2-demo/wabbit-networks.crt" ] } ``` - Pull the `net-monitor:v1` image, using the public key for verification: ```bash - docker pull $image + docker pull $IMAGE ``` - The validated pull can be seen: ```bash @@ -217,7 +174,134 @@ To validate an image, `docker pull` with `docker notary --enabled` will attempt registry.wabbit-networks.io/net-monitor@sha256:48575dfb9ef2ebb9d67c6ed3cfbd784d635fcfae8ec820235ffa24968b3474dc ``` -This shows the target experience we're shooting for, within various build and container runtime tooling. +### Create a Software Bill of Materials + +- Create an overly simplistic SBoM + ```bash + echo '{"version": "0.0.0.0", "artifact": "net-monitor:v1", "contents": "good"}' > sbom.json + ``` +- Push the SBoM with ORAS, saving the manifest for signing + ```bash + oras push $REPO \ + --artifact-type application/x.example.sbom.v0 \ + --artifact-reference $IMAGE \ + --export-manifest sbom-manifest.json \ + --plain-http \ + ./sbom.json:application/tar + ``` +- View the references with `oras discover`: + ```bash + oras discover \ + --plain-http \ + $IMAGE + ``` + +### Sign the SBoM + +In the above case, the SBoM has already been pushed to the registry. To sign it before pushing, we could have used `oras push` with the `--dry-run` and `--export-manifest` options. + +- For non-container images, we'll use the `nv2` cli to sign and the `oras` cli to push to a registry. We'll use the `oras discover` cli to find the sbom digest the signature will reference. + ```bash + nv2 sign \ + -m x509 \ + -k wabbit-networks.key \ + -c wabbit-networks.crt \ + --plain-http \ + --push \ + --push-reference oci://${REPO}@$(oras discover \ + --artifact-type application/x.example.sbom.v0 \ + --output-json \ + --plain-http \ + $IMAGE | jq -r .references[0].digest) \ + file:sbom-manifest.json + ``` +- Dynamically get the SBoM digest + ```bash + DIGEST=$(oras discover \ + --artifact-type application/x.example.sbom.v0 \ + --output-json \ + --plain-http \ + $IMAGE | jq -r .references[0].digest) +- Discover referenced artifacts of the SBoM + ```bash + oras discover \ + --plain-http \ + ${REPO}@${DIGEST} + ``` +- Generates: + ```bash + Discovered 1 artifacts referencing localhost:5000/net-monitor@sha256:adfe3a3c50838fc2a19d5d7e73119dcadad7ad8e4e98f1e0fd100dd9d2278b71 + Digest: sha256:adfe3a3c50838fc2a19d5d7e73119dcadad7ad8e4e98f1e0fd100dd9d2278b71 + + Artifact Type Digest + application/vnd.cncf.notary.v2 sha256:b7fc5fdb81f2ada359d0a709004360d1f08c9d2ac8a80630b152d1c6fb35460e + ``` + +The above workflow demonstrates the **Notary v2, prototype-2** target experience. + +## Optional Steps + +Some optional steps: + +## Demo Reset + +If iterating through the demo, these are the steps required to reset to a clean state: + +- Remove docker alias: + ```bash + unalias docker + ``` +- Reset the local registry: + ```bash + docker rm -f $(docker ps -a -q) + docker run -d -p ${PORT}:5000 notaryv2/registry:nv2-prototype-2 + ``` +- Remove the `net-monitor:v1` image: + ```bash + docker rmi -f ${REGISTRY}/net-monitor:v1 + ``` +- Remove `wabbit-networks.crt` from `"verificationCerts"` in the `nv2.json` configuration file: + ```bash + code ~/.docker/nv2.json + ``` +- Remove previous signatures: + ```bash + rm -r ~/.docker/nv2/sha256/ + ``` + +### Simulating a Registry DNS Name + +Configure the additional steps to simulate a fully qualified dns name for wabbit-networks. -[nv2-signature]: ../signature/README.md -[docker-generate]: https://github.com/shizhMSFT/docker-generate \ No newline at end of file +- Setup names and variables with `registry.wabbit-networks.io` + ```bash + export PORT=80 + export REGISTRY=registry.wabbit-networks.io + export REPO=${REGISTRY}/net-monitor + export IMAGE=${REPO}:v1 + ``` +- Edit the `~/.docker/nv2.json` file to support local, insecure registries + ```json + { + "enabled": true, + "verificationCerts": [ + ], + "insecureRegistries": [ + "registry.wabbit-networks.io" + ] + } + ``` +- Add a `etc/hosts` entry to simulate pushing to registry.wabbit-networks.io + - If running on windows, _even if using wsl_, add the following entry to: `C:\Windows\System32\drivers\etc\hosts` + ```hosts + 127.0.0.1 registry.wabbit-networks.io + ``` +- Continue with [Start a Local Registry Instance](#start-a-local-registry-instance) + +[docker-generate]: https://github.com/notaryproject/nv2/tree/prototype-2 +[nv2-signature]: ../signature/README.md +[oci-image-manifest]: https://github.com/opencontainers/image-spec/blob/master/manifest.md +[oci-image-index]: https://github.com/opencontainers/image-spec/blob/master/image-index.md +[oci-artifact-manifest]: https://github.com/SteveLasker/artifacts/blob/oci-artifact-manifest/artifact-manifest.md +[oras]: https://github.com/deislabs/oras/tree/prototype-2 +[nv2-prototype-2]: https://github.com/notaryproject/notaryproject/issues/53