Quay OCI-based Artifacts Repository

Quay can be used to store OCI-based artifacts like Helm charts, encrypted container images, signed images, zstd compressed images, etc.

Configuring allowed OCI artifact types

Some of the OCI artifacts that we will be using in the following sections are not allowed by default in Quay. For example, encrypted container images are not allowed by default (at least at the time of writing). To upload encrypted images to Quay, follow these steps to configure the ALLOWED_OCI_ARTIFACT_TYPES property:

  • Open a browser window and log in to the Red Hat OpenShift Container Platform web console.

  • Click on Operators, then Installed Operators.

  • Select quay-workshop project and click on Quay Registry. Then click on our registry.

quay registry
  • Click the Config Bundle Secret secret (registry-config-bundle-*).

config bundle secret
  • In the Actions drop-down menu, select Edit Secret.

  • Add the following into the Value text field, and click Save.

ALLOWED_OCI_ARTIFACT_TYPES:
  application/vnd.oci.image.config.v1+json:
  - application/vnd.dev.cosign.simplesigning.v1+json
  - application/vnd.oci.image.layer.v1.tar+gzip+encrypted
  application/vnd.cncf.helm.config.v1+json:
  - application/tar+gzip
valuesecret

The registry-quay-config-editor-* and registry-quay-app-* pods will be restarted automatically with the new configuration.

Helm charts

  • Login to the Quay registry with helm.

helm registry login ${QUAY_HOSTNAME}
  • Pull a chart.

  • Push the chart into the Quay repository.

helm push quarkus-0.0.3.tgz oci://${QUAY_HOSTNAME}/olleb/helm
  • Open the Quay Dashboard and navigate to the olleb/helm/quarkus repository. Then, go to Tags.

helmrepo

The Helm chart is published to Quay as an OCI image.

  • The Helm chart can now be installed directly from the repository.

helm install quarkus oci://${QUAY_HOSTNAME}/olleb/helm/quarkus --version=0.0.3

Signed container images

Image signing ensures the integrity of our image deployments. Quay will store the signature as an OCI artifact.

This section shows how to sign and store image artifacts in a Quay registry, and how to use Quay to store OCI artifacts like signatures. However, it is important to note that this is not a comprehensive security guide or a registry hardening guide. Before signing images, we need to decide whether the source registry is trusted or not. Additionally, we need to determine whether signing an image after uploading it into the registry is sufficient or if we prefer to sign it before pushing it.

Signed container images with cosign

  • Generate the key pair.

cosign generate-key-pair
  • Sign an image and pull it to Quay.

# Pull the image
podman pull quay.io/centos7/httpd-24-centos7:latest

# Tag and push the image
podman tag quay.io/centos7/httpd-24-centos7:latest ${QUAY_HOSTNAME}/olleb/httpd-24:latest
podman push ${QUAY_HOSTNAME}/olleb/httpd-24:latest

# Login
## update the config.json auth file
podman login --authfile ~/.docker/config.json ${QUAY_HOSTNAME}

## login with cosign, will rely on the updated config.json
cosign login ${QUAY_HOSTNAME} -u <USER>

# Sign and push the signature
cosign sign --key cosign.key ${QUAY_HOSTNAME}/olleb/httpd-24:latest
Strictly speaking, signing an image by referencing it using a tag is not secure, as it can lead to signing a different image than the intended one. The correct way to sign an image is by using the image digest @sha256:…​ The steps will be updated in the future before cosign drops that functionality.
  • Navigate to the Quay Registry Dashboard, olleb/httpd-24 repository.

  • Click Tags.

You should see the signature stored in the repository.

signature

Signed container images with PGP (RFC4880)

  • Generate the PGP keys.

gpg --full-generate-key
<..>
Real name: Angel
Email address: [email protected]
Comment:
You selected this USER-ID:
    "Angel <[email protected]>"
<..>
  • Copy, sign the image and push it to Quay.

skopeo copy --sign-by [email protected] docker://quay.io/centos7/nginx-116-centos7:latest docker://${QUAY_HOSTNAME}/olleb/nginx-116:latest

The signature will be stored in our sigstore ~/.local/share/containers/sigstore/olleb/nginx-116-centos7@sha256=<SHA>/signature-1

The signature can be verified with:

gpg --verify ~/.local/share/containers/sigstore/olleb/nginx-116-centos7@sha256=<SHA>/signature-1

Encrypted container images

An image can be encrypted with a key or multiple keys. Also, we can encrypt the full image layers or some specific layer instead; also, we can encrypt all image layers or only some layer. In any case, we can store the container image into Quay.

The encrypted images are used when we want to protect private and sensitive content from our images, for example, in case of our registry is compromised.

Usually the image decrypting key is stored in a secret into our OCP cluster master node.

Encrypted container images with JSON Web Encryption (JWE) (RFC7516)

  • Generate the encryption RSA keys with openssl.

# private key
openssl genrsa --out private-key.pem 2048

# public key
openssl rsa -in private-key.pem -pubout -out public-key.pem
  • Copy the image that we want to encrypt.

skopeo copy docker://quay.io/centos7/httpd-24-centos7:latest oci:local-httpd24:latest
  • Encrypt the image.

skopeo copy --encryption-key jwe:public-key.pem oci:local-httpd24:latest oci:local-httpd24-encrypted:latest
  • Push the image to Quay.

skopeo copy oci:local-httpd24-encrypted:latest docker://${QUAY_HOSTNAME}/olleb/httpd-24-encrypted:latest
  • Navigate to the Quay Registry Dashboard, olleb/httpd-24-encrypted repository.

  • Click on Tags.

We will see our encrypted image stored in it.

Encrypted container images with PGP (RFC4880)

  • Generate the PGP keys.

gpg --full-generate-key
<..>
Real name: Angel
Email address: [email protected]
Comment:
You selected this USER-ID:
    "Angel <[email protected]>"
<..>
  • Copy the image that we want to encrypt.

skopeo copy docker://quay.io/centos7/nginx-116-centos7:latest oci:local-nginx-116:latest
  • Encrypt the image.

skopeo copy --encryption-key pgp:[email protected] oci:local-nginx-116:latest oci:local-nginx-116-encrypted:latest
  • Push the image to Quay.

skopeo copy oci:local-nginx-116-encrypted:latest docker://${QUAY_HOSTNAME}/olleb/nginx-116-encrypted:latest
  • Navigate to the Quay Registry Dashboard, olleb/nginx-116-encrypted repository.

  • Click Tags.

We will see our encrypted image stored in it.