1.0 Introduction
This article describes how to integrate Fortanix-Data-Security-Manager (DSM) with HashiCorp Vault Enterprise and secure it by protecting its master key through an additional HSM key.
2.0 Why Use Fortanix Data Security Manager with HashiCorp Vault Enterprise
The Fortanix DSM with HashiCorp Vault Enterprise integration greatly simplifies the Vault administration. It is a must-have for any HashiCorp Vault Enterprise deployment within an organization storing its sensitive information inside Vault.

Figure 1: Fortanix DSM Solution for HashiCorp Vault
In summary, Fortanix Data Security Manager can harden and secure HashiCorp Vault by:
Master Key Wrapping: The Vault master key is protected by transiting it through the Fortanix HSM for encryption rather than having it split into key shares.
Automatic Unsealing: Vault stores its encrypted master key in storage, allowing for automatic unsealing, which is decrypted only through authorized HSM access.
Seal Wrapping: This provides FIPS 140-2 Level 2 secret storage conforming functionality for Critical Security Parameters. Note, that the Fortanix DSM itself is classified by NIST as a FIPS 140-2 Level 3.
Entropy Augmentation: Vault Enterprise features a mechanism to sample entropy (or randomness for cryptographic operations) from external cryptographic modules through the Seals interface. While the system entropy used by Vault is more than capable of operating in most threat models, there are some situations where additional entropy from hardware-based random number generators is desirable.
Fortanix DSM can harden existing as well as new HashiCorp Vault Enterprise deployments regardless of their current seal configuration.
Fortanix DSM can harden existing as well as new HashiCorp Vault Enterprise deployments regardless of their current seal configuration.
3.0 Prerequisites
HashiCorp Vault Enterprise HSM
Fortanix DSM
Network route between Vault Enterprise and Fortanix DSM
4.0 Setup
4.1 Deploy the Fortanix PKCS#11 Library for Vault
Install the PKCS#11 library by following the instructions provided in the following URL:
clients-pkcs-11-libraryNOTE
HashiCorp Vault Enterprise HSM is only supported on Linux.
Configure the Fortanix API endpoint using the following command:
export FORTANIX_API_ENDPOINT="https://<FORTANIX_DSM_URL>"
[OPTIONAL] - Configure extra variables to test the Fortanix library using the following commands:
export FORTANIX_PKCS11_NUM_SLOTS=5 export FORTANIX_PKCS11_LOG_LEVEL=“debug”
[OPTIONAL] - Validate that the Fortanix PKCS#11 library is functional using the following commands:
$> pkcs11-tool --module /path/to/fortanix_pkcs11.so --show-info Cryptoki version 2.40 Manufacturer Fortanix Library Fortanix PKCS#11 3.23.1408 (ver 3.23) Using slot 0 with a present token (0x0)
4.2 Enable Vault Seal Wrapping with an HSM PKSC11 Token
Create a Vault configuration file called
cfg-vault-p11.hcl
:seal "pkcs11" { lib = "/opt/fortanix/pkcs11/fortanix_pkcs11.so" slot = "0" pin = "<<FORTANIX_API_KEY>>" key_label = "Vault-Master-Key-RSA-OAEP-SHA256" mechanism = "0x0009" rsa_oaep_hash = "sha256" generate_key = "true" }
NOTE
Create an App in Fortanix DSM dedicated to the Vault Enterprise deployment.
Use different Fortanix Apps corresponding to each Vault server, to streamline the audit reporting for later compliance.
Specify the
FORTANIX_API_KEY
in the Vault config file shown above.Additional Vault configuration parameters are available at –
https://www.vaultproject.io/docs/configuration/seal/pkcs11Additional master key encryption mechanisms supported are:
0x0009
corresponds toCKM_RSA_PKCS_OAEP
0x1087
corresponds toCKM_AES_GCM
0x1082
corresponds toCKM_AES_CBC
– This mode is not supported for Fortanix HSM Gateway.
Vault creates non-exportable keys if
generate_key="true"
. Otherwise, please create the Fortanix DSM and specify the correct key label withgenerate_key="false"
.
Vault Enterprise is now ready for initialization and testing. Verify the log:
$> vault server -config=cfg-vault-p11.hcl ==> Vault server configuration: HSM PKCS#11 Version: 2.40 HSM Library: Fortanix PKCS#11 3.23.1408 HSM Library Version: 3.23 HSM Manufacturer ID: Fortanix HSM Type: pkcs11 Cgo: enabled Go Version: go1.14.4 Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled") Log Level: trace Mlock: supported: true, enabled: false Recovery Mode: false Storage: file Version: Vault v1.6.0+ent.hsm ==> Vault server started! Log data will stream in below: 2020-07-30T13:17:15.405-0400 [INFO] proxy environment: http_proxy= https_proxy= no_proxy= 2020-07-30T13:17:16.988-0400 [INFO] core: stored unseal keys supported, attempting fetch 2020-07-30T13:17:16.988-0400 [WARN] failed to unseal core: error="stored unseal keys are supported, but none were found"
Figure 2: Vault Configuration
Verify the status of Vault using the following command:
$> vault status Key Value --- ----- Recovery Seal Type pkcs11 Initialized false Sealed true Total Recovery Shares 0 Threshold 0 Unseal Progress 0/0 Unseal Nonce n/a Version n/a HA Enabled false
5.0 Test the Vault Server
For Vault version 1.7.10 or below, without an Enterprise or a Trial License, when the Vault server is running, it terminates in 30 minutes. To continue testing, please restart the Vault server.
For Vault version 1.8 onwards, you need a valid license (or a trial license that is valid for 30 days) to test.
5.1 Initialize and Unseal the Vault
With configuration done, Vault needs to be initialized and unsealed before use using the following command:
$> vault operator init -recovery-shares=3 -recovery-threshold=2
Recovery Key 1: /Ui9pazFsRI/ObpGAietRaakNiM8nj6s9SgCTDs2fVOT
Recovery Key 2: yJUsNBL4bjWeQidHIRJBE+tB+WObbTZTlzzIRN3AsfQ+
Recovery Key 3: URVrc2l7ZROFl3ePCotVceSHxrMGGSwwpAUyXlhxzWky
Initial Root Token: s.sb11N0r9HJrCyZHNrfb0YIti
Success! Vault is initialized
Recovery key initialized with 3 key shares and a key threshold of 2.
Please securely distribute the key shares printed above.
The previous step connects to Fortanix DSM and auto-unseals Vault by having the master key decrypted inside the HSM.
NOTE
If there are problems with the previous command, please ensure that Rsyslogd is enabled by verifying /var/log/syslog (Debian) or
/var/log/messages
(RHEL).Start the Vault server with additional debugging as follows:
$> FORTANIX_PKCS11_LOG_LEVEL=debug vault server -log-level=trace -config=cfg-vault-p11.hcl ==> Vault server configuration: HSM PKCS#11 Version: 2.40 HSM Library: Fortanix PKCS#11 3.23.1408 HSM Library Version: 3.23 HSM Manufacturer ID: Fortanix HSM Type: pkcs11 Cgo: enabled Go Version: go1.14.4 Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled") Log Level: trace Mlock: supported: true, enabled: false Recovery Mode: false Storage: file Version: Vault v1.6.0+ent.hsm ==> Vault server started! Log data will stream in below: 2020-07-30T13:17:15.405-0400 [INFO] proxy environment: http_proxy= https_proxy= no_proxy= 2020-07-30T13:17:15.408-0400 [TRACE] seal.pkcs11: pkcs11 mechanism selected: mechanism=0x1087 name=aes-gcm 2020-07-30T13:17:16.959-0400 [TRACE] seal.pkcs11: key successfully found 2020-07-30T13:17:16.975-0400 [WARN] no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set 2020-07-30T13:17:16.976-0400 [TRACE] core: activating sealwrap capability 2020-07-30T13:17:16.976-0400 [TRACE] core: initializing licensing 2020-07-30T13:17:16.982-0400 [DEBUG] storage.cache: creating LRU cache: size=0 2020-07-30T13:17:16.985-0400 [DEBUG] cluster listener addresses synthesized: cluster_addresses=[0.0.0.0:8201] 2020-07-30T13:17:16.988-0400 [INFO] core: stored unseal keys supported, attempting fetch 2020-07-30T13:17:16.988-0400 [WARN] failed to unseal core: error="stored unseal keys are supported, but none were found"
In addition to the Vault server transcript, the Syslog or messages log should reveal more details pertaining to connection to the Fortanix DSM or other PKCS#11 errors, if any.
5.2 Verify the Status of the Vault
Verify the status of the vault using the following command:
$> vault status
Key Value
--- -----
Recovery Seal Type shamir
Initialized true
Sealed false
Total Recovery Shares 3
Threshold 2
Version 1.6.0+ent.hsm
Cluster Name vault-cluster-dfcace02
Cluster ID 0fe5ab51-ff92-fdb0-9c37-f739679554f8
HA Enabled false
5.3 Restart Vault
Restart Vault and check the auto-unseal status before continuing using the following command:
$> vault login
Token (will be hidden):
Success! You are now authenticated...
$> vault secrets enable kv -path=morekv
$> vault kv put morekv/hello foo=world
Success! Data written to: morekv/hello
$> vault kv get morekv/hello
=== Data ===
Key Value
--- -----
foo world
5.4 Test Seal Wrapping
Apply the Enterprise license.
vault write sys/license text=<license>
NOTE
For FIPS 140-2 compliance, seal wrap requires FIPS 140-2 Certified HSM which is supported by Vault Enterprise.
For some values, seal wrapping is always enabled including the recovery key, any stored key shares, the master key, the keyring, and more. When working with the key/value secrets engine, you can enable seal wrap to wrap all data.
To compare seal wrapped data against unwrapped data, enable key/value v1 secrets engine at two different paths:kv-unwrapped
andkv-seal-wrapped
.Enable k/v v1 without seal wrap at
kv-unwrapped
.vault secrets enable -path=kv-unwrapped kv
Enable k/v v1 with seal wrap. To do so, use the '
-seal-wrap
' flag when you enable the KV workflow.vault secrets enable -path=kv-seal-wrapped -seal-wrap kv
List the enabled secrets engines with details.
vault secrets list -detailed Path Plugin Accessor Seal Wrap ---- ------ -------- --------- cubbyhole/ cubbyhole cubbyhole_3a415617 false identity/ identity identity_b544f633 false kv-seal-wrapped/ kv kv_72d69c39 true kv-unwrapped/ kv kv_2e60002d false
NOTE
Notice that the Seal Wrap parameter value is true for
kv-seal-wrapped
.
5.4.1 Example to Test the Seal Wrap Feature
Write a secret at
kv-unwrapped/unwrapped
for testing.vault kv put kv-unwrapped/unwrapped password="my-long-password"
Read the path to verify.
vault kv get kv-seal-wrapped/wrapped ====== Data ====== Key Value --- ----- password my-long-password
Write the same secret at
kv-seal-wrapped/wrapped
for testing.vault kv put kv-seal-wrapped/wrapped password="my-long-password"
Read the path to verify.
vault kv put kv-seal-wrapped/wrapped password="my-long-password"
Using a valid token, you can write and read secrets the same way regardless of the seal wrap.
NOTE
Remember that the Vault server was configured to use the local file system (
/tmp/vault
) as its storage backend in this example.SSH into the machine where the Vault server is running and check the stored values in the
/tmp/vault
directory.cd /tmp/vault/logical
Under the
/tmp/vault/logical
directory, there are two sub-directories. One maps tokv-unwrapped/
and another maps tokv-seal-wrapped/
although you cannot tell by the folder names.View the secret at rest. One of the directories maps to
kv-unwrapped/unwrapped
.cd 2da357cd-55f2-7eed-c46e-c477b70bed18
View its content. The password value is encrypted.
cat _unwrapped {"Value":"AAAAAQICk547prhuhMiBXLq2lx8ZkMpSB3p+GKHAwuMhKrZGSeqsFevMS6YoqTVlbvpU9B4zWPZ2HA SeNZ3YMw=="}
Another directory maps to
kv-seal-wrapped/wrapped
.cd ../5bcea44d-28a3-87af-393b-c6d398fe41d8
View its content. The password value is encrypted.
cat _wrapped {"Value":"ClBAg9oN7zBBaDBZcsilDAyGkL7soPe7vBA5+ADADuyzo8GuHZHb9UFN2nF1h0OpKEgCIkG3JNHcXt tZqCi6szcuNBgF3pwhWGwB4FREM3b5CRIQYK7239Q92gRGrcBBeZD6ghogEtSBDmZJBahk7n4lIYF3X4iBqmwZgH Vo4lzWur7rzncgASofCIIhENEEGghoc21fZGVtbyINaHNtX2htYWNfZGVtb3M="}
NOTE
Secrets are encrypted regardless; however, the seal-wrapped value is significantly longer despite the fact that both values are the same,
my-long-password
.Looking closely at the values in the last two outputs, you will see a slight difference.
The first output shows the truncated secret encrypted with Vault’s encryption key which is a standard across anything that passes Vault’s barrier and is stored in its storage backend.
In the second output, the value looks different, as expected. This is because Vault has applied a Seal Wrap to it, which means that it was both encrypted by Vault and encrypted by the HSM before being stored in Vault’s storage backend.
5.5 Entropy Augmentation
Apply the Enterprise license.
vault write sys/license text=
Entropy augmentation is disabled by default. To enable entropy augmentation, Vault's configuration file must include a properly configured entropy and seal stanza for a supported seal type. For example:
seal"pkcs11" { ... } entropy "seal" { mode = "augmentation" }
Enable Entropy Augmentation.
To leverage the external entropy source, set theexternal_entropy_access
parameter totrue
when you enable a secrets engine or auth method.
In this step, you are going to enable an external entropy source on a transit secrets engine. Execute the following command to enable transit secrets engine with external entropy source using the-external-entropy-access
flag.vault secrets enable -external-entropy-access transit
List the enabled secrets engines with
-detailed
flag.vault secrets list -detailed Path Plugin Accessor External Entropy Access ---- ------ -------- ----------------------- cubbyhole/ cubbyhole cubbyhole_b8e95763 false identity/ identity identity_b629a5f8 false sys/ system system_45f38555 false transit/ transit transit_b93cf7a7 true
NOTE
Notice that the External Entropy Access is set to true for
transit/
.
5.5.1 Example to Test the Entropy Augmentation Feature
You can start using the transit secrets engine to encrypt your sensitive data which leverages the HSM as its external entropy source. Regardless, the user experience remains the same as before.
Create a new encryption key named, "
orders
".vault write -f transit/keys/orders Success! Data written to: transit/keys/orders
Send a base64-encoded string to be encrypted by Vault.
vault write transit/encrypt/orders plaintext=$(base64 <<< "4111 1111 1111 1111") Key Value --- ----- ciphertext vault:v1:4oQdMopYk805wCww5t+5mwn6hmTy1FvfMiGHfsftc8lxD4YdkgW3RZUNymISzhCE key_version 1
Now, test to verify that you can decrypt.
/vault write transit/decrypt/orders ciphertext="vault:v1:4oQdMopYk805wCww5t+5mwn6hmTy1FvfMiGHfsftc8lxD4YdkgW3RZUNymISzhCE" Key Value --- ----- plaintext NDExMSAxMTExIDExMTEgMTExMQo=
Decode to get the original data.
base64 --decode <<< NDExMSAxMTExIDExMTEgMTExMQo= 4111 1111 1111 1111
NOTE
When the external entropy access is enabled, connectivity to the HSM is required. If the HSM becomes unreachable for any reason, the transit secrets engine will fail to generate new keys or rotate the existing keys.
Error writing data to transit/encrypt/orders: Error making API request. URL: PUT http://127.0.0.1:8200/v1/transit/encrypt/orders Code: 400. Errors: * error performing token check: failed to read entry: error initializing session for decryption: error logging in to HSM: pkcs11: 0xE0: CKR_TOKEN_NOT_PRESENT
6.0 Rotate the Master Key
For existing Vault Enterprise deployments where the Vault server is running with PKCS#11 auto-unseal with another HSM vendor’s PKCS#11 library, this section may be useful to migrate to the Fortanix HSM Gateway.
In addition, this section is also relevant to new or existing HashiCorp Vault deployments, wherein the master key needs to be rotated simply inside the Fortanix DSM.
6.1 Rotate Master Key
With configuration and end-to-end testing complete, Vault can have its master key rotated by specifying a default key that is used as a fallback.
Shut down the Vault server.
Update the Vault configuration file called
cfg-vault-p11.hcl
using the following command:seal "pkcs11" { lib = "/opt/fortanix/pkcs11/fortanix_pkcs11.so" slot = "0" pin = "<<FORTANIX_API_KEY>>" key_label = "New-Vault-Master-Key-RSA-OAEP-SHA256" default_key_label = "Vault-Master-Key-RSA-OAEP-SHA256" mechanism = "0x0009" rsa_oaep_hash = "sha256" generate_key = "true" }
In this example:
Vault-Master-Key-RSA-OAEP-SHA256
is the existing key.>New-Vault-Master-Key-RSA-OAEP-SHA256
is the new key.
6.2 Restart Vault
Restart vault using the following command:
$> vault server -config=cfg-vault-p11.hcl
==> Vault server configuration:
HSM PKCS#11 Version: 2.40
HSM Library: Fortanix PKCS#11 3.23.1408
HSM Library Version: 3.23
HSM Manufacturer ID: Fortanix
HSM Type: pkcs11
Cgo: enabled
Go Version: go1.14.4
Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
Log Level: trace
Mlock: supported: true, enabled: false
Recovery Mode: false
Storage: file
Version: Vault v1.6.0+ent.hsm
==> Vault server started! Log data will stream in below:
2020-07-30T14:23:55.605-0400 [INFO] proxy environment: http_proxy= https_proxy= no_proxy=
2020-07-30T14:23:57.414-0400 [WARN] no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set
2020-07-30T14:23:57.447-0400 [INFO] core: stored unseal keys supported, attempting fetch
2020-07-30T14:24:00.524-0400 [INFO] core.cluster-listener.tcp: starting listener: listener_address=0.0.0.0:8201
2020-07-30T14:24:00.526-0400 [INFO] core.cluster-listener: serving cluster requests: cluster_listen_address=[::]:8201
2020-07-30T14:24:00.527-0400 [INFO] core: post-unseal setup starting
2020-07-30T14:24:08.122-0400 [INFO] core: loaded wrapping token key
2020-07-30T14:24:08.123-0400 [INFO] core: successfully setup plugin catalog: plugin-directory=
2020-07-30T14:24:08.128-0400 [INFO] core: successfully mounted backend: type=system path=sys/
2020-07-30T14:24:08.129-0400 [INFO] core: successfully mounted backend: type=identity path=identity/
2020-07-30T14:24:08.130-0400 [INFO] core: successfully mounted backend: type=kv path=morekv/
2020-07-30T14:24:08.130-0400 [INFO] core: successfully mounted backend: type=cubbyhole path=cubbyhole/
2020-07-30T14:24:08.156-0400 [INFO] core: successfully enabled credential backend: type=token path=token/
2020-07-30T14:24:08.158-0400 [INFO] core: restoring leases
2020-07-30T14:24:08.158-0400 [INFO] rollback: starting rollback manager
2020-07-30T14:24:08.161-0400 [INFO] expiration: lease restore complete
2020-07-30T14:24:08.161-0400 [INFO] identity: entities restored
2020-07-30T14:24:08.162-0400 [INFO] identity: groups restored
2020-07-30T14:24:08.162-0400 [INFO] mfa: configurations restored
2020-07-30T14:24:08.170-0400 [INFO] core: stopping replication
2020-07-30T14:24:08.170-0400 [INFO] core: closed sync connection
2020-07-30T14:24:08.171-0400 [INFO] core: replication stopped
2020-07-30T14:24:08.171-0400 [INFO] core: setting up replication
2020-07-30T14:24:08.172-0400 [INFO] core: replicated cluster information not found or disabled, not activating client
2020-07-30T14:24:08.172-0400 [INFO] core: replication setup finished
2020-07-30T14:24:09.830-0400 [INFO] core.autoseal: upgrading recovery key
2020-07-30T14:24:13.799-0400 [INFO] core.autoseal: upgrading stored keys
2020-07-30T14:24:17.223-0400 [INFO] core: usage gauge collection is disabled
2020-07-30T14:24:17.225-0400 [INFO] core: post-unseal setup complete
2020-07-30T14:24:17.226-0400 [INFO] core: vault is unsealed
2020-07-30T14:24:17.226-0400 [INFO] core: unsealed with stored keys: stored_keys_used=1
6.3 Verify the Status of the Vault
Verify the status of the vault using the following command:
$> vault status
Key Value
--- -----
Recovery Seal Type shamir
Initialized true
Sealed false
Total Recovery Shares 3
Threshold 2
Version 1.6.0+ent.hsm
Cluster Name vault-cluster-dfcace02
Cluster ID 0fe5ab51-ff92-fdb0-9c37-f739679554f8
HA Enabled false
6.4 Check and Update the Secret
Check the secret and update it using the following command:
$> vault login
Token (will be hidden):
Success! You are now authenticated...
$> vault kv put morekv/hello foo=new-world
Success! Data written to: morekv/hello
$> vault kv get morekv/hello
=== Data ===
Key Value
--- -----
foo new-world
7.0 HSM Gateway
Notes on testing HashiCorp Vault Enterprise with an existing HSM from Thales, Entrust, IBM HSM, or Gemalto:
Ensure in Fortanix DSM that an HSM-enabled Group is successfully connected to a Fortanix HSM Gateway.
Use an appropriate
FORTANIX_API_KEY
corresponding to the external HSM-enabled Group.Check the HSM for a list of cryptographic mechanisms supported. Some HSMs have disabled certain mechanisms like
CKM_AES_GCM
.Fortanix HSM Gateway with Fortanix DSM has been successfully tested with a Vault Enterprise master
CKM_RSA_PKCS_OAEP
.