Operations

Performance Replication with Mount Filters

Mount filters are a new way of controlling which secrets are moved across clusters and physical regions as a result of replication. With mount filters, users can select which secret engines will be replicated as part of a performance replication relationship.

By default, all non-local secret engines and associated data are replicated as part of replication. The mount filter feature allows users to whitelist or blacklist which secret engines are replicated, thereby allowing users to further control the movement of secrets across their infrastructure.

Performance Replication

» Challenge

General Data Protection Regulation (GDPR) is designed to strengthen data protection and privacy for all individuals within the European Union. It requires that personally identifiable data not be physically transferred to locations outside the European Union unless the region or country has an equal rigor of data protection regulation as the EU.

Failure to abide by GDPR will result in fines as high as 20 million EUR or 4% of the global annual revenue (whichever greater).

» Solution

Leverage Vault's mount filter feature to abide by data movements and sovereignty regulations while ensuring performance access across geographically distributed regions.

The Preparing for GDPR Compliance with HashiCorp Vault webinar discusses the GDPR compliance further in details.

YouTube

» Prerequisites

This intermediate Vault operations guide assumes that you have some working knowledge of Vault.

You need two Vault Enterprise clusters: one representing the EU cluster, and another representing the US cluster both backed by Consul for storage.

» Steps

Scenario: You have a Vault cluster in EU and wish to span across the United States by setting up a secondary cluster and enable the performance replication. However, some data must remain in EU and should not be replicated to the US cluster.

Guide Scenario

Leverage the mount filter feature to blacklist the secrets, that are subject to GDPR, from being replicated across the regions.

  1. Segment GDPR and non-GDPR secret engines
  2. Enable performance replication with mount filter
  3. Verify the replication mount filter
  4. Enable a local secret engine

» Step 1: Segment GDPR and non-GDPR secret engines

In the EU cluster (primary cluster), enable key/value secret engines:

  • At EU_GDPR_data for GDPR data
  • At US_NON_GDPR_data for non-GDPR data localized for US

» CLI command

# For GDPR data
$ vault secrets enable -path=EU_GDPR_data kv-v2

# For non-GDPR data accessible in US
$ vault secrets enable -path=US_NON_GDPR_data kv-v2

» API call using cURL

# For GDPR data
$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data '{"type":"kv-v2"}' \
       https://eu-west-1.compute.com:8200/v1/sys/mounts/EU_GDPR_data

# For non-GDPR data accessible in US
$ curl --header "X-Vault-Token: ..." \
      --request POST \
      --data '{"type":"kv-v2"}' \
      https://eu-west-1.compute.com:8200/v1/sys/mounts/US_NON_GDPR_data

» Web UI

  1. Open a web browser and launch the Vault UI (e.g. https://eu-west-1.compute.com:8200/ui) and then login.

  2. Select Enable new engine and enter corresponding parameter values: GDPR KV Non-GDPR KV

  3. Click Enable Engine to complete.

» Step 2: Enable performance replication with mount filter

» CLI command

Enable performance replication on the primary cluster.

$ vault write -f sys/replication/performance/primary/enable
WARNING! The following warnings were returned from Vault:

* This cluster is being enabled as a primary for replication. Vault will be
unavailable for a brief period and will resume service shortly.

Generate a secondary token.

$ vault write sys/replication/performance/primary/secondary-token id="secondary"
Key                              Value
---                              -----
wrapping_token:                  eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJhZGRyIjoiaHR0cDovLzE3Mi4zMS4yMC4xODA6ODIwMyIsImV4cCI6MTUyNTg0ODAxMywiaWF0IjoxNTI1ODQ2MjEzLCJqdGkiOiJlNTFiMjUxZi01ZTg2LTg4OWEtNGZmMy03NTQzMjRkNTdlMGQiLCJ0eXBlIjoid3JhcHBpbmcifQ.MIGGAkE2dDj3nmaoLHg7oldQ1iZPD0U8doyj3x3mQUVfTl8W99QYG8GM6VGVzhRPGvKctGriuo2oXN_8euWQb01M1y6n7gJBSu-qdXw-v2RieOyopAHls1bWhw4sO9Nlds8IDFA15vqkLXnq2g4_5lvlhxpP7B8dEOHvWXkHG4kJ_mKvrgR0dU0
wrapping_accessor:               6ded4fb0-5e8c-2a37-1b3e-823673220348
wrapping_token_ttl:              30m
wrapping_token_creation_time:    2018-05-09 06:10:13.437421436 +0000 UTC
wrapping_token_creation_path:    sys/replication/performance/primary/secondary-token

Create a mount filter to blacklist EU_GDPR_data.

$ vault write sys/replication/performance/primary/mount-filter/secondary  \
       mode="blacklist" paths="EU_GDPR_data/"

Enable performance replication on the secondary cluster.

$ vault write sys/replication/performance/secondary/enable token="..."

Where the token is the wrapping_token obtained from the primary cluster.

» API call using cURL

Enable performance replication on the primary cluster.

$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data '{"primary_cluster_addr":"https://eu-west-1.compute.com:8200"}' \
       https://eu-west-1.compute.com:8200/v1/sys/replication/performance/primary/enable

Generate a secondary token.

$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data '{ "id": "secondary"}' \
       https://eu-west-1.compute.com:8200/v1/sys/replication/performance/primary/secondary-token | jq
  {
   "request_id": "",
   "lease_id": "",
   "renewable": false,
   "lease_duration": 0,
   "data": null,
   "wrap_info": {
     "token": "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJhZGRyIjoiaHR0cDovLzEyNy4wLjAuMTo4MjAzIiwiZXhwIjoxNTI1ODI5Njc2LCJpYXQiOjE1MjU4Mjc4NzYsImp0aSI6IjAwNmVkMDdjLWQ0MzYtZWViYy01OWYwLTdiMTU0ZGFmMDNiMCIsInR5cGUiOiJ3cmFwcGluZyJ9.MIGHAkF6saWWL-oRQMJIoUnaUOHNkcoHZCBwQs6mSMjPBopMi8DkGCJGBrh4jgV2mSzwFY1r5Ne7O66HmuMpm40MsYqjAQJCANSco_Sx5q6FmQSfoY-HtsVO1_YKWF4O6B7gYCvPKYkODMIwe5orCSgmIDyXHZt-REPm0sfdk4ZNyRCIRK5hDWyQ",
     "accessor": "6ea2a4e2-2926-120f-f288-c2348c78fb3e",
     "ttl": 1800,
     "creation_time": "2018-05-09T01:04:36.514715311Z",
     "creation_path": "sys/replication/performance/primary/secondary-token"
   },
   "warnings": null,
   "auth": null
 }

Create a mount filter to blacklist EU_GDPR_data.

$ tee payload.json <<EOF
{
  "mode": "blacklist",
  "paths": [ "EU_GDPR_data/" ]
}
EOF

$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data @payload.json \
       https://eu-west-1.compute.com:8200/v1/sys/replication/performance/primary/mount-filter/secondary

Enable performance replication on the secondary cluster.

$ tee payload.json <<EOF
{
  "token": "..."
}
EOF

$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data @payload.json \
       https://us-central.compute.com:8201/v1/sys/replication/performance/secondary/enable

Where the token in payload.json is the token obtained from the primary cluster.

» Web UI

  1. Select Replication and check the Performance radio button. Performance Replication - primary

  2. Click Enable replication.

  3. Select the Secondaries tab, and then click Add. Performance Replication - primary

  4. Populate the Secondary ID field, and then select Configure performance mount filtering to set your mount filter options. You can filter by whitelisting or blacklisting. For this example, select Blacklist.

  5. Check EU_GDPR_data to prevent it from being replicated to the secondary cluster. Performance Replication - primary

  6. Click Generate token. Performance Replication - primary

  7. Click Copy to copy the token.

  8. Now, launch the Vault UI for the secondary cluster (e.g. https://us-central.compute.com:8201/ui), and then click Replication.

  9. Check the Performance radio button, and then select secondary under the Cluster mode. Paste the token you copied from the primary. Performance Replication - secondary

  10. Click Enable replication.


Restart the secondary vault server (e.g. https://us-central.compute.com:8201) and unseal it with the primary cluster's unseal key.

$ vault operator unseal
Unseal Key (will be hidden): <primary_cluster_unseal_key>

The initial root token on the secondary no longer works. Use the auth methods configured on the primary cluster to log into the secondary.

Example:

Enable and configure the userpass auth method on the primary cluster and create a new username and password.

# Enable the userpass auth method on the primary
$ vault auth enable userpass

# Create a user with admin policy
$ vault write auth/userpass/users/james password="passw0rd" policy="admin"

Log into the secondary cluster using the enabled auth method.

$ vault login -method=userpass username=james password="passw0rd"

» Step 3: Verify the replication mount filter

Once the replication completes, verify that the secrets stored in the EU_GDPR_data never get replicated to the US cluster.

» CLI command

On the EU cluster, write some secrets:

# Write some secret at EU_GDPR_data/secret
$ vault kv put EU_GDPR_data/secret pswd="password"
Key              Value
---              -----
created_time     2018-05-10T18:00:38.912587665Z
deletion_time    n/a
destroyed        false
version          1

# Write some secret at US_NON_GDPR_data/secret
$ vault kv put US_NON_GDPR_data/secret apikey="my-api-key"
Key              Value
---              -----
created_time     2018-05-10T18:04:37.554665851Z
deletion_time    n/a
destroyed        false
version          1

From the US cluster, read the secrets:

# Read the secrets at EU_GDPR_data/secret
$ vault kv get EU_GDPR_data/secret
No value found at EU_GDPR_data/secret

# Read the secrets at US_NON_GDPR_data/secret
$ vault kv get US_NON_GDPR_data/secret
====== Metadata ======
Key              Value
---              -----
created_time     2018-05-10T18:09:07.717250408Z
deletion_time    n/a
destroyed        false
version          1

===== Data =====
Key       Value
---       -----
apikey    my-api-key

» API call using cURL

On the EU cluster, write some secret:

# Create the request payload
$ tee payload.json <<EOF
{
  "data": {
    "pswd": "password"
  }
}
EOF

# Write some secret at EU_GDPR_data/secret
$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data @payload.json \
       https://eu-west-1.compute.com:8200/v1/EU_GDPR_data/data/secret

# Create the request payload
$ tee payload-us.json <<EOF
{
 "data": {
   "apikey": "my-api-key"
 }
}
EOF

# Write some secret at US_NON_GDPR_data/secret
$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data @payload-us.json \
       https://eu-west-1.compute.com:8200/v1/US_NON_GDPR_data/data/secret

From the US cluster, read the secrets:

# Read the secrets at EU_GDPR_data/secret
$ curl --header "X-Vault-Token: ..." \
       https://us-central.compute.com:8201/v1/EU_GDPR_data/data/secret | jq
{
  "errors": []
}

# Read the secrets at US_NON_GDPR_data/secret
$ curl --header "X-Vault-Token: ..." \
       https://us-central.compute.com:8201/v1/US_NON_GDPR_data/data/secret | jq
{
  "request_id": "f5eedb5b-9406-c519-f5a5-070336c10205",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": null,
  "wrap_info": null,
  "warnings": [
    "Invalid path for a versioned K/V secrets engine. See the API docs for the appropriate API endpoints to use. If using the Vault CLI, use 'vault kv get' for this operation."
  ],
  "auth": null
}

» Web UI

  1. On the EU cluster, select EU_GDPR_data > Create secret: Secrets

  2. Enter the values and click Save. Repeat the step to write some secrets at the US_NON_GDPR_data path as well.

  3. On the US cluster, select US_NON_GDPR_data. You should be able to see the apikey under US_NON_GDPR_data/secret. Secrets

  4. The EU_GDPR_data data is not replicated, so you won't be able to see the secrets.

» Step 4: Enable a local secret engine

When replication is enabled, you can mark the secrets engine local only. Local secret engines are not replicated or removed by replication.

Login to the secondary cluster and enable key/value secret engine at US_ONLY_data to store secrets only valid for the US region.

» CLI command

Pass the -local flag:

$ vault secrets enable -local -path=US_ONLY_data kv-v2

» API call using cURL

Pass the local parameter in the API request:

$ tee payload.json <<EOF
{
  "type": "kv-v2",
  "local": true
}
EOF

$ curl --header "X-Vault-Token: ..." \
       --request POST \
       --data @payload.json \
       https://us-central.compute.com:8201/v1/sys/mounts/US_ONLY_data

» Web UI

Be sure to select the check box for Local to keep it mounted locally within the cluster.

Local Secret


» Help and Reference