gresockj commented on a change in pull request #5202:
URL: https://github.com/apache/nifi/pull/5202#discussion_r666954327



##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/SensitivePropertyProvider.java
##########
@@ -56,4 +56,11 @@
      * @return the raw value to be used by the application
      */
     String unprotect(String protectedValue) throws 
SensitivePropertyProtectionException;
+
+    /**
+     * Closes any clients that may have been opened by the SPP and releases
+     * any resources possibly used by any SPP implementation
+     * Note: If there is nothing to be done, then this function is a no-op
+     */
+    void close();

Review comment:
       What do you think about using slightly more generic language, like 
"Cleans up any resources allocated by the SPP", and naming this `cleanUp()`?

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");

Review comment:
       If you move initialization to the constructor, I believe we'd want to do 
away with this warning.

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";

Review comment:
       Rather than declaring these constants here, what do you think about 
referencing `PropertyProtectionScheme.AWS_KMS.getIdentifier()` and `getName()` 
where these are used below?

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";

Review comment:
       Perhaps just AWS_PREFIX?

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {

Review comment:
       Consider using final for all method parameters

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/AESSensitivePropertyProvider.java
##########
@@ -257,4 +257,14 @@ public static int getMinCipherTextLength() {
     public static String getDelimiter() {
         return DELIMITER;
     }
+
+    /**
+     * Closes any clients that may have been opened by the SPP and releases
+     * any resources possibly used by any SPP implementation
+     * Note: If there is nothing to be done, then this function is a no-op

Review comment:
       Though I understand this is copied from the interface comments, perhaps 
we could provide an implementation-specific comment here instead, like "No 
cleanup necessary".

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;

Review comment:
       I believe these two can be final, since they're set in the constructor.

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()
+                        .credentialsProvider(credentialsProvider)
+                        .build();
+            } catch (SdkClientException e) {
+                // this exception occurs if default credentials are not 
provided
+                logger.error("Default credentials/configuration for AWS are 
invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        }
+    }
+
+    /**
+     * Checks if the client used to communicate with AWS KMS service is open
+     * @return true if the client has been initialized and open, false 
otherwise
+     */
+    private boolean isClientOpen() {
+        return client != null;
+    }
+
+    /**
+     * Validates the key ARN, credentials and configuration provided by the 
user.
+     * Note: This function performs checks on the key and indirectly also 
validates the credentials and
+     * configurations provided during the initialization of the client
+     */
+    private void validate() throws KmsException, 
SensitivePropertyProtectionException {
+        if (!isClientOpen()) {
+            logger.error("The AWS KMS Client failed to open, cannot validate 
key");
+            throw new SensitivePropertyProtectionException("The AWS KMS Client 
failed to open, cannot validate key");
+        }
+        if (StringUtils.isBlank(keyId)) {
+            logger.error("The AWS KMS Key provided is blank");
+            throw new SensitivePropertyProtectionException("The AWS KMS Key 
provided is blank");
+        }
+
+        // asking for a Key Description is the best way to check whether a key 
is valid
+        // because AWS KMS accepts various formats for its keys.
+
+        DescribeKeyRequest request = DescribeKeyRequest.builder()
+                .keyId(keyId)
+                .build();
+
+        // using the KmsClient in a DescribeKey request indirectly also 
verifies if the credentials provided
+        // during the initialization of the key is valid

Review comment:
       are*

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf

Review comment:
       This is valuable documentation -- what do you think about adding the bit 
about "first attempts to use..." to the bootstrap-aws.conf file comments, so 
users will understand this behavior if they try configuring the SPP?

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");

Review comment:
       It would be useful to include the above exception as a cause of this 
one.  Perhaps reword to "Valid credentials/configuration is required to 
initialize KMS client"

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/AbstractHashiCorpVaultSensitivePropertyProvider.java
##########
@@ -129,4 +129,13 @@ public String getIdentifierKey() {
         return getProtectionScheme().getIdentifier(path);
     }
 
+    /**
+     * Closes any clients that may have been opened by the SPP and releases
+     * any resources possibly used by any SPP implementation
+     * Note: If there is nothing to be done, then this function is a no-op
+     */

Review comment:
       Same comment as above

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()
+                        .credentialsProvider(credentialsProvider)
+                        .build();
+            } catch (SdkClientException e) {
+                // this exception occurs if default credentials are not 
provided
+                logger.error("Default credentials/configuration for AWS are 
invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");

Review comment:
       Same comment regarding the exception cause

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);

Review comment:
       Consider using final for all local variables

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()
+                        .credentialsProvider(credentialsProvider)
+                        .build();
+            } catch (SdkClientException e) {
+                // this exception occurs if default credentials are not 
provided
+                logger.error("Default credentials/configuration for AWS are 
invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        }
+    }
+
+    /**
+     * Checks if the client used to communicate with AWS KMS service is open
+     * @return true if the client has been initialized and open, false 
otherwise
+     */
+    private boolean isClientOpen() {
+        return client != null;
+    }
+
+    /**
+     * Validates the key ARN, credentials and configuration provided by the 
user.
+     * Note: This function performs checks on the key and indirectly also 
validates the credentials and
+     * configurations provided during the initialization of the client
+     */
+    private void validate() throws KmsException, 
SensitivePropertyProtectionException {
+        if (!isClientOpen()) {
+            logger.error("The AWS KMS Client failed to open, cannot validate 
key");
+            throw new SensitivePropertyProtectionException("The AWS KMS Client 
failed to open, cannot validate key");
+        }
+        if (StringUtils.isBlank(keyId)) {
+            logger.error("The AWS KMS Key provided is blank");
+            throw new SensitivePropertyProtectionException("The AWS KMS Key 
provided is blank");
+        }
+
+        // asking for a Key Description is the best way to check whether a key 
is valid
+        // because AWS KMS accepts various formats for its keys.
+
+        DescribeKeyRequest request = DescribeKeyRequest.builder()
+                .keyId(keyId)
+                .build();
+
+        // using the KmsClient in a DescribeKey request indirectly also 
verifies if the credentials provided
+        // during the initialization of the key is valid
+        DescribeKeyResponse response = client.describeKey(request);
+        KeyMetadata metadata = response.keyMetadata();
+
+        if (!metadata.enabled()) {
+            throw new SensitivePropertyProtectionException("The key is not 
enabled");
+        }
+    }
+
+    /**
+     * Checks if we have a key ID from AWS KMS and loads it into {@link 
#keyId}. Will load null if key is not present
+     * Note: This function does not verify if the key is correctly 
formatted/valid
+     * @param props the properties representing bootstrap-aws.conf
+     */
+    private void loadRequiredAWSProperties(BootstrapProperties props) {
+        if (props != null) {
+            keyId = props.getProperty(KMS_KEY_PROPS_NAME);
+        }
+    }
+
+
+    /**
+     * Checks bootstrap.conf to check if 
BootstrapPropertyKey.AWS_KMS_SENSITIVE_PROPERTY_PROVIDER_CONF property is
+     * configured to the bootstrap-aws.conf file. Also will try to load 
bootstrap-aws.conf to {@link #awsBootstrapProperties}
+     * @param bootstrapProperties BootstrapProperties object corresponding to 
bootstrap.conf
+     * @return BootstrapProperties object corresponding to bootstrap-aws.conf, 
null otherwise
+     */
+    private BootstrapProperties getAWSBootstrapProperties(BootstrapProperties 
bootstrapProperties) {
+        if (bootstrapProperties == null) {

Review comment:
       Due to the way StandardSensitivePropertyProviderFactory is implemented, 
I don't believe bootstrapProperties can be null here (though it may be 
BootstrapProperties.EMPTY), so I don't think the null check adds value here.

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {

Review comment:
       To encourage this SPP to be used only from the context of the SPP 
factory, let's make the constructor package scoped.

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()
+                        .credentialsProvider(credentialsProvider)
+                        .build();
+            } catch (SdkClientException e) {
+                // this exception occurs if default credentials are not 
provided
+                logger.error("Default credentials/configuration for AWS are 
invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        }
+    }
+
+    /**
+     * Checks if the client used to communicate with AWS KMS service is open
+     * @return true if the client has been initialized and open, false 
otherwise
+     */
+    private boolean isClientOpen() {
+        return client != null;
+    }
+
+    /**
+     * Validates the key ARN, credentials and configuration provided by the 
user.
+     * Note: This function performs checks on the key and indirectly also 
validates the credentials and
+     * configurations provided during the initialization of the client
+     */
+    private void validate() throws KmsException, 
SensitivePropertyProtectionException {
+        if (!isClientOpen()) {
+            logger.error("The AWS KMS Client failed to open, cannot validate 
key");
+            throw new SensitivePropertyProtectionException("The AWS KMS Client 
failed to open, cannot validate key");
+        }
+        if (StringUtils.isBlank(keyId)) {
+            logger.error("The AWS KMS Key provided is blank");
+            throw new SensitivePropertyProtectionException("The AWS KMS Key 
provided is blank");
+        }
+
+        // asking for a Key Description is the best way to check whether a key 
is valid
+        // because AWS KMS accepts various formats for its keys.
+
+        DescribeKeyRequest request = DescribeKeyRequest.builder()
+                .keyId(keyId)
+                .build();
+
+        // using the KmsClient in a DescribeKey request indirectly also 
verifies if the credentials provided
+        // during the initialization of the key is valid
+        DescribeKeyResponse response = client.describeKey(request);
+        KeyMetadata metadata = response.keyMetadata();
+
+        if (!metadata.enabled()) {
+            throw new SensitivePropertyProtectionException("The key is not 
enabled");
+        }
+    }
+
+    /**
+     * Checks if we have a key ID from AWS KMS and loads it into {@link 
#keyId}. Will load null if key is not present
+     * Note: This function does not verify if the key is correctly 
formatted/valid
+     * @param props the properties representing bootstrap-aws.conf
+     */
+    private void loadRequiredAWSProperties(BootstrapProperties props) {
+        if (props != null) {
+            keyId = props.getProperty(KMS_KEY_PROPS_NAME);
+        }
+    }
+
+
+    /**
+     * Checks bootstrap.conf to check if 
BootstrapPropertyKey.AWS_KMS_SENSITIVE_PROPERTY_PROVIDER_CONF property is
+     * configured to the bootstrap-aws.conf file. Also will try to load 
bootstrap-aws.conf to {@link #awsBootstrapProperties}
+     * @param bootstrapProperties BootstrapProperties object corresponding to 
bootstrap.conf
+     * @return BootstrapProperties object corresponding to bootstrap-aws.conf, 
null otherwise
+     */
+    private BootstrapProperties getAWSBootstrapProperties(BootstrapProperties 
bootstrapProperties) {
+        if (bootstrapProperties == null) {
+            logger.warn("The file bootstrap.conf provided to AWS SPP is null");
+            return null;
+        }
+
+        BootstrapProperties cloudBootstrapProperties;
+
+        // Load the bootstrap-aws.conf file based on path specified in
+        // "nifi.bootstrap.protection.aws.kms.conf" property of bootstrap.conf
+        String filePath = 
bootstrapProperties.getProperty(BootstrapPropertyKey.AWS_KMS_SENSITIVE_PROPERTY_PROVIDER_CONF).orElse(null);
+        logger.info("bootstrap-aws.conf file path" + ": " + filePath);

Review comment:
       Recommend removing this logger.info

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;

Review comment:
       I notice you initialize the client in `protect(...)`/`unprotect(...)` 
rather than in the constructor.  Can you provide some background on this 
choice?  Could we instead try to initialize the client in the constructor if 
the required aws properties are found to be configured?  Doing so would allow 
`client` to be declared as final.

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {

Review comment:
       Consider using final for all exceptions

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()
+                        .credentialsProvider(credentialsProvider)
+                        .build();
+            } catch (SdkClientException e) {
+                // this exception occurs if default credentials are not 
provided
+                logger.error("Default credentials/configuration for AWS are 
invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        }
+    }
+
+    /**
+     * Checks if the client used to communicate with AWS KMS service is open
+     * @return true if the client has been initialized and open, false 
otherwise
+     */
+    private boolean isClientOpen() {
+        return client != null;
+    }
+
+    /**
+     * Validates the key ARN, credentials and configuration provided by the 
user.
+     * Note: This function performs checks on the key and indirectly also 
validates the credentials and
+     * configurations provided during the initialization of the client
+     */
+    private void validate() throws KmsException, 
SensitivePropertyProtectionException {
+        if (!isClientOpen()) {
+            logger.error("The AWS KMS Client failed to open, cannot validate 
key");
+            throw new SensitivePropertyProtectionException("The AWS KMS Client 
failed to open, cannot validate key");
+        }
+        if (StringUtils.isBlank(keyId)) {
+            logger.error("The AWS KMS Key provided is blank");
+            throw new SensitivePropertyProtectionException("The AWS KMS Key 
provided is blank");
+        }
+
+        // asking for a Key Description is the best way to check whether a key 
is valid
+        // because AWS KMS accepts various formats for its keys.
+
+        DescribeKeyRequest request = DescribeKeyRequest.builder()
+                .keyId(keyId)
+                .build();
+
+        // using the KmsClient in a DescribeKey request indirectly also 
verifies if the credentials provided
+        // during the initialization of the key is valid
+        DescribeKeyResponse response = client.describeKey(request);
+        KeyMetadata metadata = response.keyMetadata();
+
+        if (!metadata.enabled()) {
+            throw new SensitivePropertyProtectionException("The key is not 
enabled");

Review comment:
       Perhaps `String.format("AWS KMS key [%s] is not enabled", keyId)`

##########
File path: 
nifi-commons/nifi-sensitive-property-provider/src/main/java/org/apache/nifi/properties/aws/AWSSensitivePropertyProvider.java
##########
@@ -0,0 +1,382 @@
+/*
+ * 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.properties.aws;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.properties.AbstractBootstrapPropertiesLoader;
+import org.apache.nifi.properties.AbstractSensitivePropertyProvider;
+import org.apache.nifi.properties.BootstrapProperties;
+import org.apache.nifi.properties.PropertyProtectionScheme;
+import org.apache.nifi.properties.SensitivePropertyProtectionException;
+import org.apache.nifi.properties.BootstrapProperties.BootstrapPropertyKey;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.bouncycastle.util.encoders.DecoderException;
+import org.bouncycastle.util.encoders.EncoderException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.kms.KmsClient;
+import software.amazon.awssdk.services.kms.model.DecryptRequest;
+import software.amazon.awssdk.services.kms.model.DecryptResponse;
+import software.amazon.awssdk.services.kms.model.DescribeKeyRequest;
+import software.amazon.awssdk.services.kms.model.DescribeKeyResponse;
+import software.amazon.awssdk.services.kms.model.EncryptRequest;
+import software.amazon.awssdk.services.kms.model.EncryptResponse;
+import software.amazon.awssdk.services.kms.model.KeyMetadata;
+import software.amazon.awssdk.services.kms.model.KmsException;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Paths;
+
+public class AWSSensitivePropertyProvider extends 
AbstractSensitivePropertyProvider {
+    private static final Logger logger = 
LoggerFactory.getLogger(AWSSensitivePropertyProvider.class);
+
+    private static final String IMPLEMENTATION_NAME = "AWS KMS Sensitive 
Property Provider";
+    private static final String IMPLEMENTATION_KEY = "aws/kms";
+
+    private static final String AWS_KMS_PREFIX = "aws";
+    private static final String ACCESS_KEY_PROPS_NAME = "aws.access.key.id";
+    private static final String SECRET_KEY_PROPS_NAME = "aws.secret.key.id";
+    private static final String REGION_KEY_PROPS_NAME = "aws.region";
+    private static final String KMS_KEY_PROPS_NAME = "aws.kms.key.id";
+
+    private static final Charset PROPERTY_CHARSET = StandardCharsets.UTF_8;
+
+    private KmsClient client;
+    private BootstrapProperties awsBootstrapProperties;
+    private String keyId;
+
+    public AWSSensitivePropertyProvider(BootstrapProperties 
bootstrapProperties) throws SensitivePropertyProtectionException {
+        super(bootstrapProperties);
+        // if either awsBootstrapProperties or keyId is loaded as null values, 
then isSupported will return false
+        awsBootstrapProperties = 
getAWSBootstrapProperties(bootstrapProperties);
+        if (awsBootstrapProperties != null) {
+            loadRequiredAWSProperties(awsBootstrapProperties);
+        }
+    }
+
+    /**
+     * Initializes the KMS Client to be used for encrypt, decrypt and other 
interactions with AWS KMS
+     * First attempts to use default AWS Credentials Provider Chain
+     * If that attempt fails, attempt to initialize credentials using 
bootstrap-aws.conf
+     * Note: This does not verify if credentials are valid
+     */
+    private void initializeClient() {
+        if (awsBootstrapProperties == null) {
+            logger.warn("Cannot initialize client if awsBootstrapProperties is 
null");
+            return;
+        }
+        String accessKeyId = 
awsBootstrapProperties.getProperty(ACCESS_KEY_PROPS_NAME);
+        String secretKeyId = 
awsBootstrapProperties.getProperty(SECRET_KEY_PROPS_NAME);
+        String region = 
awsBootstrapProperties.getProperty(REGION_KEY_PROPS_NAME);
+
+        if (StringUtils.isNotBlank(accessKeyId) && 
StringUtils.isNotBlank(secretKeyId) && StringUtils.isNotBlank(region)) {
+            logger.debug("Credentials/Configuration provided in 
bootstrap-aws.conf");
+            try {
+                AwsBasicCredentials credentials = 
AwsBasicCredentials.create(accessKeyId, secretKeyId);
+                client = KmsClient.builder()
+                        .region(Region.of(region))
+                        
.credentialsProvider(StaticCredentialsProvider.create(credentials))
+                        .build();
+            } catch (KmsException | NullPointerException | 
IllegalArgumentException e) {
+                logger.error("Credentials/Configuration provided in 
bootstrap-aws.conf are invalid");
+                throw new SensitivePropertyProtectionException("Require valid 
credentials/configuration to initialize KMS client");
+            }
+        } else {
+            // attempts to initialize client with credentials provider chain
+            logger.debug("Credentials/Configuration not provided in 
bootstrap-aws.conf, attempting to use default configuration");
+            try {
+                DefaultCredentialsProvider credentialsProvider = 
DefaultCredentialsProvider.builder()
+                        .build();
+                // the following is needed to check the default credential 
builder, if it fails, throws SdkClientException
+                credentialsProvider.resolveCredentials();
+                client = KmsClient.builder()

Review comment:
       Just to confirm, is the region also set when resolving the default 
credentials?

##########
File path: nifi-nar-bundles/nifi-grpc-bundle/nifi-grpc-processors/pom.xml
##########
@@ -75,6 +75,13 @@ language governing permissions and limitations under the 
License. -->
             <artifactId>nifi-mock</artifactId>
             <version>1.14.0-SNAPSHOT</version>
             <scope>test</scope>
+<!--The following is added to make sure the resolve dependencies issues 
bringing in AWS KMS dependency-->

Review comment:
       I think you need to remove "make sure the"




-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to