Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIFI-12501 Encrypt MiNiFi bootstrap properties #8151

Conversation

ferencerdei
Copy link
Contributor

@ferencerdei ferencerdei commented Dec 12, 2023

Summary

NIFI-12501

This change makes it possible to encrypt bootstrap.conf file. The properties used in bootstrap classes and the MiNiFi framework will handle these (separate bootstrap/minifi property loaders are defined).

Added an encrypt config functionality to the MiNiFi toolkit that generates a random encryption key and encrypts sensitive values in the defined bootstrap.conf.

Tracking

Please complete the following tracking steps prior to pull request creation.

Issue Tracking

Pull Request Tracking

  • Pull Request title starts with Apache NiFi Jira issue number, such as NIFI-00000
  • Pull Request commit message starts with Apache NiFi Jira issue number, as such NIFI-00000

Pull Request Formatting

  • Pull Request based on current revision of the main branch
  • Pull Request refers to a feature branch with one commit containing changes

Verification

Please indicate the verification steps performed prior to pull request creation.

Build

  • Build completed using mvn clean install -P contrib-check
    • JDK 21

Licensing

  • New dependencies are compatible with the Apache License 2.0 according to the License Policy
  • New dependencies are documented in applicable LICENSE and NOTICE files

Documentation

  • Documentation formatting appears as expected in rendered files

@ferencerdei ferencerdei added the minifi Pull requests that updates minifi/c2 codes label Dec 12, 2023
@ferencerdei ferencerdei force-pushed the NIFI-12501_encrypt_minifi_bootstrap_conf_properties branch from 5243f63 to 4b1ffa7 Compare December 12, 2023 15:23
@exceptionfactory exceptionfactory self-requested a review December 12, 2023 16:07
@ferencerdei ferencerdei force-pushed the NIFI-12501_encrypt_minifi_bootstrap_conf_properties branch from 4b1ffa7 to 18421f1 Compare December 12, 2023 18:04
Copy link
Contributor

@exceptionfactory exceptionfactory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting together this new feature @ferencerdei.

As much of the implementation is based on the existing NiFi approach, the code looks straightforward in general. However, there appear to be a few places where copying some of the NiFi approach brought over some elements that may not be needed. This is particularly true of the nifi-property-protection-factory library, which has many transitive dependencies that do not apply to MiNiFi. That is one high-level item that should be addressed. I also noted a handful of other items to consider.

return bootstrapProperties.containsKey(MINIFI_BOOTSTRAP_SENSITIVE_KEY) && !StringUtils.isBlank(bootstrapProperties.getProperty(MINIFI_BOOTSTRAP_SENSITIVE_KEY));
}

private Path createSensitiveKeyFile(File confDir) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for writing out the sensitive key value to a new file as opposed to having the new process read the key from the bootstrap configuration itself? Although NiFi bootstrap has done some similar things with other values, this is not an optimal approach as it makes additional copies on the file system. This is one example of an approach where some additional consideration is worthwhile to implement a better solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep to logic as consistent as possible with the NiFi, so we can easily switch when we change the bootstrap / application properties file structure to the same as in NiFi. But yea, It can be read from bootstrap directly (it could be even in NiFi.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the reply, given that this is a new implementation, although based on the existing one, this is a good opportunity to change the approach for MiNiFi itself.

if (isSensitiveKeyPresent(bootstrapProperties)) {
Path sensitiveKeyFile = createSensitiveKeyFile(confDir);
writeSensitiveKeyFile(bootstrapProperties, sensitiveKeyFile);
sensitiveParameter = "-K " + sensitiveKeyFile.toFile().getAbsolutePath();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in writing the key, it seems like it one option would be to pass the path to the bootstrap configuration and having the called process read the file, instead of creating a new copy of the key in a new file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll apply that change

@ferencerdei ferencerdei force-pushed the NIFI-12501_encrypt_minifi_bootstrap_conf_properties branch from 18421f1 to 66f2596 Compare December 13, 2023 15:09
Copy link
Contributor Author

@ferencerdei ferencerdei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, I've applied the suggested changes

return bootstrapProperties.containsKey(MINIFI_BOOTSTRAP_SENSITIVE_KEY) && !StringUtils.isBlank(bootstrapProperties.getProperty(MINIFI_BOOTSTRAP_SENSITIVE_KEY));
}

private Path createSensitiveKeyFile(File confDir) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep to logic as consistent as possible with the NiFi, so we can easily switch when we change the bootstrap / application properties file structure to the same as in NiFi. But yea, It can be read from bootstrap directly (it could be even in NiFi.)

if (isSensitiveKeyPresent(bootstrapProperties)) {
Path sensitiveKeyFile = createSensitiveKeyFile(confDir);
writeSensitiveKeyFile(bootstrapProperties, sensitiveKeyFile);
sensitiveParameter = "-K " + sensitiveKeyFile.toFile().getAbsolutePath();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll apply that change

Copy link
Contributor

@briansolo1985 briansolo1985 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting together this change. It helps MiNiFi to become more secure by protecting the sensitive properties. I have no issues with the approach, only left some cosmetics related comment.

@@ -41,4 +50,22 @@ public String getProperty(String key) {
.orElseGet(() -> super.getProperty(key));
}

@Override
public String getProperty(String key, String defaultValue) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With introducing this method the previous one could be refactored to

@Override
public String getProperty(String key) {
    return getProperty(key, null);
}

}

public static ProtectedBootstrapProperties loadProtectedProperties(File file) {
if (file == null || !file.exists() || !file.canRead()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is duplicated, and present in the same form in MinifiPropertiesLoader class.
I suggest to create an interface and extract the common code to there.

if (existingValue != null) {
if (existingValue.toString().equals(value.toString())) {
redundantKeys.add(key.toString());
return existingValue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's just a copy paste code, but this return is unnecessary. Practically we always return with value.

.stream()
.filter(entry -> ((String) entry.getKey()).startsWith(JAVA_ARG_KEY_PREFIX))
.map(entry -> (String) entry.getValue())
.filter(entry -> entry.startsWith(JAVA_ARG_KEY_PREFIX))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lamdba variable should now be called key instead of entry

testProperties.put(PULL_HTTP_BASE_KEY + ".override.core", "true");
testProperties.put(FileChangeIngestor.POLLING_PERIOD_INTERVAL_KEY, FileChangeIngestor.DEFAULT_POLLING_PERIOD_INTERVAL);
testProperties.put(MiNiFiProperties.NIFI_MINIFI_FLOW_CONFIG.getKey(), MiNiFiProperties.NIFI_MINIFI_FLOW_CONFIG.getDefaultValue());
when(testProperties.getProperty(FileChangeIngestor.CONFIG_FILE_PATH_KEY)).thenReturn(TEST_CONFIG_PATH);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice refactor

if (shutdownProperty != null) {
properties.setProperty(GRACEFUL_SHUTDOWN_PROP, shutdownProperty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could eliminate the if with Optional.ofNullable(shutdownProperty).orElse(DEFAULT_GRACEFUL_SHUTDOWN_VALUE)

@@ -142,10 +144,7 @@ public void testError() {
// Exception testing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's not your code, but please remove the comment, as it does not hold any additional or valuable information

@@ -63,7 +63,7 @@ public enum MiNiFiProperties {
NIFI_MINIFI_SECURITY_SSL_PROTOCOL("nifi.minifi.security.ssl.protocol", null, false, false, VALID),
NIFI_MINIFI_FLOW_USE_PARENT_SSL("nifi.minifi.flow.use.parent.ssl", null, false, true, VALID),
NIFI_MINIFI_SENSITIVE_PROPS_KEY("nifi.minifi.sensitive.props.key", null, true, false, VALID),
NIFI_MINIFI_SENSITIVE_PROPS_ALGORITHM("nifi.minifi.sensitive.props.algorithm", null, true, false, VALID),
NIFI_MINIFI_SENSITIVE_PROPS_ALGORITHM("nifi.minifi.sensitive.props.algorithm", null, false, false, VALID),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch!

@@ -60,6 +61,87 @@ After downloading the binary and extracting it, to run the MiNiFi Toolkit Conver
## Note
It's not guaranteed in all circumstances that the migration will result in a correct flow. For example if a processor's configuration has changed between version, the conversion tool won't be aware of this, and will use the deprecated property names. You will need to fix such issues manually.

# <a id="encrypt-sensitive-properties-in-bootstrapconf" href="#encrypt-sensitive-properties-in-bootstrapconf">Encrypting Sensitive Properties in bootstrap.conf</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed docs

Copy link
Contributor

@exceptionfactory exceptionfactory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ferencerdei Just a note that this appears close to completion, but there are a couple conflicts at the moment that require rebasing.

…nifi_bootstrap_conf_properties

# Conflicts:
#	minifi/minifi-assembly/README.md
#	minifi/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/ingestors/PullHttpChangeIngestorCommonTest.java
#	minifi/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/ingestors/PullHttpChangeIngestorSSLTest.java
#	minifi/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/ingestors/PullHttpChangeIngestorTest.java
#	minifi/minifi-c2/minifi-c2-assembly/README.md
@ferencerdei
Copy link
Contributor Author

Thanks for the review comments, I resolved the requested changes and conflicts as well.

@briansolo1985
Copy link
Contributor

Thanks for the updates. Looked good to me. Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minifi Pull requests that updates minifi/c2 codes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants