# Build, sign, push and verify images as OCI image layout
## Background
Do you trust your container registries? Nowadays, users push the container images in the registry first, then sign the container image. What will happen if the registries are compromised? You could sign something that is not what you want to sign. The worst thing is that users can verify the container image successfully and use it in production. Sign images as OCI image layout is a new and creative way, which enable signing images on local disk before pushing them to the remote registry, thus the integrity of the images are secured.
## What is a OCI image layout?
OCI image layout is a directory structure that contains files and folders that refer to an OCI image. OCI image layout is defined in [OCI image spec](https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/image-layout.md).
## How can I create OCI image layout?
### Use container image builder (Option 1)
Use `docker buildx` to output the image that is built in the form of OCI Image Layout on local disk.
1. Create a Dockerfile
```text
FROM alpine
CMD echo 'hello world!'
```
2. Build and save image in the form of OCI image layout on disk
```shell
docker buildx create --use
docker buildx build . -f Dockerfile -o type=oci,dest=hello-world.tar -t hello-world:v1
```
In this example, `docker buildx build` saved the image in the form of OCI image layout as a tar file named `hell-world.tar`. The OCI image layout could also be in the form of a directory. For example,
```shell
mkdir hello-world
tar -xf ./hello-world.tar -C hello-world
```
### Copy remote image to the disk in the form of OCI image layout (Option 2)
If users already store the images in a remote registry, there are tools to copy the remote images to the disk in the form of OCI image layout. For example,
```shell
oras cp localhost:5000/hello-world:v1 --to-oci-layout ./hello-world
```
> NOTE: use flag `-r` to copy both an image and its referrers, for example signatures
## User Scenario
### Sign and verify OCI images on local disk
Pre-conditaion:
- Save the OCI images on local disk as OCI image layout directory
- The flag `--oci-layout` and `--scope` are experiemntal, make sure to set NOTATION_EXPERIMENTAL varaible
```shell
export NOTATION_EXPERIMENTAL=1
```
Steps:
1. Sign the image as OCI image layout on disk
```shell
notation cert generate-test wabbit-networks.io --default
notation sign --oci-layout ./hello-world:v1
```
> NOTE: signatures are stored in the same OCI image layout directory, and associated with OCI image.
2. List signatures associated to the image
```shell
notation list --oci-layout ./hello-world:v1
```
Output example:
```
./hello-world@sha256:a08753c0c7bcdaaf5c2fdb375f68e860c34bffb146368982c201d41769e1763c
└── application/vnd.cncf.notary.signature
└── sha256:0283100f21395c4422eeea8925a0677a46704c054d7eca04d5f47991b3dd9c19
```
3. Verify the image against signatures.
```shell
notation verify --oci-layout ./hello-world:v1 --scope "local/hello-world"
```
> NOTE: The flag `--scope` is experiemntal, which is used to specify which trust policy is used for verification. The value is the value set for property `registryScopes`.
An example of trustpolicy.json
```jsonc
{
"version": "1.0",
"trustPolicies": [
{
"name": "local-images-policy",
"registryScopes": [ "local/hello-world" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:wabbit-networks.io" ],
"trustedIdentities": [
"*"
]
}
]
}
```
### Sign OCI images on local disk, push OCI images to a remote registry and verify OCI images stored in the registry
Pre-conditaion:
- Save the OCI images on local disk as OCI image layout directory
- Download latest version of [ORAS CLI](https://github.com/oras-project/oras/releases)
- The flag `--oci-layout` and `--scope` are experiemntal, make sure to set NOTATION_EXPERIMENTAL varaible
```shell
export NOTATION_EXPERIMENTAL=1
```
Steps:
1. Sign the image as OCI image layout on local disk
```shell
notation cert generate-test wabbit-networks.io --default
notation sign --oci-layout ./hello-world:v1
```
2. List signatures associated to the image
```shell
notation list --oci-layout ./hello-world:v1
```
3. (Optional) Verify the image against signatures locally.
```shell
notation verify --oci-layout ./hello-world:v1 --scope "localhost:5000/hello-world"
```
4. Push the image from local to a remote registry
```shell
oras cp ./hello-world:v1 --from-oci-layout -r localhost:5000/hello-world:v1
```
> NOTE: Make sure flag `-r` is used, so that the signatures will be copied together with the image.
5. List signatures from remote registry
```shell
notation list localhost:5000/hello-world:v1
```
You should see the signatures pushed from local to remote as well.
6. Verify the image in remote registry before deployed in to the system.
```shell
notation verify localhost:5000/hello-world:v1
```