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
# If we already signed in with podman or docker, the password parameter is not required, as it will use config.json file
./cosign login ${QUAY_HOSTNAME} -u <USER> -p <PASSWORD>

# Sign and push the signature
./cosign sign --key cosign.key ${QUAY_HOSTNAME}/olleb/httpd-24:latest
  • 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

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 on Tags.

We will see our encrypted image stored in it.