1.0 Introduction
This article describes the steps to integrate the Docker Notary client with the Fortanix PKCS#11 library to use Fortanix-Data-Security-Manager (DSM) as a signer. The Fortanix DSM stores the root key, which is an EC key pair in the case of Notary.
1.1 Prerequisites
Ensure the following:
The system should have an open SSL with PKCS#11 enabled engine.
The PKCS#11 tool must be installed.
Run the following command to update the PKCS#11 tool:
apt update opensc
Run the following command to install the PKCS#11 tool:
apt install opensc
Run the following command to update the PKCS#11 tool, if using yum as package manager:
yum update opensc
Run the following command to install the PKCS#11 tool, if using yum as package manager:
yum install opensc
Ensure that you have created an application and a group in the Fortanix DSM. Refer to User's Guide: Getting Started with Fortanix Data Security Manager – UI to know the steps.
2.0 Create OpenSSL Configuration File
Create an OpenSSL configuration file at /root/.docker/certs/openssl.cnf
directory with the following content:
openssl_conf = openssl_def
[openssl_def]
engines = engine_section
[req]
distinguished_name = req_distinguished_name
[req_distinguished_name]
#empty.
[engine_section]
pkcs11 = pkcs11_section
[pkcs11_section]
engine_id = pkcs11
dynamic_path = /usr/lib/engines/engine_pkcs11.so
MODULE_PATH = /opt/fortanix/fortanix_pkcs11.so
PIN = file:///etc/fortanix/pkcs11.conf
init = 0
3.0 Create SymLink to fortanix PKCS#11 Library
Create a symlink for Fortanix PKCS#11 library to Notary at the required location. Run the following command:
sudo ln -s fortanix_pkcs11.so /usr/lib/libykcs11.so
sudo ln -s fortanix_pkcs11.so /usr/lib64/libykcs11.so
4.0 Create Notary Root Key
The Docker Notary root key and certificate are created using the PKCS#11 tool and library and these are stored in the Fortanix DSM. These keys are never exported out of Fortanix DSM and are used as the default root of trust for all the Docker repositories.
Perform the following steps:
Create a PKCS#11 configuration file with the following content at the default location,
/etc/fortanix/pkcs11.conf
:api_key = "<API Key>" api_endpoint = "https://<FORTANIX_DSM_URL>" [log] system = true file = "/path/to/log/file"
Where,
The value for api_key is the copied API key from Fortanix DSM.
The value for api_endpoint is the Fortanix DSM cluster endpoint.
NOTE
You can also use
FORTANIX_PKCS11_CONFIG_PATH
environment variable to set a custom configuration path.Run the following command to create the root key:
$ pkcs11-tool --module /opt/fortanix/fortanix_pkcs11.so --login --pin file:///etc/fortanix/pkcs11.conf -k --label "Notary Root Key" --key-type EC:prime256v1 Using slot 0 with a present token (0x0) Key pair generated: Private Key Object; EC label: test EC Key ID: 6866774f524a436c7a2f72614f6a374c394e7063376a664c4c303d Usage: sign, derive Public Key Object; EC EC_POINT 256 bits EC_POINT: 04410406ca6ddfafb9c3...f0a944bbcdbb3d746a315b08853ae1bc50416fa93c98fae68cb d0 EC_PARAMS: 06082a8648ce3d030107 label: test EC Key ID: 6866774f524a436c7a2f72614f6a374c394e7063376a664c4c303d Usage: verify
NOTE
Note down the value for Private Key Object ID in the output above.
Run the following command to create the self -signed certificate for the root key:
$ openssl req -config /root/.docker/certs/openssl.cnf -engine pkcs11 - keyform engine -new -key 1:<PRIV-KEY-ID> -nodes -days 365 -x509 -sha256 - out /root/.docker/certs/root.crt -subj "/CN=root" Import the certificate into Fortanix DSM: $ openssl x509 -inform pem -outform der -in /root/.docker/certs/root.crt - out /root/.docker/certs/root-crt.der $ pkcs11-tool --module /opt/fortanix/fortanix_pkcs11.so --login --pin file:///etc/fortanix/pkcs11.conf --write-object /root/.docker/certs/root- crt.der --type cert --id <PRIV_KEY-ID> --label "Notary Root Key"
For more information on the configuration file, refer to the Configuration File Format.
NOTE
Ensure to enter the value for subject as CN=root for Notary to identify the self-signed certificate created from the root key.
Run the following command to upload the certificate to Fortanix DSM:
$ pkcs11-tool --module /opt/fortanix/fortanix_pkcs11.so --login –pin file:///etc/fortanix/pkcs11.conf --write-object /root/.docker/certs/root-crt.der --type cert --id --label "Notary Root Key"
5.0 Publish Root Key and Certificate
Perform the following steps to publish the root key and certificate using the Fortanix DSM UI:
Log in to the Fortanix DSM UI.
Navigate to Security Objects tab and search for the key or certificate that you want to publish. Ensure to note the name of the key or certificate that you are publishing.
On the detailed view page, click the Public key published toggle button to publish the key.
This action might require approval from the approvers, refer to Section: Quorum Approval Policy.
Selecting this toggle button, displays the URL of the API endpoint. You can copy this endpoint using the copy icon.
In case you want to view the older version of the key or certificate, select the check box for List previous version and click the Save button.Run the following command to list all the security objects in the Fortanix DSM along with their CKA_ID value:
pkcs11-tool --module ~/path/to/pkcs11/library.so --login --pin <API_KEY> -O
The output of this command lists all the objects in the account, along with all published root keys and certificates. Note the CKA_ID value mentioned against the published keys and certificates.
NOTE
Ensure that the CKA_IDs is in HEX string format only.
Add information about the root keys and certificates in the PKCS#11 configuration file in the following format:
api_key = "..."api_key = "..." api_endpoint = "..." [log] system = true file = "/path/to/log/file" [[pub_obj_info]] account_id = "<DSM_ACCOUNT_ID>" key_name = "<PUBLIC_KEY_NAME> pkcs11_id = "<CKA_ID>" [[pub_obj_info]] account_id = "<DSM_ACCOUNT_ID>" key_name = "<CERTIFICATE_NAME>" pkcs11_id = "<CKA_ID>"
NOTE
You can find the values for the following:
account_id
- this value is available in the Settings tab → Account Settings page.key_name
- this value is copied in Step 2.pkcs11_id
– this value is copied while creating the root key in Step 4.
6.0 Verification
Run the following command to list all the Docker Notary keys:
notary key list
The following is the sample output of the above command:
ROLE GUN KEY ID LOCATION
root e38202b6664ad57...5579707260b1b yubikey
NOTE
The location of the key is always displayed as yubikey in the CLI, however it is also reflected in the Fortanix DSM.
After the integration operation is successfully done, you can run the Docker trust command and Notary operations using the keys stored in Fortanix DSM.
7.0 Sign the Image with Notary
Perform the following steps to sign the image with Notary:
Run the following command to export the PKCS#11 configuration file path:
export FORTANIX_PKCS11_CONFIG_PATH=/home/ubuntu/pkcs11.cnf
Run the following command to create the certificate for the repository:
openssl req -engine pkcs11 -keyform engine -new -key 1:<PRIV-KEY-ID> -nodes -sha256 -out <path to repo csr file> -subj "/CN=<docker repo>”
NOTE
If you encounter any error, contact the Fortanix Support team for troubleshooting steps.
Run the following command to create local key pair:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout <path to ca.key> -out <path to ca.pem>
Run the following command to sign the Certificate Signing Request (CSR):
openssl x509 -req -in <path to repo csr file> -CA <path to ca.pem> -CAkey <path to ca.key> -CAcreateserial -out <path to repo.pem> -days 375 -sha256
Run the following command to initialize the repository in Notary:
notary -c ~/.notary/config.json -D init <docker repo> -s https://notary.docker.io --publish --rootcert <path to repo.pem>
Run the following command to push the snapshot key to Notary servers:
notary -s https://notary.docker.io -d ~/.docker/trust key rotate <docker repo> snapshot --server-managed
Run the following commands to get the size and bash:
docker manifest inspect <docker repo> -v | jq .Descriptor.size docker manifest inspect <docker repo> -v | jq .Descriptor.digest
Run the following command to create the signing key:
docker trust key generate <signing key>
NOTE
This command generates a key pair. The path to the public key file is mentioned at the end of the output. Note this public key path to use in the next step for
<path to the signing key>
.Run the following command to add the delegation role:
notary -s https://notary.docker.io -d ~/.docker/trust delegation add -p <docker repo> targets/<delegation role> --all-paths <path to the signing key>
Run the following command to sign the image:
notary -c ~/.notary/config.json -D addhash -p "<docker repo>" <tagname> <size> --sha256 <hash> -r targets/<delegation role>
Now this repository can be used when the docker content trust is enabled. Run the following command to set the value for
DOCKER_CONTENT_TRUST
environment variable to1
.export DOCKER_CONTENT_TRUST=1