Signatures on container images are crucial for security, authenticity, and trust in containerized environments. They play a significant role in ensuring that the images used in production or development environments are secure and have not been tampered with. Here are the key reasons for using signatures on container images:
- Integrity Verification and Preventing Unauthorized Modifications
- Authentication of the Image Source.
By verifying the signature, users can ensure that the image's content matches what the author originally intended. Without a signature, an image could be maliciously modified, and those changes would be undetectable. Signing ensures that any alteration of the image after it was signed would invalidate the signature.
A signature provides a way to verify the identity of the image's creator or publisher. Users can confirm that the image indeed comes from a trusted source and is not a forgery
Prerequisites
Before you start, ensure you have
- Access to registry where you want to push the signed images.
- A RHEL based system with podman installed,
Create GPG key to sign the container image
-
Create key and list it.
gpg --full-gen-key
gpg --list-keys
-
Then export the gpg key to a file. In place of kay@example.com you have to provide the owner name which you given while creating the key.
mkdir /root/signing-container-images;cd signing-container-images
gpg --output ./mykey.gpg --armor --export kay@example.com
cat ./mykey.gpg
Now build the image
gpg --full-gen-key
gpg --list-keys
mkdir /root/signing-container-images;cd signing-container-images
gpg --output ./mykey.gpg --armor --export kay@example.com
cat ./mykey.gpg
Clone the repository from git and then build the image. That containerfile is using a redhat ubi image which can be accessed from redhat registry wihtout any authentication
git clone https://github.com/kaybee-singh/signing-container-images /root/signing-container-images
cd /root/signing-container-images
podman build -t webs:1 -f containerfile .
Tag and push to the registry
Tag image by using podman, you have to replace the quay-all.example.com with your registry URL
podman tag localhost/webs:1 quay-all.example.com/quayuser/a/webs:1
podman login quay-all.example.com --tls-verify=false
podman push quay-all.example.com/quayuser/a/webs:1 --tls-verify=false
Configure web server to host the signature files
In this example we are configuring the web server on the same system where our registry is configured, as our registry is utilizing the 80 and 443 port we are configuring the web server on 90 port.
yum install httpd -y
sed -i 's/^Listen 80$/Listen 90/' /etc/httpd/conf/httpd.conf
systemctl enable httpd --now
firewall-cmd --add-port 90/tcp --permanent
firewall-cmd --reload
setenforc 0
Copy the signature directory to webserver document root.
cp -R /var/lib/containers/sigstore/quayuser /var/www/html
ls -l /var/www/html/
total 3
drwxr-xr-x 3 root root 15 Aug 30 08:35 quayuser
Configure podman to verify signature while pulling the images
On the system where we want to pull the images we have to modify policy.json file and also create a regisrty.yaml file or we can modify the existing default.yaml file. GPG Public key should also be placed on that system to verify the images.
- We are modifiying the existing default.yaml file.
# cat /etc/containers/registries.d/default.yaml docker: quay-all.example.com: sigstore: http://192.168.0.10:90
-
Configure policy.json file. Type reject means if an image is pulled and does not meet any specific policies defined under "transports", it will be rejected
# cat /etc/containers/policy.json { "default": [ { "type": "reject" } ], "transports": { "docker": { "quay-all.example.com": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/etc/pki/kay-pub.asc" } ] } } }
-
Copy the GPG public key to the above specified keyPath. If you have generated the gpgkey on a different system and then signed the image then you may have to scp the gpgkey to the system where you are pulling the image.
gpg --export kay@example.com > kay-pub.asc scp kay-pub.asc root@podman-client:/etc/pki/kay-pub.asc
Try to pull the image and verify if signature verification works.
podman pull quay-all.example.com/quayuser/a/webs:1 --tls-verify=false
Trying to pull quay-all.example.com/quayuser/a/realtest1:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob fb875368e78f skipped: already exists
Copying blob b18b624f97a4 skipped: already exists
Copying blob 9d1dcd11a3fd skipped: already exists
Copying config a8c7f5a20e done |
Writing manifest to image destination
Storing signatures
a8c7f5a20e6e2bcafafd520bbec6e6c2ff6032e7af5a75c36244ba32bba59ac3