Introduction
This article describes how to build and deploy a Hashicorp Vault server within an enclave using Fortanix Confidential Computing Manager (CCM) and Fortanix Enclave OS.
Steps
Authenticate to Fortanix CCM
Before you can issue any requests, you first need to authenticate to Fortanix CCM using the following commands:
cpath=$(mktemp -p "/tmp" -t "fortanix_ccm_cookie.XXXXX")
curl -u : -c $cpath -X POST https://ccm.fortanix.com/v1/sys/auth
where and need to be replaced with the email address and password of your Fortanix CCM account.
NOTE
Authentication session tokens are short-lived. If you ever get the response {"message":"Forbidden","code":"FORBIDDEN"} you can run the following command to refresh the session token.
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -X POST https://ccm.fortanix.com/v1/sys/session/refresh
Select an Account using an API Call
Once you have successfully authenticated to Fortanix CCM, you need to select an account. First, you can list all accounts available using the following command:
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" https://ccm.fortanix.com/v1/accounts
This command will return a JSON string of the following form:
{"name":"My account","acct_id":"26eaa328-5eb4-41c7-b09b-8a3e0a0f65c7", ...}, ...
To select an account, you need to copy the account ID of the account you are interested in (the string 26eaa328-5eb4-41c7-b09b-8a3e0a0f65c7
in the example above), let us call it , and run:
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -X POST https://ccm.fortanix.com/v1/sys/session/select_account/
Create an Application using an API Call
Next, to create a new application, create a file called app.json
whose contents are shown below. Make sure to replace the output_image_name
with your private registry.
{
"name":"Vault demo server",
"description":"A hashicorp vault server demo",
"input_image_name":"vault",
"output_image_name":"fortanix-private/python-flask-nitro",
"default_build_settings": {
"sgx": {},
"nitro_enclaves": {
"cpu_count": 2,
"mem_size": 1024,
"enable_overlay_filesystem_persistence": true
}
},
"group_id": "a8e8395e-096d-4eb8-9017-2098f2ab8327",
"allowed_domains": [],
"advanced_settings": {
"entrypoint": [],
"manifestEnv": [],
"encryptedDirs": [],
"rw_dirs": ["/vault", "/home/vault"],
"certificate": {}
},
"custom_metadata": {
"app_type": "ENCLAVE_OS"
}
}
NOTE
Since the application needs to write to paths "
/vault
" and "/home/vault
", these paths need to be marked as read/write (rw_dirs
) because by default Enclave OS sets these paths to read-only.
Then, create an application using the following API call:
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -H "Content-Type: application/json" -d @app.json -X POST https://ccm.fortanix.com/v1/apps
This will print information about the newly created application including its :
{"name":"Vault demo server","app_id":"cc386097-dcf7-4813-880a-ddacdafb48a2",...}
Create an Image using an API Call
Once the application has been created, you can create an image similarly using the following steps. First, create a file called build.json
as shown below. Replace with the ID of your newly created application. The and are the credentials of the registry that you want the converted image to be stored at. This was specified above as output_image_name
.
{
"app_id":"",
"input_docker_version":"latest",
"output_docker_version":"latest",
"outputAuthConfig":{
"username":"",
"password":""
}
}
NOTE
See the Fortanix CCM Quickstart guide on how to set up registry credentials to avoid including credentials in this file.
Now you can create the image using the following command:
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -H "Content-Type: application/json" -d @build.json -X POST https://ccm.fortanix.com/v1/builds/convert-app
This returns the output that shows the (f0d815b6-9520-4ce4-b4f4-6a82a718bb7e
in this example), among other information:
{"build_name":"/vault-sgx:latest","pending_task_id":"f0d815b6-9520-4ce4-b4f4-6a82a718bb7e",...}
Finally, you can approve the image using its and the following command:
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -H "Content-Type: application/json" -d '{"status":"APPROVED"}' -X PATCH https://ccm.fortanix.com/v1/tasks/
Run the Application
Whether you chose to create your application using the UI or the API option, you should now have converted and whitelisted an application image and can run the application on an SGX compute node. Depending on the node agent attestation type, run the application using the following commands:
docker run --privileged --volume /dev:/dev -v /var/run/aesmd/aesm.socket:/var/run/aesmd/aesm.socket -e 'VAULT_LOCAL_CONFIG={"listener": {"tcp": {"address": "127.0.0.1:8000", "tls_disable": true}}, "disable_mlock": true}' -e 'VAULT_API_ADDR=http://127.0.0.1:8000' -e SKIP_SETCAP=1 --network=host /vault-sgx
Where,
8000
is the port on which Hashicorp Vault listens to./vault-sgx:latest
is the converted app.SKIP_SETCAP
environment variable: Skip the setcap call. Vault does this so it can use mlock for pages that contain secret information, so they do not get swapped to disk (where it is easier for an attacker to get them than memory). We skip these for multiple reasons: setcap probably will not work in enclave OS, mlock for this purpose is irrelevant in an enclave OS app (since all memory is protected, even when swapped out of EPC), and the additional forks are slow on SGX.Use "
disable_mlock": true
in theVAULT_LOCAL_CONFIG
and do not use--cap-add=IPC_LOCK
.
To verify that your vault server is running, use
curl http://127.0.0.1:8000/v1/sys/init
which should print:
"{"initialized":true}"