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
- Complete the instructions in Getting started with IBM Cloud Container Registry.
- Ensure that you have the most recent version of the
container-registry
CLI plug-in for the IBM Cloud CLI, see Updating thecontainer-registry
CLI plug-in. - Ensure that you have a private namespace to push your encrypted image to, see Set up a namespace.
- Install Buildah version 1.15, or later, so that you can build encrypted images. Buildah works in the Linux® environment only. As an alternative to Linux®, you can use a virtual machine or Docker image to run Buildah to build images.
- Install Podman.
Create the public-private key pair
Create a public-private key pair by using OpenSSL commands.
-
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>
-
Use OpenSSL to create a private key, where
<user>
is the name for your key's identity:openssl genrsa --out <user>Private.pem
-
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.
-
List the keys to ensure that they are created:
ls -l
-
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..
-
Go to the directory where you store your apps, for example,
<my_app>
.cd <my_app>
-
Create the Dockerfile by running the following command:
cat << EOF >> Dockerfile FROM nginx:latest RUN echo "some secret" > /secret-file EOF
-
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. -
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.
-
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.
-
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>
-
(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
-
Use Buildah to pull the image with the decryption key, where
<user_keys>/<user>Private.pem
is the decryption key andus.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.
-
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.