greyp9 commented on a change in pull request #5110:
URL: https://github.com/apache/nifi/pull/5110#discussion_r644226669



##########
File path: 
nifi-commons/nifi-security-kms/src/main/java/org/apache/nifi/security/kms/reader/StandardFileBasedKeyReader.java
##########
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms.reader;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * Standard File Based Key Reader reads Secret Keys from Properties files 
encrypted using AES-GCM with Tag Size of 128
+ */
+public class StandardFileBasedKeyReader implements FileBasedKeyReader {
+    protected static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    protected static final int IV_LENGTH = 16;
+
+    protected static final int TAG_SIZE = 128;

Review comment:
       // size in bits
   
   suggest clarifying comments to specify the units

##########
File path: 
nifi-commons/nifi-security-kms/src/test/java/org/apache/nifi/security/kms/util/SecretKeyUtils.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.Map;
+import java.util.Properties;
+
+public class SecretKeyUtils {
+    private static final SecureRandom SECURE_RANDOM = new SecureRandom();

Review comment:
       It might better if the lifetime of this is less than the lifetime of the 
process.

##########
File path: 
nifi-commons/nifi-security-kms/src/main/java/org/apache/nifi/security/kms/reader/StandardFileBasedKeyReader.java
##########
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms.reader;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * Standard File Based Key Reader reads Secret Keys from Properties files 
encrypted using AES-GCM with Tag Size of 128
+ */
+public class StandardFileBasedKeyReader implements FileBasedKeyReader {
+    protected static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    protected static final int IV_LENGTH = 16;

Review comment:
       // length in bytes

##########
File path: 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/kms/CryptoUtils.java
##########
@@ -445,7 +331,7 @@ public static boolean constantTimeEquals(byte[] a, byte[] 
b) {
      */
     private static byte[] convertCharsToBytes(char[] chars) {
         CharBuffer charBuffer = CharBuffer.wrap(chars);
-        ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
+        ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);

Review comment:
       +1

##########
File path: 
nifi-commons/nifi-security-kms/src/main/java/org/apache/nifi/security/kms/KeyProviderFactory.java
##########
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms;
+
+import org.apache.commons.codec.DecoderException;
+import 
org.apache.nifi.security.kms.configuration.FileBasedKeyProviderConfiguration;
+import org.apache.nifi.security.kms.configuration.KeyProviderConfiguration;
+import 
org.apache.nifi.security.kms.configuration.KeyStoreKeyProviderConfiguration;
+import 
org.apache.nifi.security.kms.configuration.StaticKeyProviderConfiguration;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.nifi.security.kms.reader.KeyReaderException;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Key Provider Factory
+ */
+public class KeyProviderFactory {
+    private static final String SECRET_KEY_ALGORITHM = "AES";

Review comment:
       This declaration is duplicated in several places in the code.  Should we 
consider consolidating these?  Is "nifi-security-kms" module close enough to 
the base that this might be the place?

##########
File path: 
nifi-commons/nifi-security-utils/src/test/java/org/apache/nifi/security/util/KeyStoreUtilsTest.java
##########
@@ -115,11 +142,30 @@ private void assertKeyEntryStoredLoaded(final KeyStore 
sourceKeyStore, final Key
         assertEquals(String.format("[%s] Public Key not matched", 
sourceKeyStore.getType()), keyPair.getPublic(), 
entryCertificateChain[0].getPublicKey());
     }
 
+    private void assertSecretKeyStoredLoaded(final KeyStore sourceKeyStore, 
final KeyStore destinationKeyStore) throws GeneralSecurityException, 
IOException {
+        sourceKeyStore.load(null, null);
+        final KeyStore.ProtectionParameter protection = 
getProtectionParameter(sourceKeyStore.getType());
+        sourceKeyStore.setEntry(ALIAS, new KeyStore.SecretKeyEntry(secretKey), 
protection);
+
+        final KeyStore copiedKeyStore = copyKeyStore(sourceKeyStore, 
destinationKeyStore);
+        final KeyStore.Entry entry = copiedKeyStore.getEntry(ALIAS, 
protection);
+        assertTrue(String.format("[%s] Secret Key entry not found", 
sourceKeyStore.getType()), entry instanceof KeyStore.SecretKeyEntry);
+    }
+
     private KeyStore copyKeyStore(final KeyStore sourceKeyStore, final 
KeyStore destinationKeyStore) throws GeneralSecurityException, IOException {
         final ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
         sourceKeyStore.store(byteArrayOutputStream, STORE_PASSWORD);
 
         destinationKeyStore.load(new 
ByteArrayInputStream(byteArrayOutputStream.toByteArray()), STORE_PASSWORD);
         return destinationKeyStore;
     }
+
+    private KeyStore.ProtectionParameter getProtectionParameter(final String 
keyStoreType) {
+        if (KeystoreType.PKCS12.getType().equals(keyStoreType)) {
+            // Select Key Protection Algorithm for PKCS12 to avoid unsupported 
algorithm on Java 1.8.0.292

Review comment:
       helpful comment

##########
File path: 
nifi-commons/nifi-security-kms/src/test/java/org/apache/nifi/security/kms/FileBasedKeyProviderTest.java
##########
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms;
+
+import org.apache.nifi.security.kms.util.SecretKeyUtils;
+import org.junit.Test;
+
+import javax.crypto.SecretKey;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class FileBasedKeyProviderTest {
+    private static final String KEYS_EXTENSION = ".keys";
+
+    private static final String KEY_ID = UUID.randomUUID().toString();
+
+    @Test
+    public void testGetKey() throws GeneralSecurityException, IOException {
+        final SecretKey rootKey = SecretKeyUtils.getSecretKey();
+        final SecretKey secretKey = SecretKeyUtils.getSecretKey();
+        final Path secretKeysPath = getSecretKeysPath(rootKey, 
Collections.singletonMap(KEY_ID, secretKey));
+        final FileBasedKeyProvider provider = new 
FileBasedKeyProvider(secretKeysPath, rootKey);
+
+        final SecretKey secretKeyFound = provider.getKey(KEY_ID);
+        assertEquals(secretKey, secretKeyFound);
+        assertTrue(provider.keyExists(KEY_ID));
+        assertFalse(provider.getAvailableKeyIds().isEmpty());
+    }
+
+    private Path getSecretKeysPath(final SecretKey rootKey, final Map<String, 
SecretKey> secretKeys) throws IOException, GeneralSecurityException {
+        final Path path = 
Files.createTempFile(FileBasedKeyProviderTest.class.getSimpleName(), 
KEYS_EXTENSION);
+        path.toFile().deleteOnExit();
+
+        final Properties properties = 
SecretKeyUtils.getEncryptedSecretKeys(rootKey, secretKeys);
+        try (final OutputStream outputStream = new 
FileOutputStream(path.toFile())) {

Review comment:
       Interesting that the base64 trailer bytes are escaped.  But I guess that 
makes sense.
   
   ```
   #Wed Jun 02 14:20:23 EDT 2021
   fdf3bc86-c2ed-43d4-b9af-853cb0b6745a = 
STakjx+cvYMcCrfYgog2hHAgj5e44t1DHfyAzqImW7UI7svXUI1LbUsorsZdqhtR/pkOSgFK/MGXyAi79B3LFw\=\=
   ```
   

##########
File path: nifi-docs/src/main/asciidoc/administration-guide.adoc
##########
@@ -2829,8 +2829,9 @@ NOTE: Unlike the encrypted content and provenance 
repositories, the repository i
 
 |====
 |*Property*|*Description*
-|`nifi.flowfile.repository.encryption.key.provider.implementation`|This is the 
fully-qualified class name of the **key provider**. A key provider is the 
datastore interface for accessing the encryption key to protect the content 
claims. There are currently two implementations -- `StaticKeyProvider` which 
reads a key directly from _nifi.properties_, and `FileBasedKeyProvider` which 
reads *n* many keys from an encrypted file. The interface is extensible, and 
HSM-backed or other providers are expected in the future.
+|`nifi.flowfile.repository.encryption.key.provider.implementation`|This is the 
fully-qualified class name of the **key provider**. A key provider is the 
datastore interface for accessing the encryption key to protect the content 
claims. There are currently three implementations: `StaticKeyProvider` which 
reads a key directly from _nifi.properties_, `FileBasedKeyProvider` which reads 
keys from an encrypted file, and `KeyStoreKeyProvider` which reads keys from an 
encrypted keystore.

Review comment:
       `KeyStoreKeyProvider` which reads keys from a standard, 
password-protected `java.security.Keystore`.

##########
File path: 
nifi-commons/nifi-security-kms/src/test/java/org/apache/nifi/security/kms/util/SecretKeyUtils.java
##########
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.Map;
+import java.util.Properties;
+
+public class SecretKeyUtils {
+    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
+
+    private static final Base64.Encoder ENCODER = Base64.getEncoder();
+
+    private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    private static final String KEY_ALGORITHM = "AES";
+
+    private static final int KEY_LENGTH = 32;
+
+    private static final int IV_LENGTH = 16;
+
+    private static final int TAG_LENGTH = 128;
+
+    /**
+     * Get Encrypted Secret Keys as Properties
+     *
+     * @param rootKey Root Key used to encrypt Secret Keys
+     * @param secretKeys Map of Key Identifier to Secret Key
+     * @return Properties containing encrypted Secret Keys
+     * @throws GeneralSecurityException Thrown on getEncryptedSecretKey()
+     */
+    public static Properties getEncryptedSecretKeys(final SecretKey rootKey, 
final Map<String, SecretKey> secretKeys) throws GeneralSecurityException {
+        final Properties properties = new Properties();
+        for (final Map.Entry<String, SecretKey> secretKeyEntry : 
secretKeys.entrySet()) {
+            final SecretKey secretKey = secretKeyEntry.getValue();
+            final String encryptedSecretKey = getEncryptedSecretKey(rootKey, 
secretKey);
+            properties.setProperty(secretKeyEntry.getKey(), 
encryptedSecretKey);
+        }
+        return properties;
+    }
+
+    /**
+     * Get Random AES Secret Key
+     *
+     * @return Secret Key
+     */
+    public static SecretKey getSecretKey() {
+        final byte[] encodedKey = new byte[KEY_LENGTH];
+        SECURE_RANDOM.nextBytes(encodedKey);
+        return new SecretKeySpec(encodedKey, KEY_ALGORITHM);
+    }
+
+    /**
+     * Get Encrypted Secret Key using AES-GCM with Base64 encoded string 
prefixed with initialization vector
+     *
+     * @param rootKey Root Key used to encrypt Secret Key
+     * @param secretKey Secret Key to be encrypted
+     * @return Base64 encoded and encrypted Secret Key
+     * @throws GeneralSecurityException Thrown when unable to encrypt Secret 
Key
+     */
+    private static String getEncryptedSecretKey(final SecretKey rootKey, final 
SecretKey secretKey) throws GeneralSecurityException {
+        final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+
+        final byte[] initializationVector = new byte[IV_LENGTH];
+        SECURE_RANDOM.nextBytes(initializationVector);
+        cipher.init(Cipher.ENCRYPT_MODE, rootKey, new 
GCMParameterSpec(TAG_LENGTH, initializationVector));
+        final byte[] encryptedSecretKey = 
cipher.doFinal(secretKey.getEncoded());
+
+        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            outputStream.write(initializationVector);
+            outputStream.write(encryptedSecretKey);
+        } catch (final IOException e) {
+            throw new UncheckedIOException(e);

Review comment:
       Would this be better as a GeneralSecurityException?

##########
File path: 
nifi-commons/nifi-security-kms/src/main/java/org/apache/nifi/security/kms/reader/StandardFileBasedKeyReader.java
##########
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.security.kms.reader;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * Standard File Based Key Reader reads Secret Keys from Properties files 
encrypted using AES-GCM with Tag Size of 128
+ */
+public class StandardFileBasedKeyReader implements FileBasedKeyReader {
+    protected static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    protected static final int IV_LENGTH = 16;
+
+    protected static final int TAG_SIZE = 128;
+
+    private static final Base64.Decoder DECODER = Base64.getDecoder();
+
+    private static final String SECRET_KEY_ALGORITHM = "AES";
+
+    /**
+     * Read Secret Keys using provided Root Secret Key
+     *
+     * @param path File Path contains a properties file with Key Identifier 
and Base64-encoded encrypted values
+     * @param rootKey Root Secret Key
+     * @return Map of Key Identifier to decrypted Secret Key
+     */
+    @Override
+    public Map<String, SecretKey> readSecretKeys(final Path path, final 
SecretKey rootKey) {
+        Objects.requireNonNull(path, "Path required");
+        Objects.requireNonNull(rootKey, "Root Key required");
+        final Map<String, SecretKey> secretKeys = new HashMap<>();
+
+        final Properties properties = getProperties(path);
+        for (final String keyId : properties.stringPropertyNames()) {
+            final String encodedProperty = properties.getProperty(keyId);
+            final SecretKey secretKey = readSecretKey(keyId, encodedProperty, 
rootKey);
+            secretKeys.put(keyId, secretKey);
+        }
+        return secretKeys;
+    }
+
+    private Properties getProperties(final Path path) {
+        final Properties properties = new Properties();
+        try (final FileInputStream inputStream = new 
FileInputStream(path.toFile())) {
+            properties.load(inputStream);
+        } catch (final IOException e) {
+            throw new KeyReaderException(String.format("Reading Secret Keys 
Failed [%s]", path), e);
+        }
+        return properties;
+    }
+
+    private SecretKey readSecretKey(final String keyId, final String 
encodedProperty, final SecretKey rootKey) {

Review comment:
       Do you have any plan for a means of writing secret keys in this format?

##########
File path: 
nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/KeyStoreUtils.java
##########
@@ -143,6 +169,27 @@ public static KeyStore loadKeyStore(String keystorePath, 
char[] keystorePassword
         }
     }
 
+    /**
+     * Load {@link KeyStore} containing Secret Key entries using configured 
Security Provider
+     *
+     * @param keystorePath File path to KeyStore
+     * @param keystorePassword Password for loading KeyStore
+     * @param keystoreTypeName Keystore Type Name
+     * @return KeyStore loaded using specified configuration
+     * @throws TlsException Thrown when unable to load KeyStore or unsupported 
Keystore Type
+     */
+    public static KeyStore loadSecretKeyStore(final String keystorePath, final 
char[] keystorePassword, final String keystoreTypeName) throws TlsException {
+        try {
+            final KeyStore keyStore = getSecretKeyStore(keystoreTypeName);
+            try (final InputStream keyStoreStream = new 
FileInputStream(keystorePath)) {
+                keyStore.load(keyStoreStream, keystorePassword);
+            }
+            return keyStore;
+        } catch (final GeneralSecurityException|IOException e) {
+            throw new TlsException(String.format("Loading Secret Keystore [%s] 
Type [%s] Failed", keystorePath, keystoreTypeName), e);

Review comment:
       How about KeyStoreException?  

##########
File path: nifi-docs/src/main/asciidoc/user-guide.adoc
##########
@@ -3001,6 +3029,34 @@ 
key5=c6FzfnKm7UR7xqI2NFpZ+fEKBfSU7+1NvRw+XWQ9U39MONWqk5gvoyOCdFR1kUgeg46jrN5dGXk
 
 Each line defines a key ID and then the Base64-encoded cipher text of a 16 
byte IV and wrapped AES-128, AES-192, or AES-256 key depending on the JCE 
policies available. The individual keys are wrapped by AES/GCM encryption using 
the **root key** defined by `nifi.bootstrap.sensitive.key` in 
_conf/bootstrap.conf_.
 
+==== KeyStoreKeyProvider
+The `KeyStoreKeyProvider` implementation reads from an encrypted keystore 
using the configured password to load AES Secret Key entries.

Review comment:
       ... reads from an encrypted `java.security.KeyStore` using ...

##########
File path: nifi-docs/src/main/asciidoc/user-guide.adoc
##########
@@ -2922,6 +2922,34 @@ 
key5=c6FzfnKm7UR7xqI2NFpZ+fEKBfSU7+1NvRw+XWQ9U39MONWqk5gvoyOCdFR1kUgeg46jrN5dGXk
 
 Each line defines a key ID and then the Base64-encoded cipher text of a 16 
byte IV and wrapped AES-128, AES-192, or AES-256 key depending on the JCE 
policies available. The individual keys are wrapped by AES/GCM encryption using 
the **root key** defined by `nifi.bootstrap.sensitive.key` in 
_conf/bootstrap.conf_.
 
+===== KeyStoreKeyProvider
+The `KeyStoreKeyProvider` implementation reads from an encrypted keystore 
using the configured password to load AES Secret Key entries.
+
+The provider supports the following Keystore Types:
+
+* BCFKS
+* PKCS12
+
+The keystore filename extension must be either `.p12` indicating PKCS12 or 
`.bcfks` indicating BCFKS.
+
+The `keytool` command can be used to generate an AES-256 Secret Key stored in 
a PKCS12 file for repository encryption:
+
+...
+keytool -genseckey -alias primary-key -keyalg AES -keysize 256 -keystore 
repository.p12 -storetype PKCS12

Review comment:
       great idea to provide a command template

##########
File path: nifi-docs/src/main/asciidoc/administration-guide.adoc
##########
@@ -2829,8 +2829,9 @@ NOTE: Unlike the encrypted content and provenance 
repositories, the repository i
 
 |====
 |*Property*|*Description*
-|`nifi.flowfile.repository.encryption.key.provider.implementation`|This is the 
fully-qualified class name of the **key provider**. A key provider is the 
datastore interface for accessing the encryption key to protect the content 
claims. There are currently two implementations -- `StaticKeyProvider` which 
reads a key directly from _nifi.properties_, and `FileBasedKeyProvider` which 
reads *n* many keys from an encrypted file. The interface is extensible, and 
HSM-backed or other providers are expected in the future.
+|`nifi.flowfile.repository.encryption.key.provider.implementation`|This is the 
fully-qualified class name of the **key provider**. A key provider is the 
datastore interface for accessing the encryption key to protect the content 
claims. There are currently three implementations: `StaticKeyProvider` which 
reads a key directly from _nifi.properties_, `FileBasedKeyProvider` which reads 
keys from an encrypted file, and `KeyStoreKeyProvider` which reads keys from an 
encrypted keystore.

Review comment:
       Also propagate below.

##########
File path: nifi-docs/src/main/asciidoc/user-guide.adoc
##########
@@ -2922,6 +2922,34 @@ 
key5=c6FzfnKm7UR7xqI2NFpZ+fEKBfSU7+1NvRw+XWQ9U39MONWqk5gvoyOCdFR1kUgeg46jrN5dGXk
 
 Each line defines a key ID and then the Base64-encoded cipher text of a 16 
byte IV and wrapped AES-128, AES-192, or AES-256 key depending on the JCE 
policies available. The individual keys are wrapped by AES/GCM encryption using 
the **root key** defined by `nifi.bootstrap.sensitive.key` in 
_conf/bootstrap.conf_.
 
+===== KeyStoreKeyProvider
+The `KeyStoreKeyProvider` implementation reads from an encrypted keystore 
using the configured password to load AES Secret Key entries.
+
+The provider supports the following Keystore Types:
+
+* BCFKS
+* PKCS12

Review comment:
       We are discouraging use of JKS?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to