mirror of https://github.com/apache/nifi.git
NIFI-2569 - Multiple instances on same host, range enhancements, nifi.properties incrementing ports NIFI-2569 - Updating main class in windows bat file
This closes #861. Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
parent
b0122c6a73
commit
2fd39676a8
|
@ -33,7 +33,7 @@ goto startConfig
|
|||
:startConfig
|
||||
set LIB_DIR=%~dp0..\classpath;%~dp0..\lib
|
||||
|
||||
SET JAVA_PARAMS=-cp %LIB_DIR%\* -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.toolkit.tls.service.server.TlsCertificateAuthorityService
|
||||
SET JAVA_PARAMS=-cp %LIB_DIR%\* -Xms12m -Xmx24m %JAVA_ARGS% org.apache.nifi.toolkit.tls.TlsToolkitMain
|
||||
|
||||
cmd.exe /C "%JAVA_EXE%" %JAVA_PARAMS% %*
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Comma separated list of properties to put the hostname into
|
||||
hostname.properties=nifi.remote.input.host,nifi.web.https.host,nifi.cluster.node.address
|
||||
|
||||
nifi.web.https.port=9443
|
||||
nifi.remote.input.socket.port=10443
|
||||
nifi.cluster.node.protocol.port=11443
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
|||
*/
|
||||
public class TlsToolkitMain {
|
||||
public static final String DESCRIPTION = "DESCRIPTION";
|
||||
public static final String UNABLE_TO_GET_DESCRIPTION = "Unable to get description. (";
|
||||
private final Map<String, Class<?>> mainMap;
|
||||
|
||||
public TlsToolkitMain() {
|
||||
|
@ -46,7 +47,7 @@ public class TlsToolkitMain {
|
|||
new TlsToolkitMain().doMain(args);
|
||||
}
|
||||
|
||||
private void printUsageAndExit(String message, ExitCode exitCode) {
|
||||
private <T> T printUsageAndExit(String message, ExitCode exitCode) {
|
||||
System.out.println(message);
|
||||
System.out.println();
|
||||
System.out.println("Usage: tls-toolkit service [-h] [args]");
|
||||
|
@ -55,14 +56,32 @@ public class TlsToolkitMain {
|
|||
mainMap.forEach((s, aClass) -> System.out.println(" " + s + ": " + getDescription(aClass)));
|
||||
System.out.println();
|
||||
System.exit(exitCode.ordinal());
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getDescription(Class<?> clazz) {
|
||||
protected String getDescription(Class<?> clazz) {
|
||||
try {
|
||||
Field declaredField = clazz.getDeclaredField(DESCRIPTION);
|
||||
return String.valueOf(declaredField.get(null));
|
||||
} catch (Exception e) {
|
||||
return "Unable to get description. (" + e.getMessage() + ")";
|
||||
return UNABLE_TO_GET_DESCRIPTION + e.getMessage() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Class<?>> getMainMap() {
|
||||
return mainMap;
|
||||
}
|
||||
|
||||
protected Method getMain(String service) {
|
||||
Class<?> mainClass = mainMap.get(service);
|
||||
if (mainClass == null) {
|
||||
printUsageAndExit("Unknown service: " + service, ExitCode.INVALID_ARGS);
|
||||
}
|
||||
|
||||
try {
|
||||
return mainClass.getDeclaredMethod("main", String[].class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return printUsageAndExit("Service " + service + " is missing main method.", ExitCode.SERVICE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,21 +91,9 @@ public class TlsToolkitMain {
|
|||
}
|
||||
|
||||
String service = args[0].toLowerCase();
|
||||
Class<?> mainClass = mainMap.get(service);
|
||||
if (mainClass == null) {
|
||||
printUsageAndExit("Unknown service: " + service, ExitCode.INVALID_ARGS);
|
||||
}
|
||||
|
||||
Method main;
|
||||
try {
|
||||
main = mainClass.getDeclaredMethod("main", String[].class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
printUsageAndExit("Service " + service + " is missing main method.", ExitCode.SERVICE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
main.invoke(null, (Object) args);
|
||||
getMain(service).invoke(null, (Object) args);
|
||||
} catch (IllegalAccessException e) {
|
||||
printUsageAndExit("Service " + service + " has invalid main method.", ExitCode.SERVICE_ERROR);
|
||||
} catch (InvocationTargetException e) {
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.toolkit.tls.configuration;
|
||||
|
||||
import org.apache.nifi.toolkit.tls.standalone.TlsToolkitStandaloneCommandLine;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Contains an instance identifier, a number that either corresponds to the instance identifier or to the global order and relevant passwords
|
||||
*/
|
||||
public class InstanceDefinition {
|
||||
private final InstanceIdentifier instanceIdentifier;
|
||||
private final int number;
|
||||
private final String keyStorePassword;
|
||||
private final String keyPassword;
|
||||
private final String trustStorePassword;
|
||||
|
||||
public InstanceDefinition(InstanceIdentifier instanceIdentifier, int number, String keyStorePassword, String keyPassword, String trustStorePassword) {
|
||||
this.number = number;
|
||||
this.instanceIdentifier = instanceIdentifier;
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
this.keyPassword = keyPassword;
|
||||
this.trustStorePassword = trustStorePassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of instance definitions
|
||||
*
|
||||
* @param fullHostNameExpressions the host expressions defining the global order (null if not relevant)
|
||||
* @param currentHostnameExpressions the host expressions to create instance definitions for
|
||||
* @param keyStorePasswords a supplier for keyStorePasswords
|
||||
* @param keyPasswords a supplier for keyPasswords
|
||||
* @param trustStorePasswords a supplier for trustStorePasswords
|
||||
* @return a list of instance definitions
|
||||
*/
|
||||
public static List<InstanceDefinition> createDefinitions(Stream<String> fullHostNameExpressions, Stream<String> currentHostnameExpressions, Supplier<String> keyStorePasswords,
|
||||
Supplier<String> keyPasswords, Supplier<String> trustStorePasswords) {
|
||||
if (fullHostNameExpressions == null) {
|
||||
return InstanceIdentifier.createIdentifiers(currentHostnameExpressions).map(id -> createDefinition(id, id.getNumber(), keyStorePasswords, keyPasswords, trustStorePasswords))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
Map<InstanceIdentifier, Integer> orderMap = InstanceIdentifier.createOrderMap(fullHostNameExpressions);
|
||||
return InstanceIdentifier.createIdentifiers(currentHostnameExpressions).map(id -> {
|
||||
Integer number = orderMap.get(id);
|
||||
if (number == null) {
|
||||
throw new IllegalArgumentException("Unable to find " + id.getHostname() + " in specified " + TlsToolkitStandaloneCommandLine.GLOBAL_PORT_SEQUENCE_ARG + " expression(s).");
|
||||
}
|
||||
return createDefinition(id, number, keyStorePasswords, keyPasswords, trustStorePasswords);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
protected static InstanceDefinition createDefinition(InstanceIdentifier instanceIdentifier, int number, Supplier<String> keyStorePasswords, Supplier<String> keyPasswords,
|
||||
Supplier<String> trustStorePasswords) {
|
||||
String keyStorePassword = keyStorePasswords.get();
|
||||
String keyPassword;
|
||||
if (keyPasswords == null) {
|
||||
keyPassword = keyStorePassword;
|
||||
} else {
|
||||
keyPassword = keyPasswords.get();
|
||||
}
|
||||
String trustStorePassword = trustStorePasswords.get();
|
||||
return new InstanceDefinition(instanceIdentifier, number, keyStorePassword, keyPassword, trustStorePassword);
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return instanceIdentifier.getHostname();
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public String getKeyStorePassword() {
|
||||
return keyStorePassword;
|
||||
}
|
||||
|
||||
public String getKeyPassword() {
|
||||
return keyPassword;
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return trustStorePassword;
|
||||
}
|
||||
|
||||
public InstanceIdentifier getInstanceIdentifier() {
|
||||
return instanceIdentifier;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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.toolkit.tls.configuration;
|
||||
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Each instance is uniquely identified by its hostname and instance number
|
||||
*/
|
||||
public class InstanceIdentifier {
|
||||
public static final Comparator<InstanceIdentifier> HOST_IDENTIFIER_COMPARATOR = (o1, o2) -> {
|
||||
int i = o1.getHostname().compareTo(o2.getHostname());
|
||||
if (i == 0) {
|
||||
return o1.getNumber() - o2.getNumber();
|
||||
}
|
||||
return i;
|
||||
};
|
||||
private static final Pattern RANGE_PATTERN = Pattern.compile("^[0-9]+(-[0-9]+)?$");
|
||||
private final String hostname;
|
||||
private final int number;
|
||||
|
||||
public InstanceIdentifier(String hostname, int number) {
|
||||
this.hostname = hostname;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a map that can be used to deterministically assign global instance numbers
|
||||
*
|
||||
* @param hostnameExpressions the hostname expressions to expand
|
||||
* @return a map that can be used to deterministically assign global instance numbers
|
||||
*/
|
||||
public static Map<InstanceIdentifier, Integer> createOrderMap(Stream<String> hostnameExpressions) {
|
||||
List<InstanceIdentifier> instanceIdentifiers = createIdentifiers(hostnameExpressions).sorted(HOST_IDENTIFIER_COMPARATOR).collect(Collectors.toList());
|
||||
Map<InstanceIdentifier, Integer> result = new HashMap<>();
|
||||
for (int i = 0; i < instanceIdentifiers.size(); i++) {
|
||||
result.put(instanceIdentifiers.get(i), i + 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a stream of hostname identifiers from a stream of hostname expressions
|
||||
*
|
||||
* @param hostnameExpressions the hostname expressions
|
||||
* @return the hostname identifiers
|
||||
*/
|
||||
public static Stream<InstanceIdentifier> createIdentifiers(Stream<String> hostnameExpressions) {
|
||||
return hostnameExpressions.flatMap(hostnameExpression -> extractHostnames(hostnameExpression).flatMap(hostname -> {
|
||||
ExtractedRange extractedRange = new ExtractedRange(hostname, '(', ')');
|
||||
if (extractedRange.range == null) {
|
||||
return Stream.of(new InstanceIdentifier(hostname, 1));
|
||||
}
|
||||
if (!StringUtils.isEmpty(extractedRange.afterClose)) {
|
||||
throw new IllegalArgumentException("No characters expected after )");
|
||||
}
|
||||
return extractedRange.range.map(numString -> new InstanceIdentifier(extractedRange.beforeOpen, Integer.parseInt(numString)));
|
||||
}));
|
||||
}
|
||||
|
||||
protected static Stream<String> extractHostnames(String hostname) {
|
||||
ExtractedRange extractedRange = new ExtractedRange(hostname, '[', ']');
|
||||
if (extractedRange.range == null) {
|
||||
return Stream.of(hostname);
|
||||
}
|
||||
return extractedRange.range.map(s -> extractedRange.beforeOpen + s + extractedRange.afterClose).flatMap(InstanceIdentifier::extractHostnames);
|
||||
}
|
||||
|
||||
private static Stream<String> extractRange(String range) {
|
||||
if (!RANGE_PATTERN.matcher(range).matches()) {
|
||||
throw new IllegalArgumentException("Expected either one number or two separated by a single hyphen");
|
||||
}
|
||||
String[] split = range.split("-");
|
||||
if (split.length == 1) {
|
||||
String prefix = "1-";
|
||||
if (split[0].charAt(0) == '0') {
|
||||
prefix = String.format("%0" + split[0].length() + "d-", 1);
|
||||
}
|
||||
return extractRange(prefix + split[0]);
|
||||
} else {
|
||||
int baseLength = split[0].length();
|
||||
int low = Integer.parseInt(split[0]);
|
||||
String padding = split[0].substring(0, split[0].length() - Integer.toString(low).length());
|
||||
int high = Integer.parseInt(split[1]);
|
||||
return IntStream.range(low, high + 1).mapToObj(i -> {
|
||||
String s = Integer.toString(i);
|
||||
int length = s.length();
|
||||
if (length >= baseLength) {
|
||||
return s;
|
||||
} else {
|
||||
return padding.substring(0, baseLength - length) + s;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
InstanceIdentifier that = (InstanceIdentifier) o;
|
||||
|
||||
if (number != that.number) return false;
|
||||
return hostname != null ? hostname.equals(that.hostname) : that.hostname == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = hostname != null ? hostname.hashCode() : 0;
|
||||
result = 31 * result + number;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class ExtractedRange {
|
||||
private final String beforeOpen;
|
||||
private final Stream<String> range;
|
||||
private final String afterClose;
|
||||
|
||||
public ExtractedRange(String string, char rangeOpen, char rangeClose) {
|
||||
int openBracket = string.indexOf(rangeOpen);
|
||||
if (openBracket >= 0) {
|
||||
int closeBracket = string.indexOf(rangeClose, openBracket);
|
||||
if (closeBracket < 0) {
|
||||
throw new IllegalArgumentException("Unable to find matching " + rangeClose + " for " + rangeOpen + " in " + string);
|
||||
}
|
||||
beforeOpen = string.substring(0, openBracket);
|
||||
if (closeBracket + 1 < string.length()) {
|
||||
afterClose = string.substring(closeBracket + 1);
|
||||
} else {
|
||||
afterClose = "";
|
||||
}
|
||||
range = extractRange(string.substring(openBracket + 1, closeBracket));
|
||||
} else {
|
||||
beforeOpen = string;
|
||||
range = null;
|
||||
afterClose = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,14 +25,10 @@ import java.util.List;
|
|||
public class StandaloneConfig extends TlsConfig {
|
||||
private File baseDir;
|
||||
private NiFiPropertiesWriterFactory niFiPropertiesWriterFactory;
|
||||
private List<String> hostnames;
|
||||
private List<String> keyStorePasswords;
|
||||
private List<String> keyPasswords;
|
||||
private List<String> trustStorePasswords;
|
||||
private List<InstanceDefinition> instanceDefinitions;
|
||||
private List<String> clientDns;
|
||||
private List<String> clientPasswords;
|
||||
private boolean clientPasswordsGenerated;
|
||||
private int httpsPort;
|
||||
private boolean overwrite;
|
||||
|
||||
public List<String> getClientDns() {
|
||||
|
@ -67,38 +63,6 @@ public class StandaloneConfig extends TlsConfig {
|
|||
this.niFiPropertiesWriterFactory = niFiPropertiesWriterFactory;
|
||||
}
|
||||
|
||||
public List<String> getHostnames() {
|
||||
return hostnames;
|
||||
}
|
||||
|
||||
public void setHostnames(List<String> hostnames) {
|
||||
this.hostnames = hostnames;
|
||||
}
|
||||
|
||||
public List<String> getKeyStorePasswords() {
|
||||
return keyStorePasswords;
|
||||
}
|
||||
|
||||
public void setKeyStorePasswords(List<String> keyStorePasswords) {
|
||||
this.keyStorePasswords = keyStorePasswords;
|
||||
}
|
||||
|
||||
public List<String> getKeyPasswords() {
|
||||
return keyPasswords;
|
||||
}
|
||||
|
||||
public void setKeyPasswords(List<String> keyPasswords) {
|
||||
this.keyPasswords = keyPasswords;
|
||||
}
|
||||
|
||||
public List<String> getTrustStorePasswords() {
|
||||
return trustStorePasswords;
|
||||
}
|
||||
|
||||
public void setTrustStorePasswords(List<String> trustStorePasswords) {
|
||||
this.trustStorePasswords = trustStorePasswords;
|
||||
}
|
||||
|
||||
public List<String> getClientPasswords() {
|
||||
return clientPasswords;
|
||||
}
|
||||
|
@ -107,14 +71,6 @@ public class StandaloneConfig extends TlsConfig {
|
|||
this.clientPasswords = clientPasswords;
|
||||
}
|
||||
|
||||
public int getHttpsPort() {
|
||||
return httpsPort;
|
||||
}
|
||||
|
||||
public void setHttpsPort(int httpsPort) {
|
||||
this.httpsPort = httpsPort;
|
||||
}
|
||||
|
||||
public boolean isClientPasswordsGenerated() {
|
||||
return clientPasswordsGenerated;
|
||||
}
|
||||
|
@ -122,4 +78,12 @@ public class StandaloneConfig extends TlsConfig {
|
|||
public void setClientPasswordsGenerated(boolean clientPasswordsGenerated) {
|
||||
this.clientPasswordsGenerated = clientPasswordsGenerated;
|
||||
}
|
||||
|
||||
public List<InstanceDefinition> getInstanceDefinitions() {
|
||||
return instanceDefinitions;
|
||||
}
|
||||
|
||||
public void setInstanceDefinitions(List<InstanceDefinition> instanceDefinitions) {
|
||||
this.instanceDefinitions = instanceDefinitions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,48 +27,92 @@ import org.apache.nifi.util.StringUtils;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class NifiPropertiesTlsClientConfigWriter implements ConfigurationWriter<TlsClientConfig> {
|
||||
public static final String HOSTNAME_PROPERTIES = "hostname.properties";
|
||||
public static final String OVERLAY_PROPERTIES = "overlay.properties";
|
||||
public static final String CONF = "./conf/";
|
||||
private final NiFiPropertiesWriterFactory niFiPropertiesWriterFactory;
|
||||
private final OutputStreamFactory outputStreamFactory;
|
||||
private final File file;
|
||||
private final File outputFile;
|
||||
private final String hostname;
|
||||
private final int httpsPort;
|
||||
private final int hostNum;
|
||||
private final Properties overlayProperties;
|
||||
private final Set<String> explicitProperties;
|
||||
|
||||
public NifiPropertiesTlsClientConfigWriter(NiFiPropertiesWriterFactory niFiPropertiesWriterFactory, OutputStreamFactory outputStreamFactory, File file, String hostname, int httpsPort) {
|
||||
public NifiPropertiesTlsClientConfigWriter(NiFiPropertiesWriterFactory niFiPropertiesWriterFactory, OutputStreamFactory outputStreamFactory, File outputFile, String hostname, int hostNum)
|
||||
throws IOException {
|
||||
this.niFiPropertiesWriterFactory = niFiPropertiesWriterFactory;
|
||||
this.outputStreamFactory = outputStreamFactory;
|
||||
this.file = file;
|
||||
this.outputFile = outputFile;
|
||||
this.hostname = hostname;
|
||||
this.httpsPort = httpsPort;
|
||||
this.hostNum = hostNum;
|
||||
this.overlayProperties = new Properties();
|
||||
this.overlayProperties.load(getClass().getClassLoader().getResourceAsStream(OVERLAY_PROPERTIES));
|
||||
HashSet<String> explicitProperties = new HashSet<>();
|
||||
explicitProperties.add(HOSTNAME_PROPERTIES);
|
||||
this.explicitProperties = Collections.unmodifiableSet(explicitProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(TlsClientConfig tlsClientConfig) throws IOException {
|
||||
NiFiPropertiesWriter niFiPropertiesWriter = niFiPropertiesWriterFactory.create();
|
||||
updateProperties(niFiPropertiesWriter, tlsClientConfig);
|
||||
try (OutputStream stream = outputStreamFactory.create(file)) {
|
||||
try (OutputStream stream = outputStreamFactory.create(outputFile)) {
|
||||
niFiPropertiesWriter.writeNiFiProperties(stream);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateProperties(NiFiPropertiesWriter niFiPropertiesWriter, TlsClientConfig tlsClientConfig) {
|
||||
Path parentPath = Paths.get(file.getParentFile().getAbsolutePath());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_KEYSTORE, parentPath.relativize(Paths.get(tlsClientConfig.getKeyStore())).toString());
|
||||
protected void updateProperties(NiFiPropertiesWriter niFiPropertiesWriter, TlsClientConfig tlsClientConfig) throws IOException {
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_KEYSTORE, CONF + new File(tlsClientConfig.getKeyStore()).getName());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_KEYSTORE_TYPE, tlsClientConfig.getKeyStoreType());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_KEYSTORE_PASSWD, tlsClientConfig.getKeyStorePassword());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_KEY_PASSWD, tlsClientConfig.getKeyPassword());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_TRUSTSTORE, parentPath.relativize(Paths.get(tlsClientConfig.getTrustStore())).toString());
|
||||
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_TRUSTSTORE, CONF + new File(tlsClientConfig.getTrustStore()).getName());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_TRUSTSTORE_TYPE, tlsClientConfig.getTrustStoreType());
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD, tlsClientConfig.getTrustStorePassword());
|
||||
if (!StringUtils.isEmpty(hostname)) {
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.WEB_HTTPS_HOST, hostname);
|
||||
}
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.WEB_HTTPS_PORT, Integer.toString(httpsPort));
|
||||
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.WEB_HTTP_HOST, "");
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.WEB_HTTP_PORT, "");
|
||||
niFiPropertiesWriter.setPropertyValue(NiFiProperties.SITE_TO_SITE_SECURE, "true");
|
||||
|
||||
getHostnamePropertyStream().forEach(s -> niFiPropertiesWriter.setPropertyValue(s, hostname));
|
||||
|
||||
getPropertyPortMap().entrySet().forEach(nameToPortEntry -> niFiPropertiesWriter.setPropertyValue(nameToPortEntry.getKey(), Integer.toString(nameToPortEntry.getValue())));
|
||||
}
|
||||
|
||||
protected Properties getOverlayProperties() {
|
||||
return overlayProperties;
|
||||
}
|
||||
|
||||
protected Map<String, Integer> getPropertyPortMap() {
|
||||
return overlayProperties.stringPropertyNames().stream().filter(s -> !explicitProperties.contains(s)).collect(Collectors.toMap(Function.identity(), portProperty -> {
|
||||
String portVal = overlayProperties.getProperty(portProperty);
|
||||
int startingPort;
|
||||
try {
|
||||
startingPort = Integer.parseInt(portVal);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new NumberFormatException("Expected numeric values in " + OVERLAY_PROPERTIES + " (" + portProperty + " was " + portVal + ")");
|
||||
}
|
||||
return startingPort + hostNum - 1;
|
||||
}));
|
||||
}
|
||||
|
||||
protected Stream<String> getHostnamePropertyStream() {
|
||||
String hostnamePropertyString = overlayProperties.getProperty(HOSTNAME_PROPERTIES);
|
||||
if (!StringUtils.isEmpty(hostnamePropertyString)) {
|
||||
return Arrays.stream(hostnamePropertyString.split(",")).map(String::trim);
|
||||
}
|
||||
return Stream.of();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.nifi.toolkit.tls.standalone;
|
||||
|
||||
import org.apache.nifi.security.util.CertificateUtils;
|
||||
import org.apache.nifi.toolkit.tls.configuration.InstanceDefinition;
|
||||
import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig;
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
|
||||
|
@ -84,7 +85,6 @@ public class TlsToolkitStandalone {
|
|||
X509Certificate certificate;
|
||||
KeyPair caKeyPair;
|
||||
|
||||
List<String> hostnames = standaloneConfig.getHostnames();
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Running standalone certificate generation with output directory " + baseDir);
|
||||
}
|
||||
|
@ -128,19 +128,22 @@ public class TlsToolkitStandalone {
|
|||
}
|
||||
}
|
||||
|
||||
List<String> keyStorePasswords = standaloneConfig.getKeyStorePasswords();
|
||||
List<String> keyPasswords = standaloneConfig.getKeyPasswords();
|
||||
List<String> trustStorePasswords = standaloneConfig.getTrustStorePasswords();
|
||||
NiFiPropertiesWriterFactory niFiPropertiesWriterFactory = standaloneConfig.getNiFiPropertiesWriterFactory();
|
||||
int httpsPort = standaloneConfig.getHttpsPort();
|
||||
boolean overwrite = standaloneConfig.isOverwrite();
|
||||
|
||||
if (hostnames.isEmpty() && logger.isInfoEnabled()) {
|
||||
List<InstanceDefinition> instanceDefinitions = standaloneConfig.getInstanceDefinitions();
|
||||
if (!instanceDefinitions.isEmpty() && logger.isInfoEnabled()) {
|
||||
logger.info("No " + TlsToolkitStandaloneCommandLine.HOSTNAMES_ARG + " specified, not generating any host certificates or configuration.");
|
||||
}
|
||||
for (int i = 0; i < hostnames.size(); i++) {
|
||||
String hostname = hostnames.get(i);
|
||||
File hostDir = new File(baseDir, hostname);
|
||||
for (InstanceDefinition instanceDefinition : instanceDefinitions) {
|
||||
String hostname = instanceDefinition.getHostname();
|
||||
File hostDir;
|
||||
int hostIdentifierNumber = instanceDefinition.getInstanceIdentifier().getNumber();
|
||||
if (hostIdentifierNumber == 1) {
|
||||
hostDir = new File(baseDir, hostname);
|
||||
} else {
|
||||
hostDir = new File(baseDir, hostname + "_" + hostIdentifierNumber);
|
||||
}
|
||||
|
||||
TlsClientConfig tlsClientConfig = new TlsClientConfig(standaloneConfig);
|
||||
File keystore = new File(hostDir, "keystore." + tlsClientConfig.getKeyStoreType().toLowerCase());
|
||||
|
@ -171,20 +174,20 @@ public class TlsToolkitStandalone {
|
|||
}
|
||||
|
||||
tlsClientConfig.setKeyStore(keystore.getAbsolutePath());
|
||||
tlsClientConfig.setKeyStorePassword(keyStorePasswords.get(i));
|
||||
tlsClientConfig.setKeyPassword(keyPasswords.get(i));
|
||||
tlsClientConfig.setKeyStorePassword(instanceDefinition.getKeyStorePassword());
|
||||
tlsClientConfig.setKeyPassword(instanceDefinition.getKeyPassword());
|
||||
tlsClientConfig.setTrustStore(truststore.getAbsolutePath());
|
||||
tlsClientConfig.setTrustStorePassword(trustStorePasswords.get(i));
|
||||
tlsClientConfig.setTrustStorePassword(instanceDefinition.getTrustStorePassword());
|
||||
TlsClientManager tlsClientManager = new TlsClientManager(tlsClientConfig);
|
||||
KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
|
||||
tlsClientManager.addPrivateKeyToKeyStore(keyPair, NIFI_KEY, CertificateUtils.generateIssuedCertificate(TlsConfig.calcDefaultDn(hostname),
|
||||
keyPair.getPublic(), certificate, caKeyPair, signingAlgorithm, days), certificate);
|
||||
tlsClientManager.setCertificateEntry(NIFI_CERT, certificate);
|
||||
tlsClientManager.addClientConfigurationWriter(new NifiPropertiesTlsClientConfigWriter(niFiPropertiesWriterFactory, outputStreamFactory, new File(hostDir, "nifi.properties"),
|
||||
hostname, httpsPort));
|
||||
hostname, instanceDefinition.getNumber()));
|
||||
tlsClientManager.write(outputStreamFactory);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Successfully generated TLS configuration for " + hostname + ":" + httpsPort + " in " + hostDir);
|
||||
logger.info("Successfully generated TLS configuration for " + hostname + " " + hostIdentifierNumber + " in " + hostDir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.commons.cli.CommandLine;
|
|||
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
import org.apache.nifi.toolkit.tls.configuration.InstanceDefinition;
|
||||
import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig;
|
||||
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
|
||||
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
|
||||
|
@ -33,12 +34,13 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
||||
public static final String OUTPUT_DIRECTORY_ARG = "outputDirectory";
|
||||
|
@ -47,13 +49,12 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
public static final String TRUST_STORE_PASSWORD_ARG = "trustStorePassword";
|
||||
public static final String KEY_PASSWORD_ARG = "keyPassword";
|
||||
public static final String HOSTNAMES_ARG = "hostnames";
|
||||
public static final String HTTPS_PORT_ARG = "httpsPort";
|
||||
public static final String OVERWRITE_ARG = "isOverwrite";
|
||||
public static final String CLIENT_CERT_DN_ARG = "clientCertDn";
|
||||
public static final String CLIENT_CERT_PASSWORD_ARG = "clientCertPassword";
|
||||
public static final String GLOBAL_PORT_SEQUENCE_ARG = "globalPortSequence";
|
||||
|
||||
public static final String DEFAULT_OUTPUT_DIRECTORY = "../" + Paths.get(".").toAbsolutePath().normalize().getFileName().toString();
|
||||
public static final int DEFAULT_HTTPS_PORT = 9091;
|
||||
|
||||
public static final String DESCRIPTION = "Creates certificates and config files for nifi cluster.";
|
||||
|
||||
|
@ -61,12 +62,8 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
|
||||
private final PasswordUtil passwordUtil;
|
||||
private File baseDir;
|
||||
private List<String> hostnames;
|
||||
private int httpsPort;
|
||||
private List<InstanceDefinition> instanceDefinitions;
|
||||
private NiFiPropertiesWriterFactory niFiPropertiesWriterFactory;
|
||||
private List<String> keyStorePasswords;
|
||||
private List<String> keyPasswords;
|
||||
private List<String> trustStorePasswords;
|
||||
private List<String> clientDns;
|
||||
private List<String> clientPasswords;
|
||||
private boolean clientPasswordsGenerated;
|
||||
|
@ -81,13 +78,14 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
this.passwordUtil = passwordUtil;
|
||||
addOptionWithArg("o", OUTPUT_DIRECTORY_ARG, "The directory to output keystores, truststore, config files.", DEFAULT_OUTPUT_DIRECTORY);
|
||||
addOptionWithArg("n", HOSTNAMES_ARG, "Comma separated list of hostnames.");
|
||||
addOptionWithArg("p", HTTPS_PORT_ARG, "Https port to use.", DEFAULT_HTTPS_PORT);
|
||||
addOptionWithArg("f", NIFI_PROPERTIES_FILE_ARG, "Base nifi.properties file to update. (Embedded file identical to the one in a default NiFi install will be used if not specified.)");
|
||||
addOptionWithArg("S", KEY_STORE_PASSWORD_ARG, "Keystore password to use. Must either be one value or one for each host. (autogenerate if not specified)");
|
||||
addOptionWithArg("K", KEY_PASSWORD_ARG, "Key password to use. Must either be one value or one for each host. (autogenerate if not specified)");
|
||||
addOptionWithArg("P", TRUST_STORE_PASSWORD_ARG, "Keystore password to use. Must either be one value or one for each host. (autogenerate if not specified)");
|
||||
addOptionWithArg("C", CLIENT_CERT_DN_ARG, "Generate client certificate suitable for use in browser with specified DN. (Can be specified multiple times.)");
|
||||
addOptionWithArg("B", CLIENT_CERT_PASSWORD_ARG, "Password for client certificate. Must either be one value or one for each client DN. (autogenerate if not specified)");
|
||||
addOptionWithArg("G", GLOBAL_PORT_SEQUENCE_ARG, "Use sequential ports that are calculated for all hosts according to the provided hostname expressions. " +
|
||||
"(Can be specified multiple times, MUST BE SAME FROM RUN TO RUN.)");
|
||||
addOptionNoArg("O", OVERWRITE_ARG, "Overwrite existing host output.");
|
||||
}
|
||||
|
||||
|
@ -114,10 +112,20 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
String outputDirectory = commandLine.getOptionValue(OUTPUT_DIRECTORY_ARG, DEFAULT_OUTPUT_DIRECTORY);
|
||||
baseDir = new File(outputDirectory);
|
||||
|
||||
Stream<String> globalOrderExpressions = null;
|
||||
if (commandLine.hasOption(GLOBAL_PORT_SEQUENCE_ARG)) {
|
||||
globalOrderExpressions = Arrays.stream(commandLine.getOptionValues(GLOBAL_PORT_SEQUENCE_ARG)).flatMap(s -> Arrays.stream(s.split(","))).map(String::trim);
|
||||
}
|
||||
|
||||
if (commandLine.hasOption(HOSTNAMES_ARG)) {
|
||||
hostnames = Collections.unmodifiableList(Arrays.stream(commandLine.getOptionValue(HOSTNAMES_ARG).split(",")).map(String::trim).collect(Collectors.toList()));
|
||||
instanceDefinitions = Collections.unmodifiableList(
|
||||
InstanceDefinition.createDefinitions(globalOrderExpressions,
|
||||
Arrays.stream(commandLine.getOptionValues(HOSTNAMES_ARG)).flatMap(s -> Arrays.stream(s.split(",")).map(String::trim)),
|
||||
parsePasswordSupplier(commandLine, KEY_STORE_PASSWORD_ARG, passwordUtil.passwordSupplier()),
|
||||
parsePasswordSupplier(commandLine, KEY_PASSWORD_ARG, commandLine.hasOption(DIFFERENT_KEY_AND_KEYSTORE_PASSWORDS_ARG) ? passwordUtil.passwordSupplier() : null),
|
||||
parsePasswordSupplier(commandLine, TRUST_STORE_PASSWORD_ARG, passwordUtil.passwordSupplier())));
|
||||
} else {
|
||||
hostnames = Collections.emptyList();
|
||||
instanceDefinitions = Collections.emptyList();
|
||||
}
|
||||
|
||||
String[] clientDnValues = commandLine.getOptionValues(CLIENT_CERT_DN_ARG);
|
||||
|
@ -127,12 +135,6 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
clientDns = Collections.emptyList();
|
||||
}
|
||||
|
||||
httpsPort = getIntValue(commandLine, HTTPS_PORT_ARG, DEFAULT_HTTPS_PORT);
|
||||
|
||||
int numHosts = hostnames.size();
|
||||
keyStorePasswords = Collections.unmodifiableList(getPasswords(KEY_STORE_PASSWORD_ARG, commandLine, numHosts, HOSTNAMES_ARG));
|
||||
keyPasswords = Collections.unmodifiableList(getKeyPasswords(commandLine, keyStorePasswords));
|
||||
trustStorePasswords = Collections.unmodifiableList(getPasswords(TRUST_STORE_PASSWORD_ARG, commandLine, numHosts, HOSTNAMES_ARG));
|
||||
clientPasswords = Collections.unmodifiableList(getPasswords(CLIENT_CERT_PASSWORD_ARG, commandLine, clientDns.size(), CLIENT_CERT_DN_ARG));
|
||||
clientPasswordsGenerated = commandLine.getOptionValues(CLIENT_CERT_PASSWORD_ARG) == null;
|
||||
overwrite = commandLine.hasOption(OVERWRITE_ARG);
|
||||
|
@ -165,11 +167,18 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
return printUsageAndThrow("Expected either 1 value or " + num + " (the number of " + numArg + ") values for " + arg, ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS);
|
||||
}
|
||||
|
||||
private List<String> getKeyPasswords(CommandLine commandLine, List<String> keyStorePasswords) throws CommandLineParseException {
|
||||
if (differentPasswordForKeyAndKeystore() || commandLine.hasOption(KEY_PASSWORD_ARG)) {
|
||||
return getPasswords(KEY_PASSWORD_ARG, commandLine, keyStorePasswords.size(), HOSTNAMES_ARG);
|
||||
private Supplier<String> parsePasswordSupplier(CommandLine commandLine, String option, Supplier<String> defaultSupplier) {
|
||||
if (commandLine.hasOption(option)) {
|
||||
String[] values = commandLine.getOptionValues(option);
|
||||
if (values.length == 1) {
|
||||
return PasswordUtil.passwordSupplier(values[0]);
|
||||
} else {
|
||||
return PasswordUtil.passwordSupplier("Provided " + option + " exhausted, please don't specify " + option
|
||||
+ ", specify one value to be used for all NiFi instances, or specify one value for each NiFi instance.", values);
|
||||
}
|
||||
} else {
|
||||
return defaultSupplier;
|
||||
}
|
||||
return new ArrayList<>(keyStorePasswords);
|
||||
}
|
||||
|
||||
public StandaloneConfig createConfig() {
|
||||
|
@ -177,11 +186,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
|
|||
|
||||
standaloneConfig.setBaseDir(baseDir);
|
||||
standaloneConfig.setNiFiPropertiesWriterFactory(niFiPropertiesWriterFactory);
|
||||
standaloneConfig.setHostnames(hostnames);
|
||||
standaloneConfig.setKeyStorePasswords(keyStorePasswords);
|
||||
standaloneConfig.setKeyPasswords(keyPasswords);
|
||||
standaloneConfig.setTrustStorePasswords(trustStorePasswords);
|
||||
standaloneConfig.setHttpsPort(httpsPort);
|
||||
standaloneConfig.setInstanceDefinitions(instanceDefinitions);
|
||||
standaloneConfig.setOverwrite(overwrite);
|
||||
standaloneConfig.setClientDns(clientDns);
|
||||
standaloneConfig.setClientPasswords(clientPasswords);
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.nifi.toolkit.tls.util;
|
|||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PasswordUtil {
|
||||
private final SecureRandom secureRandom;
|
||||
|
@ -40,4 +42,24 @@ public class PasswordUtil {
|
|||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
public Supplier<String> passwordSupplier() {
|
||||
return () -> generatePassword();
|
||||
}
|
||||
|
||||
public static Supplier<String> passwordSupplier(String password) {
|
||||
return () -> password;
|
||||
}
|
||||
|
||||
public static Supplier<String> passwordSupplier(String exhaustedMessage, String[] passwords) {
|
||||
AtomicInteger index = new AtomicInteger(0);
|
||||
return () -> {
|
||||
int i = index.getAndIncrement();
|
||||
if (i < passwords.length) {
|
||||
return passwords[i];
|
||||
} else {
|
||||
throw new PasswordsExhaustedException(exhaustedMessage);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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.toolkit.tls.util;
|
||||
|
||||
public class PasswordsExhaustedException extends RuntimeException {
|
||||
public PasswordsExhaustedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.toolkit.tls;
|
||||
|
||||
public class ExitException extends SecurityException {
|
||||
// [see http://stackoverflow.com/questions/309396/java-how-to-test-methods-that-call-system-exit#answer-309427]
|
||||
private final int exitCode;
|
||||
|
||||
public ExitException(int exitCode) {
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.nifi.toolkit.tls;
|
||||
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.security.Permission;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class SystemExitCapturer implements Closeable {
|
||||
private final SecurityManager originalSecurityManager;
|
||||
|
||||
public SystemExitCapturer() {
|
||||
originalSecurityManager = System.getSecurityManager();
|
||||
// [see http://stackoverflow.com/questions/309396/java-how-to-test-methods-that-call-system-exit#answer-309427]
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm, Object context) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkExit(int status) {
|
||||
super.checkExit(status);
|
||||
throw new ExitException(status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void runAndAssertExitCode(Runnable runnable, ExitCode exitCode) {
|
||||
try {
|
||||
runnable.run();
|
||||
fail("Expecting exit code " + exitCode);
|
||||
} catch (ExitException e) {
|
||||
assertEquals("Expecting exit code: " + exitCode + ", got " + ExitCode.values()[e.getExitCode()], exitCode.ordinal(), e.getExitCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
System.setSecurityManager(originalSecurityManager);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.toolkit.tls;
|
||||
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TlsToolkitMainTest {
|
||||
private TlsToolkitMain tlsToolkitMain;
|
||||
private SystemExitCapturer systemExitCapturer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
systemExitCapturer = new SystemExitCapturer();
|
||||
tlsToolkitMain = new TlsToolkitMain();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws IOException {
|
||||
systemExitCapturer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllMainClassesHaveDescription() {
|
||||
tlsToolkitMain.getMainMap().values().forEach(mainClass -> {
|
||||
String description = tlsToolkitMain.getDescription(mainClass);
|
||||
assertFalse(StringUtils.isEmpty(description));
|
||||
assertFalse(description.contains(TlsToolkitMain.UNABLE_TO_GET_DESCRIPTION));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDescriptionClassWithNoDescription() {
|
||||
assertTrue(tlsToolkitMain.getDescription(TlsToolkitMainTest.class).startsWith(TlsToolkitMain.UNABLE_TO_GET_DESCRIPTION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllMainClassesHaveMain() {
|
||||
tlsToolkitMain.getMainMap().keySet().stream().map(String::toLowerCase).forEach(service -> {
|
||||
assertNotNull(tlsToolkitMain.getMain(service));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongServiceName() {
|
||||
systemExitCapturer.runAndAssertExitCode(() -> tlsToolkitMain.doMain(new String[] {"fakeService"}), ExitCode.INVALID_ARGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoArguments() {
|
||||
systemExitCapturer.runAndAssertExitCode(() -> tlsToolkitMain.doMain(new String[0]), ExitCode.INVALID_ARGS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInaccessibleMain() {
|
||||
String privateMain = "privatemain";
|
||||
tlsToolkitMain.getMainMap().put(privateMain, PrivateMain.class);
|
||||
systemExitCapturer.runAndAssertExitCode(() -> tlsToolkitMain.doMain(new String[]{privateMain}), ExitCode.SERVICE_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvocationTargetException() {
|
||||
String throwingMain = "throwingmain";
|
||||
tlsToolkitMain.getMainMap().put(throwingMain, ThrowingMain.class);
|
||||
systemExitCapturer.runAndAssertExitCode(() -> tlsToolkitMain.doMain(new String[]{throwingMain}), ExitCode.SERVICE_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoMain() {
|
||||
String noMain = "nomain";
|
||||
tlsToolkitMain.getMainMap().put(noMain, NoMain.class);
|
||||
systemExitCapturer.runAndAssertExitCode(() -> tlsToolkitMain.doMain(new String[]{noMain}), ExitCode.SERVICE_ERROR);
|
||||
}
|
||||
|
||||
private static class PrivateMain {
|
||||
private static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThrowingMain {
|
||||
public static void main(String[] args) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoMain {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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.toolkit.tls.configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class InstanceDefinitionTest {
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionKeyPassword() {
|
||||
testCreateDefinition("testHostname", 4, "keyStorePassword", "keyPassword", "trustStorePassword");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionNoKeyPassword() {
|
||||
testCreateDefinition("testHostname", 5, "keyStorePassword", null, "trustStorePassword");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostSingleName() {
|
||||
testCreateDefinitions(Arrays.asList("hostname"), Arrays.asList("hostname"), Arrays.asList(1), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostnameOneNumberInParens() {
|
||||
testCreateDefinitions(Arrays.asList("hostname(20)"),
|
||||
IntStream.range(1, 21).mapToObj(operand -> "hostname").collect(Collectors.toList()),
|
||||
integerRange(1, 20).collect(Collectors.toList()), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostnameTwoNumbersInParens() {
|
||||
testCreateDefinitions(Arrays.asList("hostname(5-20)"),
|
||||
IntStream.range(5, 21).mapToObj(operand -> "hostname").collect(Collectors.toList()),
|
||||
integerRange(5, 20).collect(Collectors.toList()), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsMultipleHostnamesWithMultipleNumbers() {
|
||||
testCreateDefinitions(Arrays.asList("host[10]name[02-5](20)"),
|
||||
integerRange(1, 10).flatMap(v -> integerRange(2, 5).flatMap(v2 -> integerRange(1, 20).map(v3 -> "host" + v + "name" + String.format("%02d", v2)))).collect(Collectors.toList()),
|
||||
integerRange(1, 10).flatMap(val -> integerRange(2, 5).flatMap(val2 -> integerRange(1, 20))).collect(Collectors.toList()), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsStream() {
|
||||
testCreateDefinitions(Arrays.asList("host", "name"), Arrays.asList("host", "name"), Arrays.asList(1, 1), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsStreamNonNullKeyPasswords() {
|
||||
testCreateDefinitions(Arrays.asList("host", "name"), Arrays.asList("host", "name"), Arrays.asList(1, 1), false);
|
||||
}
|
||||
|
||||
private Stream<Integer> integerRange(int start, int endInclusive) {
|
||||
return IntStream.range(start, endInclusive + 1).mapToObj(value -> value);
|
||||
}
|
||||
|
||||
private void testCreateDefinitions(List<String> hostnameExpressions, List<String> expectedHostnames, List<Integer> expectedNumbers, boolean nullForKeyPasswords) {
|
||||
List<String> keyStorePasswords = IntStream.range(0, expectedHostnames.size()).mapToObj(value -> "testKeyStorePassword" + value).collect(Collectors.toList());
|
||||
List<String> keyPasswords;
|
||||
if (nullForKeyPasswords) {
|
||||
keyPasswords = null;
|
||||
} else {
|
||||
keyPasswords = IntStream.range(0, expectedHostnames.size()).mapToObj(value -> "testKeyPassword" + value).collect(Collectors.toList());
|
||||
}
|
||||
List<String> trustStorePasswords = IntStream.range(0, expectedHostnames.size()).mapToObj(value -> "testTrustStorePassword" + value).collect(Collectors.toList());
|
||||
List<InstanceDefinition> instanceDefinitions = InstanceDefinition.createDefinitions(null, hostnameExpressions.stream(),
|
||||
mockSupplier(keyStorePasswords.toArray(new String[keyStorePasswords.size()])), keyPasswords == null ? null : mockSupplier(keyPasswords.toArray(new String[keyPasswords.size()])),
|
||||
mockSupplier(trustStorePasswords.toArray(new String[trustStorePasswords.size()])));
|
||||
testCreateDefinitionsOutput(instanceDefinitions, expectedHostnames, expectedNumbers, keyStorePasswords, keyPasswords, trustStorePasswords);
|
||||
}
|
||||
|
||||
private void testCreateDefinitionsOutput(List<InstanceDefinition> instanceDefinitions, List<String> expectedHostnames, List<Integer> expectedNumbers, List<String> keyStorePasswords,
|
||||
List<String> keyPasswords, List<String> trustStorePasswords) {
|
||||
assertEquals(instanceDefinitions.size(), expectedHostnames.size());
|
||||
for (int i = 0; i < instanceDefinitions.size(); i++) {
|
||||
assertDefinitionEquals(instanceDefinitions.get(i), expectedHostnames.get(i), expectedNumbers.get(i), keyStorePasswords.get(i),
|
||||
keyPasswords == null ? null : keyPasswords.get(i), trustStorePasswords.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void testCreateDefinition(String hostname, int num, String keyStorePassword, String keyPassword, String trustStorePassword) {
|
||||
InstanceDefinition definition = InstanceDefinition.createDefinition(new InstanceIdentifier(hostname, num), num, mockSupplier(keyStorePassword),
|
||||
keyPassword == null ? null : mockSupplier(keyPassword), mockSupplier(trustStorePassword));
|
||||
assertDefinitionEquals(definition, hostname, num, keyStorePassword, keyPassword, trustStorePassword);
|
||||
}
|
||||
|
||||
private void assertDefinitionEquals(InstanceDefinition definition, String hostname, int num, String keyStorePassword, String keyPassword, String trustStorePassword) {
|
||||
assertEquals(hostname, definition.getHostname());
|
||||
assertEquals(num, definition.getNumber());
|
||||
assertEquals(keyStorePassword, definition.getKeyStorePassword());
|
||||
assertEquals(keyPassword == null ? keyStorePassword : keyPassword, definition.getKeyPassword());
|
||||
assertEquals(trustStorePassword, definition.getTrustStorePassword());
|
||||
}
|
||||
|
||||
private <T> Supplier<T> mockSupplier(T... values) {
|
||||
Supplier<T> supplier = mock(Supplier.class);
|
||||
if (values.length == 1) {
|
||||
when(supplier.get()).thenReturn(values[0]);
|
||||
} else if (values.length > 1) {
|
||||
when(supplier.get()).thenReturn(values[0], Arrays.copyOfRange(values, 1, values.length));
|
||||
}
|
||||
return supplier;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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.toolkit.tls.configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class InstanceIdentifierTest {
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesSingle() {
|
||||
testExtractHostnames("test[1-3]", "test1", "test2", "test3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesPadding() {
|
||||
testExtractHostnames("test[0001-3]", "test0001", "test0002", "test0003");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesLowGreaterThanHigh() {
|
||||
testExtractHostnames("test[3-1]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesLowEqualToHigh() {
|
||||
testExtractHostnames("test[3-3]", "test3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesSingleNumber() {
|
||||
testExtractHostnames("test[2]", "test1", "test2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesSingleNumberPadding() {
|
||||
testExtractHostnames("test[002]", "test001", "test002");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testExtractHostnamesNoNumber() {
|
||||
testExtractHostnames("test[]", "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractHostnamesMultiple() {
|
||||
testExtractHostnames("test[1-3]name[1-3]", "test1name1", "test1name2", "test1name3", "test2name1", "test2name2", "test2name3", "test3name1", "test3name2", "test3name3");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testExtractHostnamesUnmatched() {
|
||||
testExtractHostnames("test[");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testExtractHostnamesSpace() {
|
||||
testExtractHostnames("test[ 1-2]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testExtractHostnamesMultipleHyphens() {
|
||||
testExtractHostnames("test[1-2-3]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostSingleName() {
|
||||
testCreateIdentifiers(Arrays.asList("hostname"), Arrays.asList("hostname"), Arrays.asList(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostnameOneNumberInParens() {
|
||||
testCreateIdentifiers(Arrays.asList("hostname(20)"),
|
||||
IntStream.range(1, 21).mapToObj(operand -> "hostname").collect(Collectors.toList()),
|
||||
integerRange(1, 20).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsSingleHostnameTwoNumbersInParens() {
|
||||
testCreateIdentifiers(Arrays.asList("hostname(5-20)"),
|
||||
IntStream.range(5, 21).mapToObj(operand -> "hostname").collect(Collectors.toList()),
|
||||
integerRange(5, 20).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsMultipleHostnamesWithMultipleNumbers() {
|
||||
testCreateIdentifiers(Arrays.asList("host[10]name[02-5](20)"),
|
||||
integerRange(1, 10).flatMap(v -> integerRange(2, 5).flatMap(v2 -> integerRange(1, 20).map(v3 -> "host" + v + "name" + String.format("%02d", v2)))).collect(Collectors.toList()),
|
||||
integerRange(1, 10).flatMap(val -> integerRange(2, 5).flatMap(val2 -> integerRange(1, 20))).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefinitionsStream() {
|
||||
testCreateIdentifiers(Arrays.asList("host", "name"), Arrays.asList("host", "name"), Arrays.asList(1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOrderMap() {
|
||||
String abc123 = "abc[1-3]";
|
||||
String abc0123 = "abc[01-3]";
|
||||
String b = "b";
|
||||
|
||||
Map<InstanceIdentifier, Integer> orderMap = InstanceIdentifier.createOrderMap(Stream.of(abc123, abc0123 + "(2)", b));
|
||||
|
||||
AtomicInteger num = new AtomicInteger(1);
|
||||
Consumer<InstanceIdentifier> action = id -> {
|
||||
int i = num.getAndIncrement();
|
||||
assertEquals(i, orderMap.get(id).intValue());
|
||||
};
|
||||
|
||||
InstanceIdentifier.extractHostnames(abc0123).flatMap(s -> Stream.of(new InstanceIdentifier(s, 1), new InstanceIdentifier(s, 2))).forEach(action);
|
||||
InstanceIdentifier.extractHostnames(abc123).map(s -> new InstanceIdentifier(s, 1)).forEach(action);
|
||||
InstanceIdentifier.extractHostnames(b).map(s -> new InstanceIdentifier(s, 1)).forEach(action);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateIdentifiersCharactersAfterNumber() {
|
||||
InstanceIdentifier.createIdentifiers(Stream.of("test(2)a")).count();
|
||||
}
|
||||
|
||||
private Stream<Integer> integerRange(int start, int endInclusive) {
|
||||
return IntStream.range(start, endInclusive + 1).mapToObj(value -> value);
|
||||
}
|
||||
|
||||
private void testExtractHostnames(String hostnameWithRange, String... expectedHostnames) {
|
||||
assertEquals(Stream.of(expectedHostnames).collect(Collectors.toList()), InstanceIdentifier.extractHostnames(hostnameWithRange).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private void testCreateIdentifiers(List<String> hostnameExpressions, List<String> expectedHostnames, List<Integer> expectedNumbers) {
|
||||
List<InstanceIdentifier> instanceIdentifiers = InstanceIdentifier.createIdentifiers(hostnameExpressions.stream()).collect(Collectors.toList());
|
||||
assertEquals(instanceIdentifiers.size(), expectedHostnames.size());
|
||||
for (int i = 0; i < instanceIdentifiers.size(); i++) {
|
||||
InstanceIdentifier identifier = instanceIdentifiers.get(i);
|
||||
assertEquals(expectedHostnames.get(i), identifier.getHostname());
|
||||
assertEquals((int) expectedNumbers.get(i), identifier.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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.toolkit.tls.manager.writer;
|
||||
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
|
||||
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriter;
|
||||
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
|
||||
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NifiPropertiesTlsClientConfigWriterTest {
|
||||
@Mock
|
||||
NiFiPropertiesWriterFactory niFiPropertiesWriterFactory;
|
||||
@Mock
|
||||
OutputStreamFactory outputStreamFactory;
|
||||
private NiFiPropertiesWriter niFiPropertiesWriter;
|
||||
private int hostNum;
|
||||
private String testHostname;
|
||||
private File outputFile;
|
||||
private NifiPropertiesTlsClientConfigWriter nifiPropertiesTlsClientConfigWriter;
|
||||
private TlsClientConfig tlsClientConfig;
|
||||
private ByteArrayOutputStream outputStream;
|
||||
private String keyStore;
|
||||
private String keyStorePassword;
|
||||
private String trustStore;
|
||||
private String trustStorePassword;
|
||||
private Properties overlayProperties;
|
||||
private String keyPassword;
|
||||
private String keyStoreType;
|
||||
private String trustStoreType;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
testHostname = "testHostname";
|
||||
hostNum = 22;
|
||||
|
||||
keyStore = "testKeyStore.jks";
|
||||
keyStoreType = TlsConfig.DEFAULT_KEY_STORE_TYPE;
|
||||
keyStorePassword = "badKeyStorePassword";
|
||||
keyPassword = "badKeyPassword";
|
||||
|
||||
trustStore = "testTrustStore.jks";
|
||||
trustStoreType = TlsConfig.DEFAULT_KEY_STORE_TYPE;
|
||||
trustStorePassword = "badTrustStorePassword";
|
||||
|
||||
outputFile = File.createTempFile("temp", "nifi");
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
when(outputStreamFactory.create(outputFile)).thenReturn(outputStream);
|
||||
|
||||
tlsClientConfig = new TlsClientConfig();
|
||||
tlsClientConfig.setKeyStore(keyStore);
|
||||
tlsClientConfig.setKeyStoreType(keyStoreType);
|
||||
tlsClientConfig.setKeyStorePassword(keyStorePassword);
|
||||
tlsClientConfig.setKeyPassword(keyPassword);
|
||||
|
||||
tlsClientConfig.setTrustStore(trustStore);
|
||||
tlsClientConfig.setTrustStoreType(trustStoreType);
|
||||
tlsClientConfig.setTrustStorePassword(trustStorePassword);
|
||||
|
||||
niFiPropertiesWriter = new NiFiPropertiesWriter(new ArrayList<>());
|
||||
when(niFiPropertiesWriterFactory.create()).thenReturn(niFiPropertiesWriter);
|
||||
nifiPropertiesTlsClientConfigWriter = new NifiPropertiesTlsClientConfigWriter(niFiPropertiesWriterFactory, outputStreamFactory, outputFile, testHostname, hostNum);
|
||||
overlayProperties = nifiPropertiesTlsClientConfigWriter.getOverlayProperties();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaults() throws IOException {
|
||||
nifiPropertiesTlsClientConfigWriter.write(tlsClientConfig);
|
||||
testHostnamesAndPorts();
|
||||
assertNotEquals(0, nifiPropertiesTlsClientConfigWriter.getPropertyPortMap().size());
|
||||
}
|
||||
|
||||
@Test(expected = NumberFormatException.class)
|
||||
public void testBadPortNum() throws IOException {
|
||||
nifiPropertiesTlsClientConfigWriter.getOverlayProperties().setProperty(nifiPropertiesTlsClientConfigWriter.getPropertyPortMap().keySet().iterator().next(), "notAnInt");
|
||||
nifiPropertiesTlsClientConfigWriter.write(tlsClientConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoHostnameProperties() throws IOException {
|
||||
nifiPropertiesTlsClientConfigWriter.getOverlayProperties().setProperty(NifiPropertiesTlsClientConfigWriter.HOSTNAME_PROPERTIES, "");
|
||||
nifiPropertiesTlsClientConfigWriter.write(tlsClientConfig);
|
||||
testHostnamesAndPorts();
|
||||
Properties nifiProperties = getNifiProperties();
|
||||
nifiProperties.stringPropertyNames().forEach(s -> assertNotEquals(testHostname, nifiProperties.getProperty(s)));
|
||||
}
|
||||
|
||||
private void testHostnamesAndPorts() {
|
||||
Properties nifiProperties = getNifiProperties();
|
||||
|
||||
assertEquals(NifiPropertiesTlsClientConfigWriter.CONF + keyStore, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
|
||||
assertEquals(keyStoreType, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE));
|
||||
assertEquals(keyStorePassword, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD));
|
||||
assertEquals(keyPassword, nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD));
|
||||
|
||||
assertEquals(NifiPropertiesTlsClientConfigWriter.CONF + trustStore, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE));
|
||||
assertEquals(trustStoreType, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE));
|
||||
assertEquals(trustStorePassword, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD));
|
||||
|
||||
assertEquals("", nifiProperties.getProperty(NiFiProperties.WEB_HTTP_HOST));
|
||||
assertEquals("", nifiProperties.getProperty(NiFiProperties.WEB_HTTP_PORT));
|
||||
assertEquals(Boolean.toString(true), nifiProperties.getProperty(NiFiProperties.SITE_TO_SITE_SECURE));
|
||||
|
||||
nifiPropertiesTlsClientConfigWriter.getHostnamePropertyStream().forEach(s -> assertEquals(testHostname, nifiProperties.getProperty(s)));
|
||||
nifiPropertiesTlsClientConfigWriter.getPropertyPortMap().entrySet().forEach(propertyToPortEntry -> {
|
||||
assertEquals(Integer.toString(propertyToPortEntry.getValue()), nifiProperties.getProperty(propertyToPortEntry.getKey()));
|
||||
assertEquals(Integer.parseInt(overlayProperties.getProperty(propertyToPortEntry.getKey())) + hostNum - 1, propertyToPortEntry.getValue().intValue());
|
||||
});
|
||||
}
|
||||
|
||||
private Properties getNifiProperties() {
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(new ByteArrayInputStream(outputStream.toByteArray()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ package org.apache.nifi.toolkit.tls.standalone;
|
|||
|
||||
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
import org.apache.nifi.toolkit.tls.configuration.InstanceDefinition;
|
||||
import org.apache.nifi.toolkit.tls.configuration.InstanceIdentifier;
|
||||
import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig;
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
|
||||
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriter;
|
||||
|
@ -35,11 +37,15 @@ import java.io.IOException;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.any;
|
||||
|
@ -145,17 +151,10 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", nifi1 + " , " + nifi2);
|
||||
|
||||
List<String> hostnames = tlsToolkitStandaloneCommandLine.createConfig().getHostnames();
|
||||
assertEquals(2, hostnames.size());
|
||||
assertEquals(nifi1, hostnames.get(0));
|
||||
assertEquals(nifi2, hostnames.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpsPort() throws CommandLineParseException {
|
||||
int testPort = 8998;
|
||||
tlsToolkitStandaloneCommandLine.parse("-p", Integer.toString(testPort));
|
||||
assertEquals(testPort, tlsToolkitStandaloneCommandLine.createConfig().getHttpsPort());
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(nifi1, instanceDefinitions.get(0).getHostname());
|
||||
assertEquals(nifi2, instanceDefinitions.get(1).getHostname());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -183,52 +182,46 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
@Test
|
||||
public void testNotSameKeyAndKeystorePassword() throws CommandLineParseException {
|
||||
tlsToolkitStandaloneCommandLine.parse("-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
|
||||
List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
|
||||
assertEquals(1, tlsToolkitStandaloneCommandLine.createConfig().getHostnames().size());
|
||||
assertEquals(1, keyStorePasswords.size());
|
||||
assertEquals(1, keyPasswords.size());
|
||||
assertNotEquals(keyStorePasswords.get(0), keyPasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertNotEquals(instanceDefinitions.get(0).getKeyStorePassword(), instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameKeyAndKeystorePassword() throws CommandLineParseException {
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
|
||||
List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
|
||||
assertEquals(1, tlsToolkitStandaloneCommandLine.createConfig().getHostnames().size());
|
||||
assertEquals(1, keyStorePasswords.size());
|
||||
assertEquals(1, keyPasswords.size());
|
||||
assertEquals(keyStorePasswords.get(0), keyPasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(instanceDefinitions.get(0).getKeyStorePassword(), instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameKeyAndKeystorePasswordWithKeystorePasswordSpecified() throws CommandLineParseException {
|
||||
String testPassword = "testPassword";
|
||||
tlsToolkitStandaloneCommandLine.parse("-S", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
|
||||
assertEquals(1, keyStorePasswords.size());
|
||||
assertEquals(testPassword, keyStorePasswords.get(0));
|
||||
assertEquals(keyStorePasswords, tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords());
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyStorePassword());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSameKeyAndKeystorePasswordWithKeyPasswordSpecified() throws CommandLineParseException {
|
||||
String testPassword = "testPassword";
|
||||
tlsToolkitStandaloneCommandLine.parse("-K", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
|
||||
assertNotEquals(tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords(), keyPasswords);
|
||||
assertEquals(1, keyPasswords.size());
|
||||
assertEquals(testPassword, keyPasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertNotEquals(instanceDefinitions.get(0).getKeyStorePassword(), instanceDefinitions.get(0).getKeyPassword());
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyStorePasswordArg() throws CommandLineParseException {
|
||||
String testPassword = "testPassword";
|
||||
tlsToolkitStandaloneCommandLine.parse("-S", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
|
||||
assertEquals(1, keyStorePasswords.size());
|
||||
assertEquals(testPassword, keyStorePasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -236,31 +229,19 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-S", testPassword1, "-S", testPassword2);
|
||||
List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
|
||||
assertEquals(2, keyStorePasswords.size());
|
||||
assertEquals(testPassword1, keyStorePasswords.get(0));
|
||||
assertEquals(testPassword2, keyStorePasswords.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleKeystorePasswordArgSingleHost() {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
try {
|
||||
tlsToolkitStandaloneCommandLine.parse("-S", testPassword1, "-S", testPassword2);
|
||||
fail("Expected error with mismatch keystore password number");
|
||||
} catch (CommandLineParseException e) {
|
||||
assertEquals(ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS.ordinal(), e.getExitCode());
|
||||
}
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(testPassword1, instanceDefinitions.get(0).getKeyStorePassword());
|
||||
assertEquals(testPassword2, instanceDefinitions.get(1).getKeyStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPasswordArg() throws CommandLineParseException {
|
||||
String testPassword = "testPassword";
|
||||
tlsToolkitStandaloneCommandLine.parse("-K", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
|
||||
assertEquals(1, keyPasswords.size());
|
||||
assertEquals(testPassword, keyPasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -268,31 +249,19 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-K", testPassword1, "-K", testPassword2);
|
||||
List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
|
||||
assertEquals(2, keyPasswords.size());
|
||||
assertEquals(testPassword1, keyPasswords.get(0));
|
||||
assertEquals(testPassword2, keyPasswords.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleKeyPasswordArgSingleHost() {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
try {
|
||||
tlsToolkitStandaloneCommandLine.parse("-K", testPassword1, "-K", testPassword2);
|
||||
fail("Expected error with mismatch keystore password number");
|
||||
} catch (CommandLineParseException e) {
|
||||
assertEquals(ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS.ordinal(), e.getExitCode());
|
||||
}
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(testPassword1, instanceDefinitions.get(0).getKeyPassword());
|
||||
assertEquals(testPassword2, instanceDefinitions.get(1).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruststorePasswordArg() throws CommandLineParseException {
|
||||
String testPassword = "testPassword";
|
||||
tlsToolkitStandaloneCommandLine.parse("-P", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getTrustStorePasswords();
|
||||
assertEquals(1, trustStorePasswords.size());
|
||||
assertEquals(testPassword, trustStorePasswords.get(0));
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getTrustStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -300,22 +269,10 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-P", testPassword1, "-P", testPassword2);
|
||||
List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getTrustStorePasswords();
|
||||
assertEquals(2, trustStorePasswords.size());
|
||||
assertEquals(testPassword1, trustStorePasswords.get(0));
|
||||
assertEquals(testPassword2, trustStorePasswords.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleTruststorePasswordArgSingleHost() {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
try {
|
||||
tlsToolkitStandaloneCommandLine.parse("-P", testPassword1, "-P", testPassword2);
|
||||
fail("Expected error with mismatch keystore password number");
|
||||
} catch (CommandLineParseException e) {
|
||||
assertEquals(ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS.ordinal(), e.getExitCode());
|
||||
}
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(testPassword1, instanceDefinitions.get(0).getTrustStorePassword());
|
||||
assertEquals(testPassword2, instanceDefinitions.get(1).getTrustStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -364,6 +321,83 @@ public class TlsToolkitStandaloneCommandLineTest {
|
|||
assertEquals(testPass2, clientPasswords.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGlobalOrder() throws CommandLineParseException {
|
||||
String hostname1 = "other0[4-6]";
|
||||
String hostname2 = "nifi3(2)";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", hostname1, "-n", hostname2);
|
||||
Map<InstanceIdentifier, InstanceDefinition> definitionMap = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions().stream()
|
||||
.collect(Collectors.toMap(InstanceDefinition::getInstanceIdentifier, Function.identity()));
|
||||
assertEquals(5, definitionMap.size());
|
||||
|
||||
InstanceDefinition nifi3_1 = definitionMap.get(new InstanceIdentifier("nifi3", 1));
|
||||
assertNotNull(nifi3_1);
|
||||
assertEquals(1, nifi3_1.getInstanceIdentifier().getNumber());
|
||||
assertEquals(1, nifi3_1.getNumber());
|
||||
|
||||
InstanceDefinition nifi3_2 = definitionMap.get(new InstanceIdentifier("nifi3", 2));
|
||||
assertNotNull(nifi3_2);
|
||||
assertEquals(2, nifi3_2.getInstanceIdentifier().getNumber());
|
||||
assertEquals(2, nifi3_2.getNumber());
|
||||
|
||||
InstanceDefinition other04 = definitionMap.get(new InstanceIdentifier("other04", 1));
|
||||
assertNotNull(other04);
|
||||
assertEquals(1, other04.getInstanceIdentifier().getNumber());
|
||||
assertEquals(1, other04.getNumber());
|
||||
|
||||
InstanceDefinition other05 = definitionMap.get(new InstanceIdentifier("other05", 1));
|
||||
assertNotNull(other05);
|
||||
assertEquals(1, other05.getInstanceIdentifier().getNumber());
|
||||
assertEquals(1, other05.getNumber());
|
||||
|
||||
InstanceDefinition other06 = definitionMap.get(new InstanceIdentifier("other06", 1));
|
||||
assertNotNull(other06);
|
||||
assertEquals(1, other06.getInstanceIdentifier().getNumber());
|
||||
assertEquals(1, other06.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGlobalOrder() throws CommandLineParseException {
|
||||
String hostname1 = "other0[4-6]";
|
||||
String hostname2 = "nifi3(2)";
|
||||
String globalOrder1 = "nifi[1-5](2),other[01-4]";
|
||||
String globalOrder2 = "other[05-10]";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", hostname1, "-n", hostname2, "-G", globalOrder1, "-G", globalOrder2);
|
||||
Map<InstanceIdentifier, InstanceDefinition> definitionMap = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions().stream()
|
||||
.collect(Collectors.toMap(InstanceDefinition::getInstanceIdentifier, Function.identity()));
|
||||
assertEquals(5, definitionMap.size());
|
||||
|
||||
InstanceDefinition nifi3_1 = definitionMap.get(new InstanceIdentifier("nifi3", 1));
|
||||
assertNotNull(nifi3_1);
|
||||
assertEquals(1, nifi3_1.getInstanceIdentifier().getNumber());
|
||||
assertEquals(5, nifi3_1.getNumber());
|
||||
|
||||
InstanceDefinition nifi3_2 = definitionMap.get(new InstanceIdentifier("nifi3", 2));
|
||||
assertNotNull(nifi3_2);
|
||||
assertEquals(2, nifi3_2.getInstanceIdentifier().getNumber());
|
||||
assertEquals(6, nifi3_2.getNumber());
|
||||
|
||||
InstanceDefinition other04 = definitionMap.get(new InstanceIdentifier("other04", 1));
|
||||
assertNotNull(other04);
|
||||
assertEquals(1, other04.getInstanceIdentifier().getNumber());
|
||||
assertEquals(14, other04.getNumber());
|
||||
|
||||
InstanceDefinition other05 = definitionMap.get(new InstanceIdentifier("other05", 1));
|
||||
assertNotNull(other05);
|
||||
assertEquals(1, other05.getInstanceIdentifier().getNumber());
|
||||
assertEquals(15, other05.getNumber());
|
||||
|
||||
InstanceDefinition other06 = definitionMap.get(new InstanceIdentifier("other06", 1));
|
||||
assertNotNull(other06);
|
||||
assertEquals(1, other06.getInstanceIdentifier().getNumber());
|
||||
assertEquals(16, other06.getNumber());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBadGlobalOrder() throws CommandLineParseException {
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "notInGlobalOrder", "-G", "nifi[1-3]");
|
||||
}
|
||||
|
||||
private Properties getProperties() throws IOException {
|
||||
NiFiPropertiesWriter niFiPropertiesWriter = tlsToolkitStandaloneCommandLine.createConfig().getNiFiPropertiesWriterFactory().create();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.nifi.toolkit.tls.standalone;
|
|||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.nifi.security.util.CertificateUtils;
|
||||
import org.apache.nifi.toolkit.tls.SystemExitCapturer;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
|
||||
|
@ -40,7 +41,6 @@ import java.io.InputStream;
|
|||
import java.security.KeyPair;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
|
@ -54,13 +54,12 @@ import java.util.UUID;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class TlsToolkitStandaloneTest {
|
||||
public static final String NIFI_FAKE_PROPERTY = "nifi.fake.property";
|
||||
public static final String FAKE_VALUE = "fake value";
|
||||
public static final String TEST_NIFI_PROPERTIES = "src/test/resources/localhost/nifi.properties";
|
||||
private SecurityManager originalSecurityManager;
|
||||
private SystemExitCapturer systemExitCapturer;
|
||||
|
||||
private File tempDir;
|
||||
|
||||
|
@ -74,31 +73,12 @@ public class TlsToolkitStandaloneTest {
|
|||
if (!tempDir.mkdirs()) {
|
||||
throw new IOException("Couldn't make directory " + tempDir);
|
||||
}
|
||||
|
||||
originalSecurityManager = System.getSecurityManager();
|
||||
// [see http://stackoverflow.com/questions/309396/java-how-to-test-methods-that-call-system-exit#answer-309427]
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm, Object context) {
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkExit(int status) {
|
||||
super.checkExit(status);
|
||||
throw new ExitException(status);
|
||||
}
|
||||
});
|
||||
systemExitCapturer = new SystemExitCapturer();
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() throws IOException {
|
||||
System.setSecurityManager(originalSecurityManager);
|
||||
systemExitCapturer.close();
|
||||
FileUtils.deleteDirectory(tempDir);
|
||||
}
|
||||
|
||||
|
@ -248,13 +228,16 @@ public class TlsToolkitStandaloneTest {
|
|||
trustStore.load(inputStream, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD).toCharArray());
|
||||
}
|
||||
|
||||
String trustStoreFilename = BaseCommandLine.KEYSTORE + trustStoreType;
|
||||
assertEquals("./conf/" + trustStoreFilename, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
|
||||
|
||||
Certificate certificate = trustStore.getCertificate(TlsToolkitStandalone.NIFI_CERT);
|
||||
assertEquals(rootCert, certificate);
|
||||
|
||||
String keyStoreType = nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE);
|
||||
String keyStoreFilename = BaseCommandLine.KEYSTORE + keyStoreType;
|
||||
File keyStoreFile = new File(hostDir, keyStoreFilename);
|
||||
assertEquals(keyStoreFilename, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
|
||||
assertEquals("./conf/" + keyStoreFilename, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
|
||||
try (InputStream inputStream = new FileInputStream(keyStoreFile)) {
|
||||
|
@ -303,23 +286,6 @@ public class TlsToolkitStandaloneTest {
|
|||
}
|
||||
|
||||
private void runAndAssertExitCode(ExitCode exitCode, String... args) {
|
||||
try {
|
||||
TlsToolkitStandaloneCommandLine.main(args);
|
||||
fail("Expecting exit code: " + exitCode);
|
||||
} catch (ExitException e) {
|
||||
assertEquals(exitCode, ExitCode.values()[e.getExitCode()]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExitException extends SecurityException {
|
||||
private final int exitCode;
|
||||
|
||||
public ExitException(int exitCode) {
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
systemExitCapturer.runAndAssertExitCode(() -> TlsToolkitStandaloneCommandLine.main(args), exitCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
|
@ -48,4 +49,12 @@ public class PasswordUtilTest {
|
|||
String actual = passwordUtil.generatePassword();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test(expected = PasswordsExhaustedException.class)
|
||||
public void testPasswordExhausted() {
|
||||
Supplier<String> supplier = PasswordUtil.passwordSupplier("exhausted", new String[]{"a", "b"});
|
||||
supplier.get();
|
||||
supplier.get();
|
||||
supplier.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Comma separated list of properties to put the hostname into
|
||||
hostname.properties=nifi.remote.input.host,nifi.web.https.host,nifi.cluster.node.address
|
||||
|
||||
nifi.web.https.port=9443
|
||||
nifi.remote.input.socket.port=10443
|
||||
nifi.cluster.node.protocol.port=11443
|
Loading…
Reference in New Issue