IBM Cloud Docs
Encrypting images for content confidentiality in Container Registry

Encrypting images for content confidentiality in Container Registry

You can protect the confidentiality of your IBM Cloud® Container Registry images, and ensure that hosts that aren't trusted can't run the images.

Create an encrypted image so that people without the private keyAn algorithmic pattern used to encrypt messages that only the corresponding public key can decrypt. The private key is also used to decrypt messages that were encrypted by the corresponding public key. The private key is kept on the user system and is protected by a password. can't access the content. Create the encrypted image by using an RSA public-private key pair to encrypt and decrypt the image. A public key is not a secret and anyone can use it to encrypt an image. A private key is a secret, and only users that have that private key can use it to decrypt the image.

Encryption is supported in IBM Cloud Container Registry and complies with the following standards:

For more information about encrypting images, see Encrypted container images for container image security at rest and Advancing image security and compliance through Container Image Encryption.

Before you begin

Create the public-private key pair

Create a public-private key pair by using OpenSSL commands.

  1. Create a work directory, for example, <user_keys>, in which to store the keys and change to that directory:

    mkdir <user_keys>; cd <user_keys>
    
  2. Use OpenSSL to create a private key, where <user> is the name for your key's identity:

    openssl genrsa --out <user>Private.pem
    
  3. Create a public key:

    openssl rsa -in <user>Private.pem -pubout -out <user>Pub.pem
    

    To use the private key in production, you must safely store and protect the private key in a suitable store. You might also want to manage the public key in the same way. For more information, see Storing keys.

  4. List the keys to ensure that they are created:

    ls -l
    
  5. To use this key pair to encrypt images, display the public key by running the following cat command:

    cat <user>Pub.pem
    

    You get a response similar to the following output:

    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8Ny7dCWQ8Pdq1ddYSwk
    QOCB3lUEZVEyj9StX3jnISF/rxIsUZzJfbOrQN0fGkm+1sCCtltgQdztTjito8Fh
    DGflqQBSmV40XP3iZnNUJDrHuAol463Z/BuxxFXL3ry6rTosLGfrRwdQjxp8RSsn
    WyIIO2rmcqXZYe4SCtiMjMejLlTIDWLIMdYL3d6hA4DpgDLoh6EPmhKMVVwRt5b0
    ew5eMLcDuq6ButOM5yv4zYVHNrajY41NK+abSlFb6wzMg2AUDiC/MxV1LRq6mpyZ
    GJllx3LS1M1j7fDO3pmh/M0X7yD/4RgHwFaW4/4CQBw3fyxrOv0pZzZay+o
    -----END PUBLIC KEY-----
    

Encrypt the image

Encrypt the image by using the public key and then build a container image by using a DockerfileA text file that contains instructions to build a Docker image..

  1. Go to the directory where you store your apps, for example, <my_app>.

    cd <my_app>
    
  2. Create the Dockerfile by running the following command:

    cat << EOF >> Dockerfile
    FROM nginx:latest
    RUN echo "some secret" > /secret-file
    EOF
    
  3. Use Buildah to create an unencrypted image by running the following command, where <namespace> is your namespace:

    buildah bud -t us.icr.io/<namespace>/<my_app> .
    

    us.icr.io/<namespace>/<my_app> is committed to the local image store.

  4. Encrypt the image by using the public key and upload the image to the registry by running the following commands and by specifying the JSON Web Encryption (jwe) protocol to encrypt the image, where <user_keys>/<user>Pub.pem is the encryption key.

    buildah push --encryption-key jwe:..<user_keys>/<user>Pub.pem us.icr.io/<namespace>/<my_app>
    

    Buildah version 1.15, or later, uses Docker’s login credentials to authenticate. If these credentials don't work or you want to use an API keyA unique code that is used to authenticate and authorize API requests. The code is passed to an API to identify the calling application or user and to track and control how the API is used., you can supply the —-creds <user_name> option, where <user_name> is the username. If you use the —-creds <user_name> the option, when requested, type in the password of the registry credential.

    You get a response that informs you that the manifest is written to the image destination, which is the registry.

  5. Check in your registry to make sure that the image is there.

Pull and decrypt the image

Pull the image from the registry and decrypt it by using the private key.

  1. To ensure that you are pulling from the registry and that you are not using the local cache, remove the image locally:

    buildah rmi -f us.icr.io/<namespace>/<my_app>
    
  2. (Optional) You can try to pull the image without providing the decryption key to confirm that the image can't be decrypted:

    buildah pull us.icr.io/<namespace>/<my_app>
    

    The output contains a message similar to the following message:

    ...<truncated>...
    Error decrypting layer sha256:ab4ea03582e08a8e8fc35b778cc6f1a1fa797469fa9cc61cee85f703b316bb12: missing private key needed for decryption
    ERRO exit status 125
    
  3. Use Buildah to pull the image with the decryption key, where <user_keys>/<user>Private.pem is the decryption key and us.icr.io/<namespace>/<my_app> is the registry:

    buildah pull --decryption-key ../<user_keys>/<user>Private.pem us.icr.io/<namespace>/<my_app>
    

    The encrypted image is retrieved from the registry, decrypted, and stored in the local image store.

  4. Confirm that the image is stored by running Podman:

    podman run -it us.icr.io/<namespace>/<my_app> /bin/bash
    

Storing keys

To use the private key in production, you must safely store and protect the private key. You might also want to manage the public key in the same way to control who can build images. You can use IBM Key Protect to store and protect your keys.

IBM Key Protect stores symmetric keys rather than the asymmetric PKI keys that are used for image encryption. You can add your keys separately as two IBM Key Protect standard keys by using the dashboard, CLI, or API. IBM Key Protect requires that only Base64 data is imported. To obtain pure Base64 data, you can encode the PEM files by running "openssl enc -base64 -A -in <user>Private.pem -out <user>Private.b64" before you load the Base64 content, and reverse this action to obtain the usable key again by running "openssl enc -base64 -A -d -in <user>Private..b64 -out <user>Private.pem".

For more information about how to use IBM Key Protect to store and protect your keys, see Bringing your encryption keys to the cloud and Importing your own keys.

As an alternative, you can protect your keys in your own store by using an IBM Key Protect root key to wrap them. This action means that you must unwrap them again by using IBM Key Protect and the valid root key.

For example, to wrap keys by using the CLI, run the command "ibmcloud kp key wrap <root_key_id> -p <base64 encoded image key>" and to unwrap keys, run the command "ibmcloud kp key unwrap <root_key_id> -p <base64 cyphertext>, where <root_key_id> is the ID of the root key that you are using.

For more information about how you can protect your keys in your own store by using an IBM Key Protect root key to wrap them, see Wrapping keys.

Encrypted images are not scanned by Vulnerability Advisor.

Next steps

Run your encrypted image in a Red Hat® OpenShift® on IBM Cloud® cluster by using the Image Key Synchronizer cluster add-on.