Encrypting Persisted Data at Rest

Persisted data on disk such as map entries may contain sensitive information. To protect your data, you can configure members to encrypt all persisted files in your persistence store.

Before you Begin

To encrypt persisted data, you must have persistence enabled. See Persistence Configuration Options.

How Encryption at Rest Works

Data in the persistence store is encrypted using symmetric encryption. The encryption scheme uses two levels of encryption keys: auto-generated persistence store encryption keys (one for each configured parallelism) that are used to encrypt the chunk files and a master encryption key that is used to encrypt the store-specific encryption keys. The master encryption key is sourced from an external system called the secure store and, in contrast to the persistence-store encryption keys, it is not persistedanywhere within the persistence store.

When encryption at rest is first enabled on a member, the member contacts the secure store during startup and retrieves the master encryption key. Then, the member generates the persistence-store encryption keys, encrypts them with the master key, and stores them in the persistence store’s directory. The subsequent writes to any chunk files will be encrypted using this persistence-store encryption key. During Persistence, the member gets the master encryption key from the secure store, decrypts the persistence-store encryption keys and uses those to decrypt the chunk files.

Configuring Encryption at Rest

To encrypt persisted data, enable and configure it, using the following options:

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest>
      <!-- insert configuration options here -->
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        # insert configuration options here

Add configuration options to the EncryptionAtRestConfig object.

Config config = new Config();

PersistenceConfig PersistenceConfig = new PersistenceConfig()
.setEnabled(true);
EncryptionAtRestConfig encryptionAtRestConfig = PersistenceConfig.getEncryptionAtRestConfig();
encryptionAtRestConfig.setEnabled(true);

config.setPersistenceConfig(PersistenceConfig);
Option Description Default Example

algorithm

The symmetric cipher to use for encrypting persisted data.

Valid values are:

  • AES/CBC/PKCS5Padding

  • DES/ECB/PKCS5Padding

  • Blowfish

  • DESede

AES/CBC/PKCS5Padding

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest enabled="true">
      <algorithm>
        AES/CBC/PKCS5Padding
      </algorithm>
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        algorithm: AES/CBC/PKCS5Padding
Config config = new Config();

PersistenceConfig PersistenceConfig = new PersistenceConfig()
.setEnabled(true)
.setAutoRemoveStaleData(true)
.setAlgorithm("AES/CBC/PKCS5Padding");

config.setPersistenceConfig(PersistenceConfig);

salt

The encryption salt.

thesalt

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest enabled="true">
      <salt>
        thesalt
      </salt>
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        salt: thesalt
Config config = new Config();

PersistenceConfig PersistenceConfig = new PersistenceConfig()
.setEnabled(true)
.setAutoRemoveStaleData(true)
.setSalt("thesalt");

config.setPersistenceConfig(PersistenceConfig);

key-size

The size (in bits) of the auto-generated persistence store encryption key.

0

A value of 0 means that the key size is determined by the encryption algorithm.

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest enabled="true">
      <key-size>
        0
      </key-size>
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        key-size: 0
Config config = new Config();

PersistenceConfig PersistenceConfig = new PersistenceConfig()
.setEnabled(true)
.setAutoRemoveStaleData(true)
.setKeySize(0);

config.setPersistenceConfig(PersistenceConfig);

secure-store (required)

The secure store to use for the storing master encryption keys.

'' (empty)

Configuring a Secure Store

A secure store represents a secure place outside of the persistence store in which Hazelcast can keep its master encryption keys.

Hazelcast provides secure store implementations for the storing master encryption keys in the following places:

Java KeyStore Secure Store

You can configure members to store your master encryption keys in a Java KeyStore by specifying the following options:

  • path: The path to the KeyStore file.

  • type: The type of KeyStore (PKCS12, JCEKS, etc.).

  • password: The KeyStore password.

  • current-key-alias: The alias for the current encryption key entry (optional).

  • polling-interval: The polling interval (in seconds) for checking for changes in the KeyStore. Disabled by default.

Sensitive configuration values such as passwords should be protected using variable replacers.

The Java KeyStore treats all KeyStore.SecretKeyEntry entries stored in the KeyStore as encryption keys. It expects that these entries use the same protection password as the KeyStore. Entries of other types (private key entries, certificate entries) are ignored. If the current-key-alias option is configured, the corresponding entry will be treated as the current encryption key, otherwise the highest entry in the alphabetical order will be used. The remaining entries will represent historical versions of the encryption key.

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest enabled="true">
      <key-size>
        0
      </key-size>
      <secure-store>
        <keystore>
          <path>/path/to/keystore.file</path>
          <type>PKCS12</type>
          <password>password</password>
          <current-key-alias>current</current-key-alias>
          <polling-interval>60</polling-interval>
        </keystore>
      </secure-store>
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        key-size: 0
        secure-store:
          keystore:
            path: /path/to/keystore.file
            type: PKCS12
            password: password
            current-key-alias: current
            polling-interval: 60
        JavaKeyStoreSecureStoreConfig keyStoreConfig =
                new JavaKeyStoreSecureStoreConfig(new File("/path/to/keystore.file"))
                        .setType("PKCS12")
                        .setPassword("password")
                        .setCurrentKeyAlias("current")
                        .setPollingInterval(60);

HashiCorp Vault Secure Store

You can configure members to store your master encryption key in a Hashicorp Vault store by specifying the following options:

  • address: The address of the Vault server.

  • secret-path: The secret path under which the encryption keys are stored.

  • token: The Vault authentication token.

  • polling-interval: The polling interval (in seconds) for checking for changes in Vault. Disabled by default.

  • ssl: The TLS/SSL configuration for HTTPS support. See the TLS/SSL section for more information about how to use the ssl element.

Sensitive configuration properties such as token should be protected using variable replacers.

The HashiCorp Vault secure store implementation uses the official REST API to integrate with HashiCorp Vault. Only for the KV secrets engine, both KV V1 and KV V2 can be used, but since only V2 provides secrets versioning, this is the recommended option. With KV V1 (no versioning support), only one version of the encryption key can be kept, whereas with KV V2, the HashiCorp Vault secure store is able to retrieve also the historical encryption keys. (Note that the size of the version history is configurable on the Vault side.) Having access to the previous encryption keys may be critical to avoid scenarios where the data becomes undecryptable because the master encryption key is no longer usable (for instance, when the original master encryption key got rotated out in the secure store while the cluster was down).

The encryption key is expected to be stored at the specified secret path and represented as a single key/value pair in the following format:

name=Base64-encoded-data

where name can be an arbitrary string. Multiple key/value pairs under the same secret path are not supported. Here is an example of how such a key/value pair can be stored using the HashiCorp Vault command-line client (under the secret path hz/cluster):

vault kv put hz/cluster value=HEzO124Vz...

With KV V2, a second put to the same secret path creates a new version of the encryption key. With KV V1, it simply overwrites the current encryption key, discarding the old value.

  • XML

  • YAML

  • Java

<hazelcast>
  <persistence enabled="true">
    <encryption-at-rest enabled="true">
      <key-size>
        0
      </key-size>
      <secure-store>
        <vault>
          <address>http://localhost:1234</address>
          <secret-path>secret/path</secret-path>
          <token>token</token>
          <polling-interval>60</polling-interval>
          <ssl>...</ssl>
        </vault>
     </secure-store>
    </encryption-at-rest>
  </persistence>
</hazelcast>
hazelcast:
  persistence:
    enabled: true
      encryption-at-rest:
        enabled: true
        key-size: 0
        secure-store:
          vault:
            address: http://localhost:1234
            secret-path: secret/path
            token: token
            polling-interval: 60
            ssl:
              ...
        VaultSecureStoreConfig vaultConfig =
                new VaultSecureStoreConfig("http://localhost:1234", "secret/path", "token")
                        .setPollingInterval(60);
        configureSSL(vaultConfig.getSSLConfig());

Rotating the Master Key

If you update the master encryption key in the secure store, the Persistence subsystem will detect it and retrieve the new master encryption key. During this process, it will also re-encrypt the persistence store encryption keys using the new master encryption key.