Apache NiFi 1.15.0 - Protecting NiFi Configuration using HashiCorp Vault K/V Secrets


(Guest author: Joe Gresock)

This is a follow-on post to Apache NiFi 1.14.0 - HashiCorp Vault Integration, demonstrating protecting Apache NiFi 1.15.0 sensitive configuration properties by storing them as HashiCorp Vault Key/Value Secrets.

Introduction

In the last post, we walked through protecting NiFi configuration properties using HashiCorp Vault’s Transit Secrets Engine. This process outsourced the encryption of sensitive configuration properties to Vault. Here we will slightly alter the procedure in order to store these sensitive properties as actual Key/Value Secrets in a Vault server.

Rather than simply pointing out the differences, we’ll walk through the entire procedure, which will be necessary in order to pick up the latest Apache NiFi distribution anyway.

Setup

To get started, we’ll need to download and install HashiCorp Vault, NiFi 1.15.0, and nifi-toolkit.

For the purposes of this guide, we’ll unzip both nifi-toolkit-1.15.0-bin.zip and nifi-1.15.0-bin.zip in the same parent directory, so that you should see this:

$ ls
nifi-1.15.0    nifi-toolkit-1.15.0

We’ll start Vault using development mode, which allows us to easily interact with the Vault server without having to unseal the server. Run the following:

vault server -dev > init.log

This will launch Vault in development mode, and will write something like the following to init.log:

WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.

You may need to set the following environment variable:

    $ export VAULT_ADDR='http://127.0.0.1:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: fUJ6zxqlo+vsWFlCxMK9MKrhgpsmxdNla727mu+5nuY=
Root Token: s.3qsioJdA3YXptvEQURDCijUw

Development mode should NOT be used in production installations!

In another terminal, create a file containing this root token, which we’ll use later:

TOKEN=$(grep "Root Token" init.log | cut -d ":" -f2 | xargs)
echo "vault.token=$TOKEN" > ~/vault-auth.properties

Run the following to enable the K/V (version 1) Secrets Engine, which actually stores sensitive values in the Vault server:

vault secrets enable -path nifi-kv kv

This last command created a Vault path called "nifi-kv". Take note of this value, because we’ll be seeing it again later. Note that we could have simply used the command vault secrets enable kv, which would have enabled the K/V secrets engine at the path kv, but here we use a specific path in order to see how it is customized.

Integrating Vault into nifi and nifi-tookit

Now that we have Vault running and configured, we’ll configure nifi-toolkit to talk to Vault. Since the toolkit operates on actual NiFi configuration files, that’s where we’ll start.

First, open up nifi-1.15.0/conf/bootstrap-hashicorp-vault.conf in your preferred editor, and configure it as follows:

# HTTP or HTTPS URI for HashiCorp Vault is required to enable the Sensitive Properties Provider
vault.uri=http://127.0.0.1:8200

# Transit Path is required to enable the Sensitive Properties Provider Protection Scheme 'hashicorp/vault/transit/{path}'
vault.transit.path=

# Key/Value Path is required to enable the Sensitive Properties Provider Protection Scheme 'hashicorp/vault/kv/{path}'
vault.kv.path=nifi-kv

# Token Authentication example properties
# vault.authentication=TOKEN
# vault.token=<token value>

# Optional file supports authentication properties described in the Spring Vault Environment Configuration
# https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration
#
# All authentication properties must be included in bootstrap-hashicorp-vault.conf when this property is not specified.
# Properties in bootstrap-hashicorp-vault.conf take precedence when the same values are defined in both files.
# Token Authentication is the default when the 'vault.authentication' property is not specified.
vault.authentication.properties.file=<full/path/to/vault-auth.properties>

Make sure you’ve specified the full path to the vault-auth.properties file that you created when installing Vault. Notice that we could have actually stored the vault.token directly in the bootstrap-hashicorp-vault.conf file, but it’s considered better practice to keep your authentication properties separate, in case you decide to rotate your Vault authentication token or other credentials.

At this point, we’ve integrated Vault into NiFi. Now copy this configuration file into nifi-toolkit and we’ll be ready to start encrypting files:

cp nifi-1.15.0/conf/bootstrap-hashicorp-vault.conf nifi-toolkit-1.15.0/conf/

Encrypting files using the HASHICORP_VAULT_KV protection scheme

We will have some sensitive values to protect in nifi-1.15.0/conf/nifi.properties once we start NiFi:

cd nifi-1.15.0
./bin/nifi.sh start
tail -f logs/nifi-app.log

Once you see the following:

2021-10-29 15:12:32,167 INFO [main] org.apache.nifi.web.server.JettyServer NiFi has started. The UI is available at the following URLs:
2021-10-29 15:12:32,167 INFO [main] org.apache.nifi.web.server.JettyServer https://127.0.0.1:8443/nifi

Then Ctrl-C from tailing the log and stop NiFi:

./bin/nifi.sh stop

Now there should be some generated passwords in our nifi-1.15.0/conf/nifi.properties file. We can encrypt them using the following commands:

cd ../nifi-toolkit-1.15.0
# The breakdown of this command is as follows:
# -b specifies the NiFi bootstrap.conf, which specifies nifi.bootstrap.protection.hashicorp.vault.conf=./conf/bootstrap-hashicorp-vault.conf
# -n specifies the nifi.properties file to encrypt
# -o specifies the location to output the encrypted nifi.properties file.  If we left out this argument, it would simply encrypt nifi.properties in place.
# -S specifies the protection scheme.  If we left out this argument, it would use the default AES_GCM protection scheme.
./bin/encrypt-config.sh -b ../nifi-1.15.0/conf/bootstrap.conf \
    -n ../nifi-1.15.0/conf/nifi.properties \
    -o nifi.properties.encrypted \
    -S HASHICORP_VAULT_KV

We’re prompted to enter a password (must be at least 12 characters), which will be used to configure the nifi-1.15.0/conf/bootstrap.conf with a nifi.bootstrap.sensitive.key. This value is not used by the HashiCorp Vault protection scheme, but is required for other protection schemes. Since different properties are permitted to be protected by different protection schemes at the same time, the key is still generated from the password you enter.

After you enter a password, you should see output like the following:

2021/10/28 16:02:33 INFO [main] org.apache.nifi.properties.NiFiPropertiesLoader: Loaded 202 properties from ../nifi-1.15.0/conf/nifi.properties
2021/10/28 16:02:33 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Loaded NiFiProperties instance with 202 properties
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Protected nifi.security.keyPasswd with hashicorp/vault/kv/nifi-kv -> 	nifi-kv/default/nifi.security.keyPasswd
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Updated protection key nifi.security.keyPasswd.protected
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Protected nifi.security.keystorePasswd with hashicorp/vault/kv/nifi-kv -> 	nifi-kv/default/nifi.security.keystorePasswd
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Updated protection key nifi.security.keystorePasswd.protected
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Protected nifi.security.truststorePasswd with hashicorp/vault/kv/nifi-kv -> 	nifi-kv/default/nifi.security.truststorePasswd
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Updated protection key nifi.security.truststorePasswd.protected
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Protected nifi.sensitive.props.key with hashicorp/vault/kv/nifi-kv -> 	nifi-kv/default/nifi.sensitive.props.key
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Updated protection key nifi.sensitive.props.key.protected
2021/10/28 16:02:35 INFO [main] org.apache.nifi.properties.ConfigEncryptionTool: Final result: 205 keys including 4 protected keys

Our new protected properties can be seen in nifi.properties.encrypted:

nifi.security.keystore=./conf/keystore.p12
nifi.security.keystoreType=PKCS12
nifi.security.keystorePasswd=nifi-kv/default/nifi.security.keystorePasswd
nifi.security.keystorePasswd.protected=hashicorp/vault/kv/nifi-kv
nifi.security.keyPasswd=nifi-kv/default/nifi.security.keyPasswd
nifi.security.keyPasswd.protected=hashicorp/vault/kv/nifi-kv
nifi.security.truststore=./conf/truststore.p12
nifi.security.truststoreType=PKCS12
nifi.security.truststorePasswd=nifi-kv/default/nifi.security.truststorePasswd
nifi.security.truststorePasswd.protected=hashicorp/vault/kv/nifi-kv

Notice that the .protected properties indicate hashicorp/vault/kv/nifi-kv, which tells NiFi to use the HashiCorp Vault K/V Sensitive Property Provider using a Vault path prefix of "nifi-kv".

Also observe that the actual property values are simply the Vault paths of the relevant secrets. For example:

nifi.security.keystorePasswd=nifi-kv/default/nifi.security.keystorePasswd

This tells us that the keystore password is now stored in a Vault Secret named nifi-kv/default/nifi.security.keystorePasswd. Well, let’s test it out!

vault kv get nifi-kv/default/nifi.security.keystorePasswd

This produces output like the following:

==== Data ====
Key      Value
---      -----
value    [REDACTED]

Starting NiFi

Now that we’ve successfully encrypted our nifi.properties using HashiCorp Vault, let’s start it up and see it decrypt the values.

cp nifi.properties.encrypted ../nifi-1.15.0/conf/nifi.properties
cd ../nifi-1.15.0
./bin/nifi.sh start
tail -f logs/nifi-app.logs

Since you’ve already configured nifi-1.15.0/conf/bootstrap-hashicorp-vault.conf, NiFi should use that configuration to connect to Vault when it encounters the hashicorp/vault/kv/nifi-kv values in nifi.properties, allowing it to retrieve the protected properties from the Vault server. If everything works as planned, you should be able to view NiFi’s UI at https://localhost:8443/nifi, this time with your properties pulled from the Vault Server at startup.

Other Secrets Managers

With the Apache NiFi 1.15.0 release also come some new sensitive property providers for Azure KeyVault Secrets (AZURE_KEYVAULT_SECRET nifi-toolkit protection scheme) and AWS Secrets Manager (AWS_SECRETSMANAGER nifi-toolkit protection scheme). These providers function very similarly to the one we just saw, storing secrets in their respective cloud provider secrets managers.


blog comments powered by Disqus