mirror of https://github.com/apache/nifi.git
NIFI-12073 removed toolkit tests which rely on system exit calls and captures not allowed any longer by defunct security manager support in Java 21
Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #7743.
This commit is contained in:
parent
019e16c728
commit
ad753318e7
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* 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.security.Permission;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
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) {
|
||||
final ExitException e = assertThrows(ExitException.class, runnable::run);
|
||||
|
||||
assertEquals(exitCode.ordinal(), e.getExitCode(), "Expecting exit code: " + exitCode + ", got " + ExitCode.values()[e.getExitCode()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
System.setSecurityManager(originalSecurityManager);
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* 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.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class TlsToolkitMainTest {
|
||||
private TlsToolkitMain tlsToolkitMain;
|
||||
private SystemExitCapturer systemExitCapturer;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
systemExitCapturer = new SystemExitCapturer();
|
||||
tlsToolkitMain = new TlsToolkitMain();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovesServiceArg() {
|
||||
String storingMain = "storingmain";
|
||||
tlsToolkitMain.getMainMap().put(storingMain, StoringMain.class);
|
||||
tlsToolkitMain.doMain(new String[]{storingMain, "-h"});
|
||||
assertArrayEquals(new String[]{"-h"}, StoringMain.args);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
}
|
||||
|
||||
private static class StoringMain {
|
||||
private static String[] args;
|
||||
|
||||
public static void main(String[] args) {
|
||||
StoringMain.args = args;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,512 +0,0 @@
|
|||
/*
|
||||
* 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.standalone;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
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;
|
||||
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
public class TlsToolkitStandaloneCommandLineTest {
|
||||
private TlsToolkitStandaloneCommandLine tlsToolkitStandaloneCommandLine;
|
||||
|
||||
final String CHANGEIT = "changeit";
|
||||
final String keyPass = CHANGEIT;
|
||||
final String keystorePass = CHANGEIT;
|
||||
final String wrongPass = "wrongpass";
|
||||
private File outputFolder = null;
|
||||
final String keystoreFile = Objects.requireNonNull(getClass().getClassLoader().getResource("keystore.jks")).getFile();
|
||||
|
||||
@BeforeEach
|
||||
public void setup(@TempDir Path tempDir) throws IOException {
|
||||
final SecureRandom secureRandom = new SecureRandom();
|
||||
tlsToolkitStandaloneCommandLine = new TlsToolkitStandaloneCommandLine(new PasswordUtil(secureRandom));
|
||||
final Path outputDir = Files.createTempDirectory(tempDir, "splitKeystoreOutputDir");
|
||||
outputFolder = outputDir.toFile();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelp() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-h"));
|
||||
|
||||
assertEquals(ExitCode.HELP, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnknownArg() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("--unknownArg"));
|
||||
|
||||
assertEquals(ExitCode.ERROR_PARSING_COMMAND_LINE, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyAlgorithm() throws CommandLineParseException {
|
||||
String testKeyAlgorithm = "testKeyAlgorithm";
|
||||
tlsToolkitStandaloneCommandLine.parse("-a", testKeyAlgorithm);
|
||||
assertEquals(testKeyAlgorithm, tlsToolkitStandaloneCommandLine.createConfig().getKeyPairAlgorithm());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeySizeArgNotInteger() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-k", "badVal"));
|
||||
|
||||
assertEquals(ExitCode.ERROR_PARSING_INT_ARG, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeySize() throws CommandLineParseException {
|
||||
int testKeySize = 4096;
|
||||
tlsToolkitStandaloneCommandLine.parse("-k", Integer.toString(testKeySize));
|
||||
assertEquals(testKeySize, tlsToolkitStandaloneCommandLine.createConfig().getKeySize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSigningAlgorithm() throws CommandLineParseException {
|
||||
String testSigningAlgorithm = "testSigningAlgorithm";
|
||||
tlsToolkitStandaloneCommandLine.parse("-s", testSigningAlgorithm);
|
||||
assertEquals(testSigningAlgorithm, tlsToolkitStandaloneCommandLine.createConfig().getSigningAlgorithm());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSAN() throws CommandLineParseException {
|
||||
String dnsSAN = "nifi.apache.org";
|
||||
tlsToolkitStandaloneCommandLine.parse("--subjectAlternativeNames", dnsSAN);
|
||||
assertEquals(dnsSAN, tlsToolkitStandaloneCommandLine.createConfig().getDomainAlternativeNames().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDaysNotInteger() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-d", "badVal"));
|
||||
|
||||
assertEquals(ExitCode.ERROR_PARSING_INT_ARG, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDays() throws CommandLineParseException {
|
||||
int testDays = 29;
|
||||
tlsToolkitStandaloneCommandLine.parse("-d", Integer.toString(testDays));
|
||||
assertEquals(testDays, tlsToolkitStandaloneCommandLine.createConfig().getDays());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyStoreType() throws CommandLineParseException {
|
||||
String testKeyStoreType = "testKeyStoreType";
|
||||
tlsToolkitStandaloneCommandLine.parse("-T", testKeyStoreType);
|
||||
assertEquals(testKeyStoreType, tlsToolkitStandaloneCommandLine.getKeyStoreType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutputDirectory() throws CommandLineParseException {
|
||||
String testPath = File.separator + "fake" + File.separator + "path" + File.separator + "doesnt" + File.separator + "exist";
|
||||
tlsToolkitStandaloneCommandLine.parse("-o", testPath);
|
||||
assertEquals(testPath, tlsToolkitStandaloneCommandLine.createConfig().getBaseDir().getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostnames() throws CommandLineParseException {
|
||||
String nifi1 = "nifi1";
|
||||
String nifi2 = "nifi2";
|
||||
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", nifi1 + " , " + nifi2);
|
||||
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(nifi1, instanceDefinitions.get(0).getHostname());
|
||||
assertEquals(nifi2, instanceDefinitions.get(1).getHostname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNifiPropertiesFile() throws CommandLineParseException, IOException {
|
||||
tlsToolkitStandaloneCommandLine.parse("-f", TlsToolkitStandaloneTest.TEST_NIFI_PROPERTIES);
|
||||
assertEquals(TlsToolkitStandaloneTest.FAKE_VALUE, getProperties().get(TlsToolkitStandaloneTest.NIFI_FAKE_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNifiPropertiesFileDefault() throws CommandLineParseException, IOException {
|
||||
tlsToolkitStandaloneCommandLine.parse();
|
||||
assertNull(getProperties().get(TlsToolkitStandaloneTest.NIFI_FAKE_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadNifiPropertiesFile() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-f", "/this/file/should/not/exist.txt"));
|
||||
|
||||
assertEquals(ExitCode.ERROR_READING_NIFI_PROPERTIES, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotSameKeyAndKeystorePassword() throws CommandLineParseException {
|
||||
tlsToolkitStandaloneCommandLine.parse("-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
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<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<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<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<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleKeystorePasswordArgs() throws CommandLineParseException {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-S", testPassword1, "-S", testPassword2);
|
||||
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<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getKeyPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleKeyPasswordArgs() throws CommandLineParseException {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-K", testPassword1, "-K", testPassword2);
|
||||
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<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(1, instanceDefinitions.size());
|
||||
assertEquals(testPassword, instanceDefinitions.get(0).getTrustStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleTruststorePasswordArgs() throws CommandLineParseException {
|
||||
String testPassword1 = "testPassword1";
|
||||
String testPassword2 = "testPassword2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-P", testPassword1, "-P", testPassword2);
|
||||
List<InstanceDefinition> instanceDefinitions = tlsToolkitStandaloneCommandLine.createConfig().getInstanceDefinitions();
|
||||
assertEquals(2, instanceDefinitions.size());
|
||||
assertEquals(testPassword1, instanceDefinitions.get(0).getTrustStorePassword());
|
||||
assertEquals(testPassword2, instanceDefinitions.get(1).getTrustStorePassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNifiDnPrefix() throws CommandLineParseException {
|
||||
String testPrefix = "O=apache, CN=";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi", "--nifiDnPrefix", testPrefix);
|
||||
StandaloneConfig config = tlsToolkitStandaloneCommandLine.createConfig();
|
||||
assertEquals(testPrefix, config.getDnPrefix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNifiDnSuffix() throws CommandLineParseException {
|
||||
String testSuffix = ", O=apache, OU=nifi";
|
||||
tlsToolkitStandaloneCommandLine.parse("-n", "nifi", "--nifiDnSuffix", testSuffix);
|
||||
StandaloneConfig config = tlsToolkitStandaloneCommandLine.createConfig();
|
||||
assertEquals(testSuffix, config.getDnSuffix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientDnDefault() throws CommandLineParseException {
|
||||
tlsToolkitStandaloneCommandLine.parse();
|
||||
assertEquals(Collections.emptyList(), tlsToolkitStandaloneCommandLine.createConfig().getClientDns());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientDnSingle() throws CommandLineParseException {
|
||||
String testCn = "OU=NIFI,CN=testuser";
|
||||
tlsToolkitStandaloneCommandLine.parse("-C", testCn);
|
||||
List<String> clientDns = tlsToolkitStandaloneCommandLine.createConfig().getClientDns();
|
||||
assertEquals(1, clientDns.size());
|
||||
assertEquals(testCn, clientDns.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientDnMulti() throws CommandLineParseException {
|
||||
String testCn = "OU=NIFI,CN=testuser";
|
||||
String testCn2 = "OU=NIFI,CN=testuser2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-C", testCn, "-C", testCn2);
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createConfig();
|
||||
List<String> clientDns = standaloneConfig.getClientDns();
|
||||
assertEquals(2, clientDns.size());
|
||||
assertEquals(testCn, clientDns.get(0));
|
||||
assertEquals(testCn2, clientDns.get(1));
|
||||
assertEquals(2, standaloneConfig.getClientPasswords().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientPasswordMulti() throws CommandLineParseException {
|
||||
String testCn = "OU=NIFI,CN=testuser";
|
||||
String testCn2 = "OU=NIFI,CN=testuser2";
|
||||
String testPass1 = "testPass1";
|
||||
String testPass2 = "testPass2";
|
||||
tlsToolkitStandaloneCommandLine.parse("-C", testCn, "-C", testCn2, "-B", testPass1, "-B", testPass2);
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createConfig();
|
||||
List<String> clientDns = standaloneConfig.getClientDns();
|
||||
assertEquals(2, clientDns.size());
|
||||
assertEquals(testCn, clientDns.get(0));
|
||||
assertEquals(testCn2, clientDns.get(1));
|
||||
List<String> clientPasswords = standaloneConfig.getClientPasswords();
|
||||
assertEquals(2, clientPasswords.size());
|
||||
assertEquals(testPass1, clientPasswords.get(0));
|
||||
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
|
||||
public void testBadGlobalOrder() {
|
||||
assertThrows(IllegalArgumentException.class, () -> tlsToolkitStandaloneCommandLine.parse("-n", "notInGlobalOrder", "-G", "nifi[1-3]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultOutputPathRoot() {
|
||||
Path root = Paths.get(".").toAbsolutePath().getRoot().resolve(".");
|
||||
String calculateDefaultOutputDirectory = TlsToolkitStandaloneCommandLine.calculateDefaultOutputDirectory(root);
|
||||
assertEquals(root.toAbsolutePath().getRoot().toString(), calculateDefaultOutputDirectory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultOutputPath() {
|
||||
Path path = Paths.get(".");
|
||||
String calculateDefaultOutputDirectory = TlsToolkitStandaloneCommandLine.calculateDefaultOutputDirectory(path);
|
||||
assertEquals("../" + path.toAbsolutePath().normalize().getFileName().toString(), calculateDefaultOutputDirectory);
|
||||
}
|
||||
|
||||
private Properties getProperties() throws IOException {
|
||||
NiFiPropertiesWriter niFiPropertiesWriter = tlsToolkitStandaloneCommandLine.createConfig().getNiFiPropertiesWriterFactory().create();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
niFiPropertiesWriter.writeNiFiProperties(byteArrayOutputStream);
|
||||
Properties properties = new Properties();
|
||||
properties.load(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystore() throws Exception {
|
||||
tlsToolkitStandaloneCommandLine.parse("-splitKeystore", keystoreFile, "-S", keystorePass, "-K", keyPass, "-o", outputFolder.getPath());
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createSplitKeystoreConfig();
|
||||
|
||||
assertTrue(standaloneConfig.isSplitKeystore());
|
||||
assertEquals(keyPass, standaloneConfig.getKeyPassword());
|
||||
assertEquals(keystorePass, standaloneConfig.getKeyStorePassword());
|
||||
TlsToolkitStandalone toolkit = new TlsToolkitStandalone();
|
||||
toolkit.splitKeystore(standaloneConfig);
|
||||
|
||||
assertEquals(3, Objects.requireNonNull(outputFolder.listFiles()).length);
|
||||
|
||||
// Validity checking of the output is done in TlsHelperTest
|
||||
for (File file : Objects.requireNonNull(outputFolder.listFiles())) {
|
||||
assertTrue(file.length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreMissingPasswords() {
|
||||
assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-splitKeystore", keystoreFile, "-o", outputFolder.getPath()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreWithSameKeystoreAndKeyPassword() throws Exception {
|
||||
tlsToolkitStandaloneCommandLine.parse("-splitKeystore", keystoreFile, "-S", keystorePass, "-o", outputFolder.getPath());
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createSplitKeystoreConfig();
|
||||
|
||||
TlsToolkitStandalone toolkit = new TlsToolkitStandalone();
|
||||
toolkit.splitKeystore(standaloneConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreWrongKeyPass() throws Exception {
|
||||
tlsToolkitStandaloneCommandLine.parse("-splitKeystore", keystoreFile, "-S", keystorePass, "-K", wrongPass, "-o", outputFolder.getPath());
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createSplitKeystoreConfig();
|
||||
|
||||
TlsToolkitStandalone toolkit = new TlsToolkitStandalone();
|
||||
|
||||
assertThrows(UnrecoverableKeyException.class, () -> toolkit.splitKeystore(standaloneConfig));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreWrongKeystorePass() throws Exception {
|
||||
tlsToolkitStandaloneCommandLine.parse("-splitKeystore", keystoreFile, "-S", wrongPass, "-K", keyPass, "-o", outputFolder.getPath());
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createSplitKeystoreConfig();
|
||||
|
||||
TlsToolkitStandalone toolkit = new TlsToolkitStandalone();
|
||||
|
||||
assertThrows(IOException.class, () -> toolkit.splitKeystore(standaloneConfig));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreNoKeystore() {
|
||||
assertThrows(CommandLineParseException.class, () -> tlsToolkitStandaloneCommandLine.parse("-splitKeystore", "-S", keystorePass, "-K", keyPass, "-o", outputFolder.getPath()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitKeystoreEmptyKeystore() throws Exception {
|
||||
tlsToolkitStandaloneCommandLine.parse(
|
||||
"-splitKeystore", new File("src/test/resources/empty-keystore.jks").getPath(), "-S", keystorePass, "-K", keyPass, "-o", outputFolder.getPath());
|
||||
StandaloneConfig standaloneConfig = tlsToolkitStandaloneCommandLine.createSplitKeystoreConfig();
|
||||
|
||||
assertTrue(standaloneConfig.isSplitKeystore());
|
||||
assertEquals(keyPass, standaloneConfig.getKeyPassword());
|
||||
assertEquals(keystorePass, standaloneConfig.getKeyStorePassword());
|
||||
TlsToolkitStandalone toolkit = new TlsToolkitStandalone();
|
||||
|
||||
assertThrows(KeyStoreException.class, () -> toolkit.splitKeystore(standaloneConfig));
|
||||
}
|
||||
}
|
|
@ -1,726 +0,0 @@
|
|||
/*
|
||||
* 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.standalone;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
||||
import org.apache.nifi.security.util.KeyStoreUtils;
|
||||
import org.apache.nifi.security.util.KeystoreType;
|
||||
import org.apache.nifi.toolkit.tls.SystemExitCapturer;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.BaseTlsToolkitCommandLine;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
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.service.TlsCertificateAuthorityTest;
|
||||
import org.apache.nifi.toolkit.tls.util.TlsHelper;
|
||||
import org.apache.nifi.toolkit.tls.util.TlsHelperTest;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
|
||||
import org.bouncycastle.util.io.pem.PemWriter;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
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 SystemExitCapturer systemExitCapturer;
|
||||
|
||||
@TempDir
|
||||
private File tempDir;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws IOException {
|
||||
systemExitCapturer = new SystemExitCapturer();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
systemExitCapturer.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadParse() {
|
||||
runAndAssertExitCode(ExitCode.ERROR_PARSING_COMMAND_LINE, "--unknownArgument");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelp() {
|
||||
runAndAssertExitCode(ExitCode.HELP, "-h");
|
||||
runAndAssertExitCode(ExitCode.HELP, "--help");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDirOutput() throws Exception {
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertNull(nifiProperties.get("nifi.fake.property"));
|
||||
assertEquals(nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD), nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferentArg() throws Exception {
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertNull(nifiProperties.get("nifi.fake.property"));
|
||||
assertNotEquals(nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD), nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileArg() throws Exception {
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-f", TEST_NIFI_PROPERTIES, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertEquals(FAKE_VALUE, nifiProperties.get(NIFI_FAKE_PROPERTY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostnamesArgumentOverwrite() throws Exception {
|
||||
String nifi1 = "nifi1";
|
||||
String nifi2 = "nifi2";
|
||||
String nifi3 = "nifi3";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi1 + "," + nifi2);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi3);
|
||||
|
||||
checkHostDirAndReturnNifiProperties(nifi1, x509Certificate);
|
||||
checkHostDirAndReturnNifiProperties(nifi2, x509Certificate);
|
||||
checkHostDirAndReturnNifiProperties(nifi3, x509Certificate);
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-O", "-n", nifi3);
|
||||
checkHostDirAndReturnNifiProperties(nifi3, x509Certificate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostnamesArgumentNoOverwrite() throws Exception {
|
||||
String nifi = "nifi";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
checkHostDirAndReturnNifiProperties(nifi, x509Certificate);
|
||||
runAndAssertExitCode(ExitCode.ERROR_GENERATING_CONFIG, "-o", tempDir.getAbsolutePath(), "-n", nifi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyPasswordArg() throws Exception {
|
||||
String testKey = "testKey";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-K", testKey, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertEquals(testKey, nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyStorePasswordArg() throws Exception {
|
||||
String testKeyStore = "testKeyStore";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-S", testKeyStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertEquals(testKeyStore, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrustStorePasswordArg() throws Exception {
|
||||
String testTrustStore = "testTrustStore";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-P", testTrustStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
assertEquals(testTrustStore, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDnArgs() throws Exception {
|
||||
String nifiDnPrefix = "O=apache, CN=";
|
||||
String nifiDnSuffix = ", OU=nifi";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", TlsConfig.DEFAULT_HOSTNAME,
|
||||
"--" + TlsToolkitStandaloneCommandLine.NIFI_DN_PREFIX_ARG, nifiDnPrefix, "--" + TlsToolkitStandaloneCommandLine.NIFI_DN_SUFFIX_ARG, nifiDnSuffix);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, nifiDnPrefix, nifiDnSuffix, x509Certificate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeyStoreTypeArg() throws Exception {
|
||||
final String certificateAuthorityHostname = "certificate-authority";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", TlsConfig.DEFAULT_HOSTNAME, "-T", KeystoreType.PKCS12.toString().toLowerCase(),
|
||||
"-K", "change", "-S", "change", "-P", "change", "-c", certificateAuthorityHostname);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientDnsArg() throws Exception {
|
||||
String clientDn = "OU=NIFI,CN=testuser";
|
||||
String clientDn2 = "OU=NIFI,CN=testuser2";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-C", clientDn, "-C", clientDn2, "-B", "pass1", "-P", "pass2");
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
checkClientCert(clientDn, x509Certificate);
|
||||
checkClientCert(clientDn2, x509Certificate);
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-O", "-C", clientDn2, "-B", "pass3");
|
||||
checkClientCert(clientDn2, x509Certificate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientDnsArgNoOverwrite() throws Exception {
|
||||
String clientDn = "OU=NIFI,CN=testuser";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-C", clientDn, "-B", "passwor");
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
checkClientCert(clientDn, x509Certificate);
|
||||
|
||||
runAndAssertExitCode(ExitCode.ERROR_GENERATING_CONFIG, "-o", tempDir.getAbsolutePath(), "-C", clientDn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticHostnameNoSan() throws Exception {
|
||||
String hostname = "static.nifi.apache.org";
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", hostname);
|
||||
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
Certificate[] certificateChain = loadCertificateChain(hostname, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have one san that matches
|
||||
assertEquals(1, clientSaNames.size());
|
||||
List<?> firstSan = clientSaNames.toArray(new List<?>[0])[0];
|
||||
assertEquals(GeneralName.dNSName, firstSan.get(0));
|
||||
assertEquals(hostname, firstSan.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticHostnameStaticSan() throws Exception {
|
||||
String hostname = "static.nifi.apache.org";
|
||||
String san = "alternative.nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", hostname, "--subjectAlternativeName", san);
|
||||
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
Certificate[] certificateChain = loadCertificateChain(hostname, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have two sans, and one san that matches
|
||||
assertEquals(2, clientSaNames.size());
|
||||
List<?> explicitSan = clientSaNames.toArray(new List<?>[0])[1];
|
||||
assertEquals(GeneralName.dNSName, explicitSan.get(0));
|
||||
assertEquals(san, explicitSan.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameStaticSan() throws Exception {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String san = "alternative.nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", san);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
Stream<InstanceIdentifier> hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
|
||||
|
||||
for (InstanceIdentifier hostInstance : (Iterable<InstanceIdentifier>) hostIds::iterator) {
|
||||
Certificate[] certificateChain = loadCertificateChain(hostInstance.getHostname(), x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have two sans, and one san that matches
|
||||
assertEquals(2, clientSaNames.size());
|
||||
List<?> explicitSan = clientSaNames.toArray(new List<?>[0])[1];
|
||||
assertEquals(GeneralName.dNSName, explicitSan.get(0));
|
||||
assertEquals(san, explicitSan.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameDynamicSansSameRange() throws Exception {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String saNames = "alternative[1-2].nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Stream<InstanceIdentifier> hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
|
||||
Stream<InstanceIdentifier> sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
|
||||
|
||||
String[] nodeHosts = hostIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
String[] sanHosts = sansIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
assertEquals(nodeHosts.length, sanHosts.length);
|
||||
|
||||
for (int i = 0; i< nodeHosts.length; i++) {
|
||||
String host = nodeHosts[i];
|
||||
String san = sanHosts[i];
|
||||
|
||||
Certificate[] certificateChain = loadCertificateChain(host, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have two sans, and both must match
|
||||
assertEquals(2, clientSaNames.size());
|
||||
|
||||
List<?> hostSan = clientSaNames.toArray(new List<?>[0])[0];
|
||||
assertEquals(GeneralName.dNSName, hostSan.get(0));
|
||||
assertEquals(host, hostSan.get(1));
|
||||
|
||||
List<?> altSan = clientSaNames.toArray(new List<?>[0])[1];
|
||||
assertEquals(GeneralName.dNSName, altSan.get(0));
|
||||
assertEquals(san, altSan.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameDynamicSansSameRangeDiffValues() throws Exception {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String saNames = "alternative[3-4].nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Stream<InstanceIdentifier> hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
|
||||
Stream<InstanceIdentifier> sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
|
||||
|
||||
String[] nodeHosts = hostIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
String[] sanHosts = sansIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
assertEquals(nodeHosts.length, sanHosts.length);
|
||||
|
||||
for (int i = 0; i< nodeHosts.length; i++) {
|
||||
String host = nodeHosts[i];
|
||||
String san = sanHosts[i];
|
||||
|
||||
Certificate[] certificateChain = loadCertificateChain(host, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have two sans, and both must match
|
||||
assertEquals(2, clientSaNames.size());
|
||||
|
||||
List<?> hostSan = clientSaNames.toArray(new List<?>[0])[0];
|
||||
assertEquals(GeneralName.dNSName, hostSan.get(0));
|
||||
assertEquals(host, hostSan.get(1));
|
||||
|
||||
List<?> altSan = clientSaNames.toArray(new List<?>[0])[1];
|
||||
assertEquals(GeneralName.dNSName, altSan.get(0));
|
||||
assertEquals(san, altSan.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameDynamicSansDiffRange() throws Exception {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String saNames = "alternative[5-7].nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Stream<InstanceIdentifier> hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
|
||||
Stream<InstanceIdentifier> sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
|
||||
|
||||
String[] nodeHosts = hostIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
String[] sanHosts = sansIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
assertEquals(2, nodeHosts.length);
|
||||
assertEquals(3, sanHosts.length);
|
||||
|
||||
for (int i = 0; i< nodeHosts.length; i++) {
|
||||
String host = nodeHosts[i];
|
||||
|
||||
Certificate[] certificateChain = loadCertificateChain(host, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have sans + cn
|
||||
assertEquals(1 + sanHosts.length, clientSaNames.size());
|
||||
|
||||
for (int j = 0; j < sanHosts.length; j++) {
|
||||
String sanHost = clientSaNames.stream().collect(Collectors.toList()).get(j+1).get(1).toString();
|
||||
assertEquals(sanHosts[j], sanHost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameDynamicSansSameRangeReverseOrder() throws Exception {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String saNames = "alternative[2-1].nifi.apache.org";
|
||||
|
||||
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
|
||||
X509Certificate x509Certificate = checkLoadCertPrivateKey();
|
||||
|
||||
Stream<InstanceIdentifier> hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
|
||||
Stream<InstanceIdentifier> sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
|
||||
|
||||
String[] nodeHosts = hostIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
String[] sanHosts = sansIds.map(InstanceIdentifier::getHostname).toArray(String[]::new);
|
||||
assertTrue(nodeHosts.length > 0);
|
||||
assertEquals(nodeHosts.length, sanHosts.length);
|
||||
|
||||
for (int i = 0; i< nodeHosts.length; i++) {
|
||||
String host = nodeHosts[i];
|
||||
String san = sanHosts[i];
|
||||
|
||||
Certificate[] certificateChain = loadCertificateChain(host, x509Certificate);
|
||||
X509Certificate clientCert = (X509Certificate) certificateChain[0];
|
||||
Collection<List<?>> clientSaNames = clientCert.getSubjectAlternativeNames();
|
||||
|
||||
// Must have sans + cn
|
||||
assertEquals(2, clientSaNames.size());
|
||||
|
||||
List<?> hostSan = clientSaNames.toArray(new List<?>[0])[0];
|
||||
assertEquals(GeneralName.dNSName, hostSan.get(0));
|
||||
assertEquals(host, hostSan.get(1));
|
||||
|
||||
List<?> altSan = clientSaNames.toArray(new List<?>[0])[1];
|
||||
assertEquals(GeneralName.dNSName, altSan.get(0));
|
||||
assertEquals(san, altSan.get(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicHostnameDynamicSansNonNumeric() {
|
||||
String nodeNames = "node[1-2].nifi.apache.org";
|
||||
String saNames = "alternative[A-B].nifi.apache.org";
|
||||
runAndAssertExitCode(ExitCode.ERROR_PARSING_INT_ARG, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldVerifyCertificateSignatureWhenSelfSigned() throws Exception {
|
||||
// Create a temp directory for this test and populate it with the nifi-cert.pem and nifi-key.key files
|
||||
populateTempDirWithCAFiles();
|
||||
|
||||
// Make a standalone config which doesn't trigger any keystore generation and just has a self-signed cert and key
|
||||
StandaloneConfig standaloneConfig = new StandaloneConfig();
|
||||
standaloneConfig.setBaseDir(tempDir);
|
||||
standaloneConfig.setInstanceDefinitions(new ArrayList<>());
|
||||
standaloneConfig.setClientDns(new ArrayList<>());
|
||||
standaloneConfig.initDefaults();
|
||||
|
||||
TlsToolkitStandalone standalone = new TlsToolkitStandalone();
|
||||
// The test will fail with an exception if the certificate is not signed by a known certificate
|
||||
assertDoesNotThrow(() -> standalone.createNifiKeystoresAndTrustStores(standaloneConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* The certificate under examination is self-signed, but there is another signing cert which will be iterated over first, fail, and then the self-signed signature will be validated.
|
||||
*/
|
||||
@Test
|
||||
void testShouldVerifyCertificateSignatureWithMultipleSigningCerts() throws Exception {
|
||||
// Populate temp directory for this test with the nifi-cert.pem and nifi-key.key files
|
||||
populateTempDirWithCAFiles();
|
||||
|
||||
// Create a different cert and persist it to the base dir
|
||||
X509Certificate otherCert = generateX509Certificate();
|
||||
File otherCertFile = writeCertificateToPEMFile(otherCert, tempDir.getPath() + "/other.pem");
|
||||
|
||||
// Make a standalone config which doesn't trigger any keystore generation and just has a self-signed cert and key
|
||||
StandaloneConfig standaloneConfig = new StandaloneConfig();
|
||||
standaloneConfig.setBaseDir(tempDir);
|
||||
standaloneConfig.setInstanceDefinitions(new ArrayList<>());
|
||||
standaloneConfig.setClientDns(new ArrayList<>());
|
||||
standaloneConfig.initDefaults();
|
||||
|
||||
// Inject the additional CA cert path
|
||||
standaloneConfig.setAdditionalCACertificate(otherCertFile.getPath());
|
||||
TlsToolkitStandalone standalone = new TlsToolkitStandalone();
|
||||
|
||||
assertDoesNotThrow(() -> standalone.createNifiKeystoresAndTrustStores(standaloneConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* The certificate under examination is signed with the external signing cert.
|
||||
*/
|
||||
@Test
|
||||
void testShouldVerifyCertificateSignatureWithAdditionalSigningCert() throws Exception {
|
||||
// Create a root CA, create an intermediate CA, use the root to sign the intermediate and then provide the root
|
||||
KeyPair rootKeyPair = generateKeyPair();
|
||||
X509Certificate rootCert = generateX509Certificate("CN=Root CA", rootKeyPair);
|
||||
|
||||
File rootCertFile = writeCertificateToPEMFile(rootCert, tempDir.getPath() + "/root.pem");
|
||||
|
||||
KeyPair intermediateKeyPair = generateKeyPair();
|
||||
X509Certificate intermediateCert = new StandardCertificateBuilder(rootKeyPair, rootCert.getIssuerX500Principal(), Duration.ofDays(1))
|
||||
.setSubject(new X500Principal("CN=Intermediate CA"))
|
||||
.setSubjectPublicKey(intermediateKeyPair.getPublic())
|
||||
.build();
|
||||
|
||||
//intermediateCertFile
|
||||
writeCertificateToPEMFile(intermediateCert, tempDir.getPath() + "/nifi-cert.pem");
|
||||
|
||||
// Write the private key of the intermediate cert to nifi-key.key
|
||||
//intermediateKeyFile
|
||||
writePrivateKeyToFile(intermediateKeyPair, tempDir.getPath() + "/nifi-key.key");
|
||||
|
||||
// Make a standalone config which doesn't trigger any keystore generation and just has a signed cert and key
|
||||
StandaloneConfig standaloneConfig = new StandaloneConfig();
|
||||
standaloneConfig.setBaseDir(tempDir);
|
||||
standaloneConfig.setInstanceDefinitions(new ArrayList<>());
|
||||
standaloneConfig.setClientDns(new ArrayList<>());
|
||||
standaloneConfig.initDefaults();
|
||||
|
||||
// Inject the additional CA cert path
|
||||
standaloneConfig.setAdditionalCACertificate(rootCertFile.getPath());
|
||||
TlsToolkitStandalone standalone = new TlsToolkitStandalone();
|
||||
|
||||
assertDoesNotThrow(() -> standalone.createNifiKeystoresAndTrustStores(standaloneConfig));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldNotVerifyCertificateSignatureWithWrongSigningCert() throws Exception {
|
||||
// Create a root CA, create an intermediate CA, use the root to sign the intermediate and then do not provide the root
|
||||
KeyPair rootKeyPair = generateKeyPair();
|
||||
X509Certificate rootCert = generateX509Certificate("CN=Root CA", rootKeyPair);
|
||||
|
||||
KeyPair intermediateKeyPair = generateKeyPair();
|
||||
X509Certificate intermediateCert = new StandardCertificateBuilder(rootKeyPair, rootCert.getIssuerX500Principal(), Duration.ofDays(1))
|
||||
.setSubject(new X500Principal("CN=Intermediate CA"))
|
||||
.setSubjectPublicKey(intermediateKeyPair.getPublic())
|
||||
.build();
|
||||
|
||||
//intermediateCertFile
|
||||
writeCertificateToPEMFile(intermediateCert, tempDir.getPath() + "/nifi-cert.pem");
|
||||
|
||||
// Write the private key of the intermediate cert to nifi-key.key
|
||||
//intermediateKeyFile
|
||||
writePrivateKeyToFile(intermediateKeyPair, tempDir.getPath() + "/nifi-key.key");
|
||||
|
||||
// Make a standalone config which doesn't trigger any keystore generation and just has a signed cert and key
|
||||
StandaloneConfig standaloneConfig = new StandaloneConfig();
|
||||
standaloneConfig.setBaseDir(tempDir);
|
||||
standaloneConfig.setInstanceDefinitions(new ArrayList<>());
|
||||
standaloneConfig.setClientDns(new ArrayList<>());
|
||||
standaloneConfig.initDefaults();
|
||||
TlsToolkitStandalone standalone = new TlsToolkitStandalone();
|
||||
|
||||
assertThrows(SignatureException.class, () -> standalone.createNifiKeystoresAndTrustStores(standaloneConfig));
|
||||
}
|
||||
|
||||
private X509Certificate checkLoadCertPrivateKey() throws IOException, CertificateException {
|
||||
KeyPair keyPair = TlsHelperTest.loadKeyPair(new File(tempDir, TlsToolkitStandalone.NIFI_KEY + ".key"));
|
||||
|
||||
assertEquals(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM, keyPair.getPrivate().getAlgorithm());
|
||||
assertEquals(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM, keyPair.getPublic().getAlgorithm());
|
||||
|
||||
X509Certificate x509Certificate = TlsHelperTest.loadCertificate(new File(tempDir, TlsToolkitStandalone.NIFI_CERT + ".pem"));
|
||||
assertEquals(keyPair.getPublic(), x509Certificate.getPublicKey());
|
||||
return x509Certificate;
|
||||
}
|
||||
|
||||
private Properties checkHostDirAndReturnNifiProperties(String hostname, X509Certificate rootCert) throws Exception {
|
||||
return checkHostDirAndReturnNifiProperties(hostname, TlsConfig.DEFAULT_DN_PREFIX, TlsConfig.DEFAULT_DN_SUFFIX, rootCert);
|
||||
}
|
||||
|
||||
private Properties checkHostDirAndReturnNifiProperties(String hostname, String dnPrefix, String dnSuffix, X509Certificate rootCert) throws Exception {
|
||||
File hostDir = new File(tempDir, hostname);
|
||||
Properties nifiProperties = new Properties();
|
||||
try (InputStream inputStream = new FileInputStream(new File(hostDir, TlsToolkitStandalone.NIFI_PROPERTIES))) {
|
||||
nifiProperties.load(inputStream);
|
||||
}
|
||||
|
||||
String trustStoreType = nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE);
|
||||
assertEquals(KeystoreType.JKS.toString().toLowerCase(), trustStoreType.toLowerCase());
|
||||
KeyStore trustStore = KeyStoreUtils.getKeyStore(trustStoreType);
|
||||
try (InputStream inputStream = new FileInputStream(new File(hostDir, "truststore." + trustStoreType))) {
|
||||
trustStore.load(inputStream, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD).toCharArray());
|
||||
}
|
||||
|
||||
String trustStoreFilename = BaseTlsToolkitCommandLine.TRUSTSTORE + trustStoreType;
|
||||
assertEquals("./conf/" + trustStoreFilename, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE));
|
||||
|
||||
Certificate certificate = trustStore.getCertificate(TlsToolkitStandalone.NIFI_CERT);
|
||||
assertEquals(rootCert, certificate);
|
||||
|
||||
String keyStoreType = nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE);
|
||||
String keyStoreFilename = BaseTlsToolkitCommandLine.KEYSTORE + keyStoreType;
|
||||
File keyStoreFile = new File(hostDir, keyStoreFilename);
|
||||
assertEquals("./conf/" + keyStoreFilename, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
|
||||
|
||||
KeyStore keyStore = KeyStoreUtils.getKeyStore(keyStoreType);
|
||||
char[] keyStorePassword = nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD).toCharArray();
|
||||
try (InputStream inputStream = new FileInputStream(keyStoreFile)) {
|
||||
keyStore.load(inputStream, keyStorePassword);
|
||||
}
|
||||
|
||||
char[] keyPassword = nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD).toCharArray();
|
||||
if(ArrayUtils.isEmpty(keyPassword)) {
|
||||
keyPassword = keyStorePassword;
|
||||
}
|
||||
|
||||
KeyStore.Entry entry = keyStore.getEntry(TlsToolkitStandalone.NIFI_KEY, new KeyStore.PasswordProtection(keyPassword));
|
||||
assertEquals(KeyStore.PrivateKeyEntry.class, entry.getClass());
|
||||
|
||||
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
|
||||
|
||||
Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
|
||||
|
||||
assertEquals(2, certificateChain.length);
|
||||
assertEquals(rootCert, certificateChain[1]);
|
||||
certificateChain[1].verify(rootCert.getPublicKey());
|
||||
certificateChain[0].verify(rootCert.getPublicKey());
|
||||
TlsConfig tlsConfig = new TlsConfig();
|
||||
tlsConfig.setDnPrefix(dnPrefix);
|
||||
tlsConfig.setDnSuffix(dnSuffix);
|
||||
TlsCertificateAuthorityTest.assertPrivateAndPublicKeyMatch(privateKeyEntry.getPrivateKey(), certificateChain[0].getPublicKey());
|
||||
return nifiProperties;
|
||||
}
|
||||
|
||||
private void checkClientCert(String clientDn, X509Certificate rootCert) throws Exception {
|
||||
String clientDnFile = TlsHelper.escapeFilename(clientDn);
|
||||
String password;
|
||||
try (FileReader fileReader = new FileReader(new File(tempDir, clientDnFile + ".password"))) {
|
||||
List<String> lines = IOUtils.readLines(fileReader);
|
||||
assertEquals(1, lines.size());
|
||||
password = lines.get(0);
|
||||
}
|
||||
|
||||
KeyStore keyStore = KeyStoreUtils.getKeyStore(KeystoreType.PKCS12.toString());
|
||||
try (FileInputStream fileInputStream = new FileInputStream(new File(tempDir, clientDnFile + ".p12"))) {
|
||||
keyStore.load(fileInputStream, password.toCharArray());
|
||||
}
|
||||
final char[] keyPassword = password.toCharArray();
|
||||
PrivateKey privateKey = (PrivateKey) keyStore.getKey(TlsToolkitStandalone.NIFI_KEY, keyPassword);
|
||||
Certificate[] certificateChain = keyStore.getCertificateChain(TlsToolkitStandalone.NIFI_KEY);
|
||||
assertEquals(2, certificateChain.length);
|
||||
assertEquals(rootCert, certificateChain[1]);
|
||||
certificateChain[1].verify(rootCert.getPublicKey());
|
||||
certificateChain[0].verify(rootCert.getPublicKey());
|
||||
PublicKey publicKey = certificateChain[0].getPublicKey();
|
||||
TlsCertificateAuthorityTest.assertPrivateAndPublicKeyMatch(privateKey, publicKey);
|
||||
}
|
||||
|
||||
private Certificate[] loadCertificateChain(String hostname, X509Certificate rootCert) throws Exception {
|
||||
File hostDir = new File(tempDir, hostname);
|
||||
Properties nifiProperties = checkHostDirAndReturnNifiProperties(hostname, rootCert);
|
||||
String keyStoreType = nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE);
|
||||
String keyStoreFilename = BaseTlsToolkitCommandLine.KEYSTORE + keyStoreType;
|
||||
File keyStoreFile = new File(hostDir, keyStoreFilename);
|
||||
KeyStore keyStore = KeyStoreUtils.getKeyStore(keyStoreType);
|
||||
|
||||
try (FileInputStream fileInputStream = new FileInputStream(keyStoreFile)) {
|
||||
keyStore.load(fileInputStream, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD).toCharArray());
|
||||
}
|
||||
|
||||
return keyStore.getCertificateChain(TlsToolkitStandalone.NIFI_KEY);
|
||||
}
|
||||
|
||||
private void runAndAssertExitCode(ExitCode exitCode, String... args) {
|
||||
systemExitCapturer.runAndAssertExitCode(() -> TlsToolkitStandaloneCommandLine.main(args), exitCode);
|
||||
}
|
||||
|
||||
private void populateTempDirWithCAFiles() throws Exception {
|
||||
final String testSrcDir = "src/test/resources/";
|
||||
File certificateFile = new File(testSrcDir, "rootCert.crt");
|
||||
File keyFile = new File(testSrcDir, "rootCert.key");
|
||||
File destinationCertFile = new File(tempDir, "nifi-cert.pem");
|
||||
Files.copy(certificateFile.toPath(), destinationCertFile.toPath());
|
||||
File destinationKeyFile = new File(tempDir, "nifi-key.key");
|
||||
Files.copy(keyFile.toPath(), destinationKeyFile.toPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link X509Certificate} with the provided DN and default algorithms. The validity period is only 1 day.
|
||||
* DN (defaults to {@code CN=Test Certificate})
|
||||
* @return the X509Certificate
|
||||
*/
|
||||
private static X509Certificate generateX509Certificate() throws Exception {
|
||||
return generateX509Certificate("CN=Test Certificate", generateKeyPair());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link X509Certificate} with the provided DN and default algorithms. The validity period is only 1 day.
|
||||
*
|
||||
* @param dn the DN (defaults to {@code CN=Test Certificate})
|
||||
* @return the X509Certificate
|
||||
*/
|
||||
private static X509Certificate generateX509Certificate(String dn, KeyPair keyPair) {
|
||||
return new StandardCertificateBuilder(keyPair, new X500Principal(dn), Duration.ofDays(1)).build();
|
||||
}
|
||||
|
||||
private static KeyPair generateKeyPair() throws Exception {
|
||||
final String defaultKeyPairAlgorithm = "RSA";
|
||||
KeyPairGenerator instance = KeyPairGenerator.getInstance(defaultKeyPairAlgorithm);
|
||||
instance.initialize(2048);
|
||||
|
||||
return instance.generateKeyPair();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the provided {@link X509Certificate} to the specified file in PEM format.
|
||||
*
|
||||
* @param certificate the certificate
|
||||
* @param destination the path to write the certificate in PEM format
|
||||
* @return the file
|
||||
*/
|
||||
private static File writeCertificateToPEMFile(X509Certificate certificate, String destination) throws Exception {
|
||||
return writePem(certificate, destination);
|
||||
}
|
||||
|
||||
private static File writePem(Object object, String destination) throws Exception{
|
||||
File destinationFile = new File(destination);
|
||||
try(PemWriter pemWriter = new PemWriter(new FileWriter(destinationFile))) {
|
||||
pemWriter.writeObject(new JcaMiscPEMGenerator(object));
|
||||
}
|
||||
|
||||
return destinationFile;
|
||||
}
|
||||
|
||||
private static void writePrivateKeyToFile(KeyPair intermediateKeyPair, String destination) throws Exception {
|
||||
writePem(intermediateKeyPair, destination);
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* 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.status;
|
||||
|
||||
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
|
||||
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
|
||||
import org.apache.nifi.toolkit.tls.configuration.GetStatusConfig;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.net.URI;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class TlsToolkitGetStatusCommandLineTest {
|
||||
|
||||
private final String TRUSTSTORE_PATH = "src/test/resources/localhost/truststore.jks";
|
||||
private final String TRUSTSTORE_PASSWORD = "passwordpassword";
|
||||
private final String JKS_TYPE = "JKS";
|
||||
|
||||
private TlsToolkitGetStatusCommandLine commandLine;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
commandLine = new TlsToolkitGetStatusCommandLine();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelp() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> commandLine.parse("-h"));
|
||||
|
||||
assertEquals(ExitCode.HELP, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess() throws CommandLineParseException {
|
||||
final String urlStr = "https://localhost:8443/test";
|
||||
commandLine.parse(
|
||||
"-u", urlStr,
|
||||
"-ts", TRUSTSTORE_PATH,
|
||||
"-tst", JKS_TYPE,
|
||||
"-tsp", TRUSTSTORE_PASSWORD);
|
||||
|
||||
final GetStatusConfig config = commandLine.createConfig();
|
||||
assertNotNull(config);
|
||||
|
||||
final URI url = config.getUrl();
|
||||
assertNotNull(url);
|
||||
assertEquals(urlStr, url.toString());
|
||||
|
||||
final SSLContext sslContext = config.getSslContext();
|
||||
assertNotNull(sslContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingUrl() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> commandLine.parse(
|
||||
"-ts", TRUSTSTORE_PATH,
|
||||
"-tst", JKS_TYPE,
|
||||
"-tsp", TRUSTSTORE_PASSWORD)
|
||||
);
|
||||
|
||||
assertEquals(ExitCode.INVALID_ARGS, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruststoreDoesNotExist() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> commandLine.parse(
|
||||
|
||||
"-u", "https://localhost:8443/test",
|
||||
"-ts", "does/not/exist/truststore.jks",
|
||||
"-tst", JKS_TYPE,
|
||||
"-tsp", TRUSTSTORE_PASSWORD)
|
||||
);
|
||||
|
||||
assertEquals(ExitCode.INVALID_ARGS, e.getExitCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidTruststoreType() {
|
||||
final CommandLineParseException e = assertThrows(CommandLineParseException.class, () -> commandLine.parse(
|
||||
|
||||
"-u", "https://localhost:8443/test",
|
||||
"-ts", TRUSTSTORE_PATH,
|
||||
"-tst", "INVALID",
|
||||
"-tsp", TRUSTSTORE_PASSWORD)
|
||||
);
|
||||
|
||||
assertEquals(ExitCode.INVALID_ARGS, e.getExitCode());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue