Signing Images for Security

For compliance and security reasons, system administrators often want to deploy software into a production system only when they are satisfied that:

  • the software comes from a trusted source
  • the software has not been modified since it was published, compromising its integrity

To meet these requirements, you can sign images stored in Oracle Cloud Infrastructure Registry (also known as Container Registry). Signed images provide a way to verify both the source of an image and its integrity.

Container Registry enables users or systems to push images to the registry and then sign them using a master encryption key obtained from Oracle Cloud Infrastructure Vault, creating an image signature. An image signature associates a signed image with a particular master encryption key used to sign the image. An image can have multiple signatures, each created using a different master encryption key.

Users or systems pulling a signed image from Container Registry can be confident both that the source of the image is trusted, and that the image's integrity has not been compromised. To further enhance compliance and security, clients can be configured to only pull signed images from the registry.

At a high level, these are the steps to follow to store signed images in Container Registry:

  • Build the image on your own machine or in your CI/CD system.
  • Tag and push the image to Container Registry.
  • If you don't have access to a master encryption key in Oracle Cloud Infrastructure Vault, either obtain access to an existing key or create a new key.
  • Sign the image using the Container Registry CLI, creating an image signature that associates the image with the master encryption key and key version in the Vault service.

Signing an Image and Creating an Image Signature

Having built an image and pushed it to Container Registry, you can sign the image using a master encryption key obtained from Oracle Cloud Infrastructure Vault, creating an image signature. Note that an image signature is associated with an image's OCID, making it specific to a particular push of the image.

To sign an image and create an image signature:

  1. Build an image on your own machine or in your CI/CD system (for example, using the docker build command).
  2. Push the image to Container Registry. Follow the instructions in Pushing Images Using the Docker CLI to:
    1. Log in to Container Registry using the docker login command.
    2. Tag the image you want to push using docker tag command. For example:
      docker tag 8e0506e14874 phx.ocir.io/ansh81vru1zp/project01/acme-web-app:version2.0.test
    3. Push the image to Container Registry using the docker push command. For example:
      docker push phx.ocir.io/ansh81vru1zp/project01/acme-web-app:version2.0.test
  3. Obtain the OCID of the image, either using the Console (see Viewing Images and Image Details ), or using the CLI (use the oci artifacts container image list --compartment-id <compartment_ocid> --repository-name <repository-name> command).
  4. If you don't already have access to an RSA or ECDSA asymmetric key in Oracle Cloud Infrastructure Vault, either obtain access to an existing RSA or ECDSA asymmetric key or create a new master encryption key as an RSA or ECDSA asymmetric key (see To create a new master encryption key).

    Note that the use of AES symmetric keys to sign images is not supported. For more information about different key types, see Overview of Vault.

  5. Make a note of both the OCID of the master encryption key and the OCID of the key version stored in Oracle Cloud Infrastructure Vault. See To view key details.
  6. Sign the image you pushed to Container Registry using the master key and key version in the Vault service, creating an image signature, by entering:
    oci artifacts container image-signature sign-upload --compartment-id <compartment-ocid> --kms-key-id <key-ocid> --kms-key-version-id <key-version-ocid> --signing-algorithm <signing-algorithm> --image-id <image-ocid> --description <signature-description> --metadata <image-metadata-json>
    where:
    • --compartment-id <compartment-ocid> is the OCID of the compartment to which the image's repository belongs. For example, --compartment-id ocid1.compartment.oc1..aaaaaaaa23______smwa
    • --kms-key-id <key-ocid> is the OCID of the master encryption key to use to sign the image. For example, --kms-key-id ocid1.key.oc1.phx.bbqehaq3aadfa.abyh______qlj
    • --kms-key-version-id <key-version-ocid> is the OCID of the key version to use to sign the image. For example, --kms-key-version-id ocid1.keyversion.oc1.phx.0.bbqehaq3aadfa.acy6______mbb
    • --signing-algorithm <signing-algorithm> is one of the following algorithms to use to sign the image:

      • SHA_224_RSA_PKCS_PSS
      • SHA_256_RSA_PKCS_PSS
      • SHA_384_RSA_PKCS_PSS
      • SHA_512_RSA_PKCS_PSS
      • SHA_224_RSA_PKCS1_V1_5
      • SHA_256_RSA_PKCS1_V1_5
      • SHA_384_RSA_PKCS1_V1_5
      • SHA_512_RSA_PKCS1_V1_5
      • ECDSA_SHA_256
      • ECDSA_SHA_384
      • ECDSA_SHA_512

      The algorithm to choose depends on the type of the master encryption key. For RSA keys, supported signature schemes include PKCS #1 and RSASSA-PSS, along with different hashing algorithms. For ECDSA keys, ECDSA is the supported signature scheme with different hashing algorithms. For the latest list of supported algorithms, see Sign and the SignDataDetails resource in the Vault API documentation.

      For example, --signing-algorithm SHA_224_RSA_PKCS_PSS

    • --image-id <image-ocid> is the OCID of the image to sign . For example, --image-id ocid1.containerimage.oc1.phx.0.ansh81vru1zp.aaaaaaaalqzj______yks
    • --description <signature-description> is optional text of your choice to describe the image. The description is included as part of the signature, and is shown in the Console. For example, --description "Image for UAT testing"
    • --metadata <image-metadata-json> is optional information of your choice about the image, in a valid JSON format (alphanumeric characters only, with no whitespace or escape characters). For example, --metadata {"buildnumber":"8447"}

    For example:

    oci artifacts container image-signature sign-upload --compartment-id ocid1.compartment.oc1..aaaaaaaa23______smwa --kms-key-id ocid1.key.oc1.phx.bbqehaq3aadfa.abyh______qlj --kms-key-version-id ocid1.keyversion.oc1.phx.0.bbqehaq3aadfa.acy6______mbb --signing-algorithm SHA_224_RSA_PKCS_PSS --image-id ocid1.containerimage.oc1.phx.0.ansh81vru1zp.aaaaaaaalqzj______yks --description "Image for UAT testing" --metadata {"buildnumber": "8447"}

    The image you specified is now signed. When you view the list of images in a repository in the Console, the text "(Signed)" appears beside the image name.

Viewing Signed Images

You can use the Console to view the signed images in a repository.

To view signed images:

  1. In the Console, open the navigation menu and click Developer Services. Under Containers, click Container Registry.
  2. Choose the registry's region.
  3. Choose a Compartment you have permission to work in.
  4. Click the name of a repository containing signed images.

    The text "(Signed)" appears beside images that have been signed.

  5. (Optional) Click the name of a signed image, and display the Signatures tab to view the signature(s) created when the image was signed.

Working with Image Signatures

An image signature associates an image with the master key (obtained from the Vault service) that was used to sign the image. An image can have multiple signatures, each created using a different master encryption key.

Having signed an image in Container Registry and created an image signature, you can:

  • view details of the signature
  • verify the signature with the Vault service to confirm that the master encryption key used to sign the image is still valid and available
  • delete the signature to indicate that the image is no longer to be considered as trusted

To view, verify, or delete the signature(s) that was created when an image was signed:

  1. In the Console, open the navigation menu and click Developer Services. Under Containers, click Container Registry.
  2. Choose the registry's region.
  3. Choose a Compartment you have permission to work in.
  4. Click the name of the repository containing the signed image.

    The text "(Signed)" appears beside images that have been signed.

  5. Click the name of a signed image, and display the Signatures tab to view details of the signature(s) created when the image was signed:
    • Description: A description of the signature that was specified when the image was signed.
    • Status: The result of the last attempt to verify the image signature with the Vault service.
    • Date: When the image was signed and the image signature created.
  6. (Optional) To see the master key, key version, and signing algorithm for a particular signature, select View Key Details from the Actions menu beside the signature.
  7. (Optional) To verify a particular signature with the Vault service, select Verify Signature from the Actions menu beside the signature.

    The Vault service checks that the source of the image had access to a valid private key when they pushed the image, and that the image has not been modified since it was pushed. If both conditions are met, the signature is shown with a Verified status. Users or systems pulling the image from the registry can be confident both that the source of the image is trusted, and that the image's integrity has not been compromised.

    If image verification fails, check that you have access to the master key, and that it has not been deleted.

  8. (Optional) To delete a particular signature, select Delete Signature from the Actions menu beside the signature. The signature is deleted and no longer shown on the Signatures tab. If the image has no other signatures, the text "(Signed)" no longer appears beside the image name in the list of images in the repository.

Using the CLI

For information about using the CLI, see Command Line Interface (CLI). For a complete list of flags and options available for CLI commands, see the Command Line Reference.

To sign an image and create an image signature

oci artifacts container image-signature sign-upload --compartment-id <compartment-ocid> --kms-key-id <key-ocid> --kms-key-version-id <key-version-ocid> --signing-algorithm <signing-algorithm> --image-id <image-ocid> --description <signature-description> --metadata <image-metadata-json>
For example:
oci artifacts container image-signature sign-upload --compartment-id ocid1.compartment.oc1..aaaaaaaa23______smwa --kms-key-id ocid1.key.oc1.phx.bbqehaq3aadfa.abyh______qlj --kms-key-version-id ocid1.keyversion.oc1.phx.0.bbqehaq3aadfa.acy6______mbb --signing-algorithm SHA_224_RSA_PKCS_PSS --image-id ocid1.containerimage.oc1.phx.0.ansh81vru1zp.aaaaaaaalqzj______yks --description "Image for UAT testing" --metadata {"buildnumber": "8447"}

To verify a signed image using an image signature

oci artifacts container image-signature get-verify --compartment-id <compartment-ocid> --repo-name <repository-name> --image-digest <image-digest> --trusted-keys <key-ocid> --compartment-id-in-subtree true|false

For example:

oci artifacts container image-signature get-verify --compartment-id ocid1.compartment.oc1..aaaaaaaa23______smwa --repo-name project01/acme-web-app --image-digest sha256:da1f_____31fd --trusted-keys ocid1.key.oc1.phx.bbqehaq3aadfa.abyh______qlj --compartment-id-in-subtree false