This is an automated email from the ASF dual-hosted git repository. aldrin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nifi-minifi.git
The following commit(s) were added to refs/heads/master by this push: new f50d3f7 MINIFI-501 Provide the ability to specify security and sensitive properties in bootstrap.conf instead of the config.yml f50d3f7 is described below commit f50d3f7c36e18d19eba76a7524ac2dffec61ce68 Author: Aldrin Piri <ald...@apache.org> AuthorDate: Thu Jun 20 08:16:20 2019 -0400 MINIFI-501 Provide the ability to specify security and sensitive properties in bootstrap.conf instead of the config.yml Correct wrong usage of keyPasswd instead of keystorePasswd when creating the statically defined SSL-Context-Service Update nifi version This closes #155. --- .../apache/nifi/minifi/bootstrap/RunMiNiFi.java | 90 ++++++++++++++++- .../minifi/bootstrap/util/ConfigTransformer.java | 25 ++++- .../nifi/minifi/bootstrap/RunMiNiFiTest.java | 102 ++++++++++++++++++++ .../bootstrap/util/ConfigTransformerTest.java | 66 +++++++------ .../bootstrap-ssl-ctx/bootstrap.conf.configured | 24 ++++- .../bootstrap.conf.configured.invalid | 24 ++++- .../bootstrap-ssl-ctx/bootstrap.conf.default | 24 ++++- .../test/resources/bootstrap-ssl-ctx/config.yml | 107 +++++++++++++++++++++ .../src/main/markdown/System_Admin_Guide.md | 30 ++++++ .../src/main/resources/conf/bootstrap.conf | 16 +++ 10 files changed, 459 insertions(+), 49 deletions(-) diff --git a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java index edc1f22..e7ac3ed 100644 --- a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java +++ b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/RunMiNiFi.java @@ -23,6 +23,9 @@ import org.apache.nifi.minifi.bootstrap.configuration.ConfigurationChangeExcepti import org.apache.nifi.minifi.bootstrap.configuration.ConfigurationChangeListener; import org.apache.nifi.minifi.bootstrap.status.PeriodicStatusReporter; import org.apache.nifi.minifi.bootstrap.util.ConfigTransformer; +import org.apache.nifi.minifi.commons.schema.SecurityPropertiesSchema; +import org.apache.nifi.minifi.commons.schema.SensitivePropsSchema; +import org.apache.nifi.minifi.commons.schema.common.CommonPropertyKeys; import org.apache.nifi.minifi.commons.status.FlowStatusReport; import org.apache.nifi.util.Tuple; import org.apache.nifi.util.file.FileUtils; @@ -65,6 +68,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -133,6 +137,59 @@ public class RunMiNiFi implements QueryableStatusAggregator, ConfigurationFileHo public static final String STATUS_REPORTER_PROPERTY_PREFIX = "nifi.minifi.status.reporter"; public static final String STATUS_REPORTER_COMPONENTS_KEY = STATUS_REPORTER_PROPERTY_PREFIX + ".components"; + + public static final String SECURITY_KEYSTORE_KEY = "nifi.minifi.security.keystore"; + public static final String SECURITY_KEYSTORE_TYPE_KEY = "nifi.minifi.security.keystoreType"; + public static final String SECURITY_KEYSTORE_PASSWORD_KEY = "nifi.minifi.security.keystorePasswd"; + public static final String SECURITY_KEY_PASSWORD_KEY = "nifi.minifi.security.keyPasswd"; + public static final String SECURITY_TRUSTSTORE_KEY = "nifi.minifi.security.truststore"; + public static final String SECURITY_TRUSTSTORE_TYPE_KEY = "nifi.minifi.security.truststoreType"; + public static final String SECURITY_TRUSTSTORE_PASSWORD_KEY = "nifi.minifi.security.truststorePasswd"; + public static final String SECURITY_SSL_PROTOCOL_KEY = "nifi.minifi.security.ssl.protocol"; + + public static final String SENSITIVE_PROPS_KEY_KEY = "nifi.minifi.sensitive.props.key"; + public static final String SENSITIVE_PROPS_ALGORITHM_KEY = "nifi.minifi.sensitive.props.algorithm"; + public static final String SENSITIVE_PROPS_PROVIDER_KEY = "nifi.minifi.sensitive.props.provider"; + + public static final Set<String> BOOTSTRAP_SECURITY_PROPERTY_KEYS = new HashSet<>( + Arrays.asList(SECURITY_KEYSTORE_KEY, + SECURITY_KEYSTORE_TYPE_KEY, + SECURITY_KEYSTORE_PASSWORD_KEY, + SECURITY_KEY_PASSWORD_KEY, + SECURITY_TRUSTSTORE_KEY, + SECURITY_TRUSTSTORE_TYPE_KEY, + SECURITY_TRUSTSTORE_PASSWORD_KEY, + SECURITY_SSL_PROTOCOL_KEY)); + + public static final Set<String> BOOTSTRAP_SENSITIVE_PROPERTY_KEYS = new HashSet<>( + Arrays.asList( + SENSITIVE_PROPS_KEY_KEY, + SENSITIVE_PROPS_ALGORITHM_KEY, + SENSITIVE_PROPS_PROVIDER_KEY)); + + + public static final Map<String, String> BOOTSTRAP_KEYS_TO_YML_KEYS; + + static { + final Map<String, String> mutableMap = new HashMap<>(); + mutableMap.put(SECURITY_KEYSTORE_KEY, SecurityPropertiesSchema.KEYSTORE_KEY); + mutableMap.put(SECURITY_KEYSTORE_TYPE_KEY, SecurityPropertiesSchema.KEYSTORE_TYPE_KEY); + mutableMap.put(SECURITY_KEYSTORE_PASSWORD_KEY, SecurityPropertiesSchema.KEYSTORE_PASSWORD_KEY); + mutableMap.put(SECURITY_KEY_PASSWORD_KEY, SecurityPropertiesSchema.KEY_PASSWORD_KEY); + + mutableMap.put(SECURITY_TRUSTSTORE_KEY, SecurityPropertiesSchema.TRUSTSTORE_KEY); + mutableMap.put(SECURITY_TRUSTSTORE_TYPE_KEY, SecurityPropertiesSchema.TRUSTSTORE_TYPE_KEY); + mutableMap.put(SECURITY_TRUSTSTORE_PASSWORD_KEY, SecurityPropertiesSchema.TRUSTSTORE_PASSWORD_KEY); + + mutableMap.put(SECURITY_SSL_PROTOCOL_KEY, SecurityPropertiesSchema.SSL_PROTOCOL_KEY); + + mutableMap.put(SENSITIVE_PROPS_KEY_KEY, SensitivePropsSchema.SENSITIVE_PROPS_KEY_KEY); + mutableMap.put(SENSITIVE_PROPS_ALGORITHM_KEY, SensitivePropsSchema.SENSITIVE_PROPS_ALGORITHM_KEY); + mutableMap.put(SENSITIVE_PROPS_PROVIDER_KEY, SensitivePropsSchema.SENSITIVE_PROPS_PROVIDER_KEY); + + BOOTSTRAP_KEYS_TO_YML_KEYS = Collections.unmodifiableMap(mutableMap); + } + private volatile boolean autoRestartNiFi = true; private volatile int ccPort = -1; private volatile long minifiPid = -1L; @@ -1703,7 +1760,7 @@ public class RunMiNiFi implements QueryableStatusAggregator, ConfigurationFileHo private static ByteBuffer performTransformation(InputStream configIs, String configDestinationPath) throws ConfigurationChangeException, IOException { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - TeeInputStream teeInputStream = new TeeInputStream(configIs, byteArrayOutputStream)) { + TeeInputStream teeInputStream = new TeeInputStream(configIs, byteArrayOutputStream)) { ConfigTransformer.transformConfigFile(teeInputStream, configDestinationPath); @@ -1715,6 +1772,37 @@ public class RunMiNiFi implements QueryableStatusAggregator, ConfigurationFileHo } } + public static Optional<SecurityPropertiesSchema> buildSecurityPropertiesFromBootstrap(final Properties bootstrapProperties) { + + Optional<SecurityPropertiesSchema> securityPropsOptional = Optional.empty(); + + final Map<String, Object> securityProperties = new HashMap<>(); + + BOOTSTRAP_SECURITY_PROPERTY_KEYS.stream() + .filter(key -> StringUtils.isNotBlank(bootstrapProperties.getProperty(key))) + .forEach(key -> + securityProperties.put(BOOTSTRAP_KEYS_TO_YML_KEYS.get(key), bootstrapProperties.getProperty(key)) + ); + + if (!securityProperties.isEmpty()) { + // Determine if sensitive properties were provided + final Map<String, String> sensitiveProperties = new HashMap<>(); + BOOTSTRAP_SENSITIVE_PROPERTY_KEYS.stream() + .filter(key -> StringUtils.isNotBlank(bootstrapProperties.getProperty(key))) + .forEach(key -> + sensitiveProperties.put(BOOTSTRAP_KEYS_TO_YML_KEYS.get(key), bootstrapProperties.getProperty(key)) + ); + if (!sensitiveProperties.isEmpty()) { + securityProperties.put(CommonPropertyKeys.SENSITIVE_PROPS_KEY, sensitiveProperties); + } + + final SecurityPropertiesSchema securityPropertiesSchema = new SecurityPropertiesSchema(securityProperties); + securityPropsOptional = Optional.of(securityPropertiesSchema); + } + + return securityPropsOptional; + } + private static class Status { private final Integer port; diff --git a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformer.java b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformer.java index 90b944e..06856d0 100644 --- a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformer.java +++ b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformer.java @@ -78,7 +78,7 @@ import java.util.zip.GZIPOutputStream; public final class ConfigTransformer { // Underlying version of NIFI will be using - public static final String NIFI_VERSION = "1.4.0"; + public static final String NIFI_VERSION = "1.8.0"; public static final String ROOT_GROUP = "Root-Group"; public static final String DEFAULT_PROV_REPORTING_TASK_CLASS = "org.apache.nifi.reporting.SiteToSiteProvenanceReportingTask"; public static final String NIFI_VERSION_KEY = "nifi.version"; @@ -88,16 +88,31 @@ public final class ConfigTransformer { } public static void transformConfigFile(String sourceFile, String destPath) throws Exception { - File ymlConfigFile = new File(sourceFile); - InputStream ios = new FileInputStream(ymlConfigFile); + transformConfigFile(sourceFile, destPath, null); + } + + public static void transformConfigFile(String sourceFile, String destPath, SecurityPropertiesSchema securityProperties) throws Exception { + final File ymlConfigFile = new File(sourceFile); + final InputStream ios = new FileInputStream(ymlConfigFile); - transformConfigFile(ios, destPath); + transformConfigFile(ios, destPath, securityProperties); } + public static void transformConfigFile(InputStream sourceStream, String destPath) throws Exception { + transformConfigFile(sourceStream, destPath, null); + } + + + public static void transformConfigFile(InputStream sourceStream, String destPath, SecurityPropertiesSchema securityProperties) throws Exception { ConvertableSchema<ConfigSchema> convertableSchema = throwIfInvalid(SchemaLoader.loadConvertableSchemaFromYaml(sourceStream)); ConfigSchema configSchema = throwIfInvalid(convertableSchema.convert()); + // See if we are providing defined properties from the filesystem configurations and use those as the definitive values + if (securityProperties != null) { + configSchema.setSecurityProperties(securityProperties); + } + // Create nifi.properties and flow.xml.gz in memory ByteArrayOutputStream nifiPropertiesOutputStream = new ByteArrayOutputStream(); writeNiFiProperties(configSchema, nifiPropertiesOutputStream); @@ -338,7 +353,7 @@ public final class ConfigTransformer { Map<String, Object> attributes = new HashMap<>(); attributes.put("Keystore Filename", securityProperties.getKeystore()); attributes.put("Keystore Type", securityProperties.getKeystoreType()); - attributes.put("Keystore Password", securityProperties.getKeyPassword()); + attributes.put("Keystore Password", securityProperties.getKeystorePassword()); attributes.put("Truststore Filename", securityProperties.getTruststore()); attributes.put("Truststore Type", securityProperties.getTruststoreType()); attributes.put("Truststore Password", securityProperties.getTruststorePassword()); diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/RunMiNiFiTest.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/RunMiNiFiTest.java new file mode 100644 index 0000000..055bab2 --- /dev/null +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/RunMiNiFiTest.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.minifi.bootstrap; + +import org.apache.nifi.minifi.commons.schema.SecurityPropertiesSchema; +import org.apache.nifi.minifi.commons.schema.SensitivePropsSchema; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; +import java.util.Properties; + +public class RunMiNiFiTest { + + @Test + public void buildSecurityPropertiesNotDefined() throws Exception { + final Properties bootstrapProperties = getTestBootstrapProperties("bootstrap-ssl-ctx/bootstrap.conf.default"); + final Optional<SecurityPropertiesSchema> securityPropsOptional = RunMiNiFi.buildSecurityPropertiesFromBootstrap(bootstrapProperties); + Assert.assertTrue(!securityPropsOptional.isPresent()); + } + + @Test + public void buildSecurityPropertiesDefined() throws Exception { + final Properties bootstrapProperties = getTestBootstrapProperties("bootstrap-ssl-ctx/bootstrap.conf.configured"); + final Optional<SecurityPropertiesSchema> securityPropsOptional = RunMiNiFi.buildSecurityPropertiesFromBootstrap(bootstrapProperties); + Assert.assertTrue(securityPropsOptional.isPresent()); + + final SecurityPropertiesSchema securityPropertiesSchema = securityPropsOptional.get(); + Assert.assertEquals("/my/test/keystore.jks", securityPropertiesSchema.getKeystore()); + Assert.assertEquals("JKS", securityPropertiesSchema.getKeystoreType()); + Assert.assertEquals("mykeystorepassword", securityPropertiesSchema.getKeystorePassword()); + Assert.assertEquals("mykeypassword", securityPropertiesSchema.getKeyPassword()); + + Assert.assertEquals("/my/test/truststore.jks", securityPropertiesSchema.getTruststore()); + Assert.assertEquals("JKS", securityPropertiesSchema.getTruststoreType()); + Assert.assertEquals("mytruststorepassword", securityPropertiesSchema.getTruststorePassword()); + + Assert.assertEquals("TLS", securityPropertiesSchema.getSslProtocol()); + + final SensitivePropsSchema sensitiveProps = securityPropertiesSchema.getSensitiveProps(); + Assert.assertNotNull(sensitiveProps); + + Assert.assertEquals("sensitivepropskey", sensitiveProps.getKey()); + Assert.assertEquals("algo", sensitiveProps.getAlgorithm()); + Assert.assertEquals("BC", sensitiveProps.getProvider()); + + + Assert.assertTrue(securityPropertiesSchema.isValid()); + } + + @Test + public void buildSecurityPropertiesDefinedButInvalid() throws Exception { + final Properties bootstrapProperties = getTestBootstrapProperties("bootstrap-ssl-ctx/bootstrap.conf.configured.invalid"); + final Optional<SecurityPropertiesSchema> securityPropsOptional = RunMiNiFi.buildSecurityPropertiesFromBootstrap(bootstrapProperties); + Assert.assertTrue(securityPropsOptional.isPresent()); + + final SecurityPropertiesSchema securityPropertiesSchema = securityPropsOptional.get(); + Assert.assertEquals("/my/test/keystore.jks", securityPropertiesSchema.getKeystore()); + Assert.assertEquals("NOTAKEYSTORETYPE", securityPropertiesSchema.getKeystoreType()); + Assert.assertEquals("mykeystorepassword", securityPropertiesSchema.getKeystorePassword()); + Assert.assertEquals("mykeypassword", securityPropertiesSchema.getKeyPassword()); + + Assert.assertEquals("/my/test/truststore.jks", securityPropertiesSchema.getTruststore()); + Assert.assertEquals("JKS", securityPropertiesSchema.getTruststoreType()); + Assert.assertEquals("mytruststorepassword", securityPropertiesSchema.getTruststorePassword()); + + final SensitivePropsSchema sensitiveProps = securityPropertiesSchema.getSensitiveProps(); + Assert.assertNotNull(sensitiveProps); + + Assert.assertEquals("sensitivepropskey", sensitiveProps.getKey()); + Assert.assertEquals("algo", sensitiveProps.getAlgorithm()); + Assert.assertEquals("BC", sensitiveProps.getProvider()); + + Assert.assertFalse(securityPropertiesSchema.isValid()); + + } + + public static Properties getTestBootstrapProperties(final String fileName) throws IOException { + final Properties bootstrapProperties = new Properties(); + try (final InputStream fis = RunMiNiFiTest.class.getClassLoader().getResourceAsStream(fileName)) { + bootstrapProperties.load(fis); + } + return bootstrapProperties; + } + +} \ No newline at end of file diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformerTest.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformerTest.java index 3f251cb..b8e5218 100644 --- a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformerTest.java +++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/util/ConfigTransformerTest.java @@ -17,37 +17,6 @@ package org.apache.nifi.minifi.bootstrap.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; - import org.apache.commons.io.FileUtils; import org.apache.nifi.minifi.bootstrap.configuration.ConfigurationChangeException; import org.apache.nifi.minifi.bootstrap.exception.InvalidConfigurationException; @@ -64,11 +33,43 @@ import org.apache.nifi.minifi.commons.schema.common.StringUtil; import org.apache.nifi.minifi.commons.schema.exception.SchemaLoaderException; import org.apache.nifi.minifi.commons.schema.serialization.SchemaLoader; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class ConfigTransformerTest { public static final Map<String, Integer> PG_ELEMENT_ORDER_MAP = generateOrderMap( Arrays.asList("processor", "inputPort", "outputPort", "funnel", "processGroup", "remoteProcessGroup", "connection")); @@ -77,6 +78,9 @@ public class ConfigTransformerTest { private Element config; private DocumentBuilder documentBuilder; + @Rule + final public TemporaryFolder tempOutputFolder = new TemporaryFolder(); + @Before public void setup() throws ParserConfigurationException { documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured similarity index 85% copy from minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf copy to minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured index 5147759..7c5dd13 100644 --- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf +++ b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured @@ -19,7 +19,7 @@ java=java # Username to use when running MiNiFi. This value will be ignored on Windows. -run.as=${minifi.run.as} +run.as= # Configure where MiNiFi's lib and conf directories live # When running as a Windows service set full paths instead of relative paths @@ -33,6 +33,22 @@ graceful.shutdown.seconds=20 # When running as a Windows service use the full path to the file nifi.minifi.config=./conf/config.yml +# Security Properties # +# These properties take precedence over any equivalent properties specified in config.yml # +nifi.minifi.security.keystore=/my/test/keystore.jks +nifi.minifi.security.keystoreType=JKS +nifi.minifi.security.keystorePasswd=mykeystorepassword +nifi.minifi.security.keyPasswd=mykeypassword +nifi.minifi.security.truststore=/my/test/truststore.jks +nifi.minifi.security.truststoreType=JKS +nifi.minifi.security.truststorePasswd=mytruststorepassword +nifi.minifi.security.ssl.protocol=TLS + +nifi.minifi.sensitive.props.key=sensitivepropskey +nifi.minifi.sensitive.props.algorithm=algo +nifi.minifi.sensitive.props.provider=BC + + # Notifiers to use for the associated agent, comma separated list of class names #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.FileChangeIngestor #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.RestChangeIngestor @@ -79,8 +95,8 @@ nifi.minifi.config=./conf/config.yml java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true # JVM memory settings -java.arg.2=-Xms${minifi.jvm.heap.mb}m -java.arg.3=-Xmx${minifi.jvm.heap.mb}m +java.arg.2=-Xms256m +java.arg.3=-Xmx256m # Enable Remote Debugging #java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 @@ -100,4 +116,4 @@ java.arg.7=-Djava.security.egd=file:/dev/urandom #java.arg.13=-XX:+UseG1GC #Set headless mode by default -java.arg.14=-Djava.awt.headless=true +java.arg.14=-Djava.awt.headless=true \ No newline at end of file diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured.invalid similarity index 85% copy from minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf copy to minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured.invalid index 5147759..9428599 100644 --- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf +++ b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.configured.invalid @@ -19,7 +19,7 @@ java=java # Username to use when running MiNiFi. This value will be ignored on Windows. -run.as=${minifi.run.as} +run.as= # Configure where MiNiFi's lib and conf directories live # When running as a Windows service set full paths instead of relative paths @@ -33,6 +33,22 @@ graceful.shutdown.seconds=20 # When running as a Windows service use the full path to the file nifi.minifi.config=./conf/config.yml +# Security Properties # +# These properties take precedence over any equivalent properties specified in config.yml # +nifi.minifi.security.keystore=/my/test/keystore.jks +nifi.minifi.security.keystoreType=NOTAKEYSTORETYPE +nifi.minifi.security.keystorePasswd=mykeystorepassword +nifi.minifi.security.keyPasswd=mykeypassword +nifi.minifi.security.truststore=/my/test/truststore.jks +nifi.minifi.security.truststoreType=JKS +nifi.minifi.security.truststorePasswd=mytruststorepassword +nifi.minifi.security.ssl.protocol=TLS + +nifi.minifi.sensitive.props.key=sensitivepropskey +nifi.minifi.sensitive.props.algorithm=algo +nifi.minifi.sensitive.props.provider=BC + + # Notifiers to use for the associated agent, comma separated list of class names #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.FileChangeIngestor #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.RestChangeIngestor @@ -79,8 +95,8 @@ nifi.minifi.config=./conf/config.yml java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true # JVM memory settings -java.arg.2=-Xms${minifi.jvm.heap.mb}m -java.arg.3=-Xmx${minifi.jvm.heap.mb}m +java.arg.2=-Xms256m +java.arg.3=-Xmx256m # Enable Remote Debugging #java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 @@ -100,4 +116,4 @@ java.arg.7=-Djava.security.egd=file:/dev/urandom #java.arg.13=-XX:+UseG1GC #Set headless mode by default -java.arg.14=-Djava.awt.headless=true +java.arg.14=-Djava.awt.headless=true \ No newline at end of file diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.default similarity index 88% copy from minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf copy to minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.default index 5147759..4b1c658 100644 --- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf +++ b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/bootstrap.conf.default @@ -19,7 +19,7 @@ java=java # Username to use when running MiNiFi. This value will be ignored on Windows. -run.as=${minifi.run.as} +run.as= # Configure where MiNiFi's lib and conf directories live # When running as a Windows service set full paths instead of relative paths @@ -33,6 +33,22 @@ graceful.shutdown.seconds=20 # When running as a Windows service use the full path to the file nifi.minifi.config=./conf/config.yml +# Security Properties # +# These properties take precedence over any equivalent properties specified in config.yml # +nifi.minifi.security.keystore= +nifi.minifi.security.keystoreType= +nifi.minifi.security.keystorePasswd= +nifi.minifi.security.keyPasswd= +nifi.minifi.security.truststore= +nifi.minifi.security.truststoreType= +nifi.minifi.security.truststorePasswd= +nifi.minifi.security.ssl.protocol= + +nifi.minifi.sensitive.props.key= +nifi.minifi.sensitive.props.algorithm= +nifi.minifi.sensitive.props.provider= + + # Notifiers to use for the associated agent, comma separated list of class names #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.FileChangeIngestor #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.RestChangeIngestor @@ -79,8 +95,8 @@ nifi.minifi.config=./conf/config.yml java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true # JVM memory settings -java.arg.2=-Xms${minifi.jvm.heap.mb}m -java.arg.3=-Xmx${minifi.jvm.heap.mb}m +java.arg.2=-Xms256m +java.arg.3=-Xmx256m # Enable Remote Debugging #java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 @@ -100,4 +116,4 @@ java.arg.7=-Djava.security.egd=file:/dev/urandom #java.arg.13=-XX:+UseG1GC #Set headless mode by default -java.arg.14=-Djava.awt.headless=true +java.arg.14=-Djava.awt.headless=true \ No newline at end of file diff --git a/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/config.yml b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/config.yml new file mode 100644 index 0000000..def2666 --- /dev/null +++ b/minifi-bootstrap/src/test/resources/bootstrap-ssl-ctx/config.yml @@ -0,0 +1,107 @@ +# 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. + +MiNiFi Config Version: 3 +Flow Controller: + name: MiNiFi Flow + comment: '' +Core Properties: + flow controller graceful shutdown period: 10 sec + flow service write delay interval: 500 ms + administrative yield duration: 30 sec + bored yield duration: 10 millis + max concurrent threads: 1 + variable registry properties: additional.properties +FlowFile Repository: + partitions: 256 + checkpoint interval: 2 mins + always sync: false + Swap: + threshold: 20000 + in period: 5 sec + in threads: 1 + out period: 5 sec + out threads: 4 +Content Repository: + content claim max appendable size: 10 MB + content claim max flow files: 100 + always sync: false +Provenance Repository: + provenance rollover time: 1 min +Component Status Repository: + buffer size: 1440 + snapshot frequency: 1 min +Security Properties: + keystore: /tmp/ssl/localhost-ks.jks + keystore type: JKS + keystore password: localtest + key password: localtest + truststore: /tmp/ssl/localhost-ts.jks + truststore type: JKS + truststore password: localtest + ssl protocol: TLS + Sensitive Props: + key: '' + algorithm: PBEWITHMD5AND256BITAES-CBC-OPENSSL + provider: BC +Processors: +- id: 94b8e610-b4ed-3ec9-b26f-c839931bf3e2 + name: TailFile + class: org.apache.nifi.processors.standard.TailFile + max concurrent tasks: 1 + scheduling strategy: TIMER_DRIVEN + scheduling period: 1 sec + penalization period: 30 sec + yield period: 1 sec + run duration nanos: 0 + auto-terminated relationships list: [] + Properties: + File to Tail: logs/minifi-app.log + Initial Start Position: Beginning of File + Rolling Filename Pattern: minifi-app* +Connections: +- id: f6cef9b0-8982-391c-8d70-76f33917ac12 + name: TailToS2S + source id: 94b8e610-b4ed-3ec9-b26f-c839931bf3e2 + source relationship names: + - success + destination id: 8644cbcc-a45c-40e0-964d-5e536e2ada61 + max work queue size: 0 + max work queue data size: 1 MB + flowfile expiration: 60 sec + queue prioritizer class: org.apache.nifi.prioritizer.NewestFlowFileFirstPrioritizer +Remote Process Groups: +- id: 94b8e610-b4ed-3ec9-b26f-c839931bf3e3 + name: NiFi Flow + url: https://localhost:8090/nifi + comment: '' + timeout: 30 secs + yield period: 10 sec + Input Ports: + - id: 8644cbcc-a45c-40e0-964d-5e536e2ada61 + name: tailed log + comment: '' + max concurrent tasks: 1 + use compression: false +Provenance Reporting: + comment: '' + scheduling strategy: TIMER_DRIVEN + scheduling period: 30 sec + destination url: https://localhost:8090/ + port name: provenance + originating url: http://${hostname(true)}:8081/nifi + use compression: true + timeout: 30 secs + batch size: 1000 diff --git a/minifi-docs/src/main/markdown/System_Admin_Guide.md b/minifi-docs/src/main/markdown/System_Admin_Guide.md index 6db25c1..f2d694f 100644 --- a/minifi-docs/src/main/markdown/System_Admin_Guide.md +++ b/minifi-docs/src/main/markdown/System_Admin_Guide.md @@ -647,6 +647,36 @@ NiFi Properties Overrides: nifi.database.directory: ./database_repository_override ``` +# Security Configuration +Currently, it is possible to specify keystore and truststore information to allow mutual TLS communication across the Site to Site protocol as well as provisioning an SSL Context for components in the config.yml + +Security can be configured in two ways for instances via: + +* **config.yml**: These properties are specified as outlined in the 'Security Properties' and 'Sensitive Properties' in the config.yml sections above. These allow the specification of security properties to be versioned with the flow and consumed via Change Ingestors. +* **bootstrap.conf**: This is an alternative means of configuration that takes precedence over the config.yml configuration and is a way of separating security concerns from the processing flow. The following properties should be defined: + +## Security Properties in bootstrap.conf + +*bootstrap.conf Property* | *config.yml Property* | *Description* +--------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------- +`nifi.minifi.security.keystore` | `keystore` | The full path and name of the keystore. It is blank by default. +`nifi.minifi.security.keystoreType` | `keystore type` | The keystore type. It is blank by default. +`nifi.minifi.security.keystorePasswd` | `keystore password` | The keystore password. It is blank by default. +`nifi.minifi.security.keyPasswd` | `key password` | The key password. It is blank by default. +`nifi.minifi.security.truststore` | `truststore` | The full path and name of the truststore. It is blank by default. +`nifi.minifi.security.truststoreType` | `truststore type` | The truststore type. It is blank by default. +`nifi.minifi.security.truststorePasswd` | `truststore password` | The truststore password. It is blank by default. +`nifi.minifi.security.ssl.protocol` | `ssl protocol` | The protocol to use when communicating via https. Necessary to transfer provenance securely. + +## Sensitive Property Configuration in bootstrap.conf + +*bootstrap.conf Property* | *config.yml Property* | *Description* +--------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------- +`nifi.minifi.sensitive.props.key` | `key` | This is the password used to encrypt any sensitive property values that are configured in processors. By default, it is blank, but the system administrator should provide a value for it. It can be a string of any length, although the recommended minimum length is 10 characters. Be aware that once this password is set and one or more sensitive processor properties have been configured, this password should not be changed. +`nifi.minifi.sensitive.props.algorithm` | `algorithm` | The algorithm used to encrypt sensitive properties. The default value is `PBEWITHMD5AND256BITAES-CBC-OPENSSL`. +`nifi.minifi.sensitive.props.provider` | `provider` | The sensitive property provider. The default value is `BC`. + + # Running as a Windows Service MiNiFi can run as a Windows service. To do so, you must modify the _conf/bootstrap.conf_ to set absolute paths for some properties. The properties are: diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf index 5147759..e3885aa 100644 --- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf +++ b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf @@ -33,6 +33,22 @@ graceful.shutdown.seconds=20 # When running as a Windows service use the full path to the file nifi.minifi.config=./conf/config.yml +# Security Properties # +# These properties take precedence over any equivalent properties specified in config.yml # +nifi.minifi.security.keystore= +nifi.minifi.security.keystoreType= +nifi.minifi.security.keystorePasswd= +nifi.minifi.security.keyPasswd= +nifi.minifi.security.truststore= +nifi.minifi.security.truststoreType= +nifi.minifi.security.truststorePasswd= +nifi.minifi.security.ssl.protocol= + +nifi.minifi.sensitive.props.key= +nifi.minifi.sensitive.props.algorithm= +nifi.minifi.sensitive.props.provider= + + # Notifiers to use for the associated agent, comma separated list of class names #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.FileChangeIngestor #nifi.minifi.notifier.ingestors=org.apache.nifi.minifi.bootstrap.configuration.ingestors.RestChangeIngestor