Cluster Deployment Key Protection - Non-SGX

1.0 Introduction

This article describes the process to protect the Cluster Master Key (CMK) using another key, the Cluster Deployment Key (CDK) which is stored in an external HSM when Fortanix DSM is deployed on non-SGX platforms such as AWS.

2.0 Overview

Fortanix DSM generates a CMK during cluster creation. All data that the Fortanix DSM stores in its database is protected by keys derived from the CMK. When a node joins the cluster, it receives the CMK from its peers and then wraps it with the Platform Key before writing to the database. This Platform Key is provided either by SGX or by a Kubernetes secret for non-SGX.

For SGX platforms, the CMK is protected using the keys built into the CPU, such as the SGX sealing key, and the SGX attestation key. But for non-SGX platforms, CMK does not get the same protection. So, for non-SGX platforms, you can opt-in for the CMK protection and enable it during cluster creation so that  Fortanix DSM derives the CMK from another key, the CDK, stored in an external HSM which can either be a Fortanix DSM cluster, or a PKCS#11 HSM connected through the HSM Gateway. The CMK is derived from two pieces of information: the CDK, generated by the external HSM, and the Seed, generated by the Fortanix DSM. In this case, the CMK is not written to the database. Instead, nodes exchange the data (ID of CDK, seed), and wrap this with the Platform key before persisting it. On key rotations, both a new CDK and seed are generated, and the (ID of CDK, seed) pair is shared between the nodes.

The HSM configuration, including the URL, slot, PIN, and/or API key, is always stored in a Kubernetes secret.

3.0 Configuration Format

The configuration format is a JSON object with the following fields:

  • kind: (required) Enter either "Fortanix", "Ncipher", or "Safenet".
  • url: (required) The hostname or IP address, and optionally port, of the Fortanix DSM cluster or Fortanix HSM Gateway to connect to, separated by a colon, for example, <fortanix_dsm_url> or
    This is not a full URL as per RFC 3986, so https://<fortanix_dsm_url> is not valid, but <fortanix_dsm_url> is.
  • pin: (required)
    • For Fortanix DSM clusters: the API key of the app to use to export the CDK.
    • For PKCS#11 HSM's: the PIN to log into the HSM.
  • slot: (required for PKCS#11 HSM's only) The slot of the token with the CDK.
  • tls:(required) A JSON object describing the TLS configuration. It has the following fields:
    • mode: (required) Either "required" or "opportunistic". Using "opportunistic" disables many security checks, so only "required" should be used in production. The other fields are only available in "required" mode.
    • validate_hostname:(required) Either true or false. Only true should be used in production.
    • ca: (required) A JSON object describing the trusted certificate authorities to use. Must contain exactly one of the following fields:
      • ca_set: Must be set to "global_roots". This uses the node’s built-in set of root CA’s.
      • pinned: A list of strings, each of which is a base64-encoded PEM certificate. That is, the entire PEM certificate, guards included, is run through base64 encoding. This can be produced with the following Unix command:
        base64 -w0 < my_ca_cert.pem
    • client_cert: (optional) A client certificate to use for mutual authentication. This is a base-64 encoded PEM certificate. See above for encoding.
    • client_key: (optional) A client private key to use for mutual authentication. This is a base-64 encoded PEM key. See above for encoding.

3.1 Example

To store the CDK in the Fortanix DSM cluster at "<fortanix_dsm_url>", the config should appear as follows:

"kind": "Fortanix",
"url": "<fortanix_dsm_url>",
"tls": {
"mode": "required",
"validate_hostname": true,
"ca": { "ca_set": "global_roots" }
"pin": "<api key of app here>"

Similarly, to store the CDK in slot 1 of an nCipher PKCS#11 HSM using the HSM Gateway at, the config should appear as follows:

"kind": "Ncipher",
"url": "",
"tls": {
"mode": "required",
"validate_hostname": true,
"ca": { "ca_set": "global_roots" }
"slot": 1,
"pin": "<HSM pin here>"

4.0 Creating a New Cluster

  1. Before the cluster creation, add the following entry to the config.yaml file:
    extHsmEnabled: true
    # ... more fields ...
  2. Set the .global.extHsmEnabled field to true in theconfig.yaml file.
  3. Now, create the Fortanix DSM cluster by running the following command:
    sdkms-cluster create --self=<server ip address/subnet mask> --config ./config.yaml
  4. Before running get_csrs, run sdkms-cluster secret set secret-ext-hsm-credentials. This will prompt you for the configuration on stdin and perform validation.
  5. Run get_csrs.
  6. You will be prompted for the JSON configuration described in Section 3.1 above. Paste it here followed by a blank line.

5.0 Migrating an Existing Cluster or Changing Configuration

  1. Take the desired JSON configuration as shown in Section 3.1 above. Then base64 encode it using the command
    base64 -w0 < my_config.json
  2. Replace the value of external_cdk_config in the following command with the base64-encoded config.
    kubectl edit secret secret-ext-hsm-credentials -o yaml
  3. If you are enabling CDK protection for the first time, you will need to rotate the CMK before this feature can have any effect. Refer to the Administrative Guide: Rotating Cluster Master Key for more details. Any new data will be protected by this feature, but old data will not be changed.


Please sign in to leave a comment.

Was this article helpful?
0 out of 0 found this helpful