diff --git a/nifi-toolkit/nifi-toolkit-tls/pom.xml b/nifi-toolkit/nifi-toolkit-tls/pom.xml
index 8912388b98..7eb6806553 100644
--- a/nifi-toolkit/nifi-toolkit-tls/pom.xml
+++ b/nifi-toolkit/nifi-toolkit-tls/pom.xml
@@ -90,11 +90,6 @@
org.slf4j
jcl-over-slf4j
-
- org.codehaus.groovy
- groovy-test
- test
-
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneGroovyTest.groovy b/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneGroovyTest.groovy
deleted file mode 100644
index 9ab3d463d6..0000000000
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneGroovyTest.groovy
+++ /dev/null
@@ -1,214 +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.nifi.security.cert.builder.StandardCertificateBuilder
-import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig
-import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator
-import org.bouncycastle.util.io.pem.PemWriter
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.io.TempDir
-
-import javax.security.auth.x500.X500Principal
-import java.nio.file.Files
-import java.security.KeyPair
-import java.security.KeyPairGenerator
-import java.security.SignatureException
-import java.security.cert.X509Certificate
-import java.time.Duration
-
-import static org.junit.jupiter.api.Assertions.assertThrows
-
-class TlsToolkitStandaloneGroovyTest {
- private final String TEST_SRC_DIR = "src/test/resources/"
- private final String DEFAULT_KEY_PAIR_ALGORITHM = "RSA"
-
- @Test
- void testShouldVerifyCertificateSignatureWhenSelfSigned(@TempDir File tempDir) {
- // Arrange
-
- // Create a temp directory for this test and populate it with the nifi-cert.pem and nifi-key.key files
- File baseDir = createBaseDirAndPopulateWithCAFiles(tempDir)
-
- // 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(baseDir)
- standaloneConfig.setInstanceDefinitions([])
- standaloneConfig.setClientDns([])
- standaloneConfig.initDefaults()
-
- TlsToolkitStandalone standalone = new TlsToolkitStandalone()
-
- // Act
- standalone.createNifiKeystoresAndTrustStores(standaloneConfig)
-
- // Assert
-
- // The test will fail with an exception if the certificate is not signed by a known certificate
- }
-
- /**
- * 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(@TempDir File tempDir) {
- // Create a temp directory for this test and populate it with the nifi-cert.pem and nifi-key.key files
- File baseDir = createBaseDirAndPopulateWithCAFiles(tempDir)
-
- // Create a different cert and persist it to the base dir
- X509Certificate otherCert = generateX509Certificate()
- File otherCertFile = writeCertificateToPEMFile(otherCert, "${baseDir.path}/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(baseDir)
- standaloneConfig.setInstanceDefinitions([])
- standaloneConfig.setClientDns([])
- standaloneConfig.initDefaults()
-
- // Inject the additional CA cert path
- standaloneConfig.setAdditionalCACertificate(otherCertFile.path)
-
- TlsToolkitStandalone standalone = new TlsToolkitStandalone()
-
- // Act
- standalone.createNifiKeystoresAndTrustStores(standaloneConfig)
- }
-
- /**
- * The certificate under examination is signed with the external signing cert.
- */
- @Test
- void testShouldVerifyCertificateSignatureWithAdditionalSigningCert(@TempDir File baseDir) {
- // 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, "${baseDir.path}/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()
-
- File intermediateCertFile = writeCertificateToPEMFile(intermediateCert, "${baseDir.path}/nifi-cert.pem")
-
- // Write the private key of the intermediate cert to nifi-key.key
- File intermediateKeyFile = writePrivateKeyToFile(intermediateKeyPair, "${baseDir}/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(baseDir)
- standaloneConfig.setInstanceDefinitions([])
- standaloneConfig.setClientDns([])
- standaloneConfig.initDefaults()
-
- // Inject the additional CA cert path
- standaloneConfig.setAdditionalCACertificate(rootCertFile.path)
-
- TlsToolkitStandalone standalone = new TlsToolkitStandalone()
-
- // Act
- standalone.createNifiKeystoresAndTrustStores(standaloneConfig)
- }
-
- @Test
- void testShouldNotVerifyCertificateSignatureWithWrongSigningCert(@TempDir File baseDir) {
- // 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()
-
- File intermediateCertFile = writeCertificateToPEMFile(intermediateCert, "${baseDir.path}/nifi-cert.pem")
-
- // Write the private key of the intermediate cert to nifi-key.key
- File intermediateKeyFile = writePrivateKeyToFile(intermediateKeyPair, "${baseDir.path}/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(baseDir)
- standaloneConfig.setInstanceDefinitions([])
- standaloneConfig.setClientDns([])
- standaloneConfig.initDefaults()
-
- TlsToolkitStandalone standalone = new TlsToolkitStandalone()
-
- assertThrows(SignatureException.class, () -> standalone.createNifiKeystoresAndTrustStores(standaloneConfig))
- }
-
- private static File writePrivateKeyToFile(KeyPair intermediateKeyPair, String destination) {
- File intermediateKeyFile = new File(destination)
- PemWriter pemWriter = new PemWriter(new FileWriter(intermediateKeyFile))
- pemWriter.writeObject(new JcaMiscPEMGenerator(intermediateKeyPair))
- pemWriter.close()
- intermediateKeyFile
- }
-
- private File createBaseDirAndPopulateWithCAFiles(File baseDir) {
- populateBaseDirWithCAFiles(baseDir)
- }
-
- private File populateBaseDirWithCAFiles(File baseDir) {
- File certificateFile = new File(TEST_SRC_DIR, "rootCert.crt")
- File keyFile = new File(TEST_SRC_DIR, "rootCert.key")
- File destinationCertFile = new File(baseDir.path, "nifi-cert.pem")
- Files.copy(certificateFile.toPath(), destinationCertFile.toPath())
- File destinationKeyFile = new File(baseDir.path, "nifi-key.key")
- Files.copy(keyFile.toPath(), destinationKeyFile.toPath())
-
- baseDir
- }
-
- /**
- * 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 X509Certificate generateX509Certificate(String dn = "CN=Test Certificate", KeyPair keyPair = generateKeyPair()) {
- new StandardCertificateBuilder(keyPair, new X500Principal(dn), Duration.ofDays(1)).build()
- }
-
- private KeyPair generateKeyPair() {
- KeyPairGenerator instance = KeyPairGenerator.getInstance(DEFAULT_KEY_PAIR_ALGORITHM)
- instance.initialize(2048)
- 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) {
- File certificateFile = new File(destination)
- PemWriter pemWriter = new PemWriter(new FileWriter(certificateFile))
- pemWriter.writeObject(new JcaMiscPEMGenerator(certificate))
- pemWriter.close()
-
- certificateFile
- }
-}
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/util/TlsHelperGroovyTest.groovy b/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/util/TlsHelperGroovyTest.groovy
deleted file mode 100644
index 4004bfb76a..0000000000
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/groovy/org/apache/nifi/toolkit/tls/util/TlsHelperGroovyTest.groovy
+++ /dev/null
@@ -1,102 +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.util
-
-import org.bouncycastle.crypto.params.RSAKeyParameters
-import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey
-import org.bouncycastle.jce.provider.BouncyCastleProvider
-import org.junit.jupiter.api.BeforeAll
-import org.junit.jupiter.api.Test
-
-import javax.security.auth.x500.X500Principal
-import java.security.KeyPair
-import java.security.PrivateKey
-import java.security.Security
-import java.security.cert.X509Certificate
-
-class TlsHelperGroovyTest {
-
- @BeforeAll
- static void setProvider() {
- System.setProperty("org.bouncycastle.rsa.allow_unsafe_mod","true")
- Security.addProvider(new BouncyCastleProvider())
- BCRSAPublicKey badPublicKey = new BCRSAPublicKey(new RSAKeyParameters(false, new BigInteger("3", 10), new BigInteger("1", 10)))
- }
-
- @Test
- void testShouldVerifyCertificateSignatureWhenSelfSigned() {
- File certificateFile = new File("src/test/resources/rootCert.crt")
- FileReader certReader = new FileReader(certificateFile)
- X509Certificate certificate = TlsHelper.parseCertificate(certReader)
-
- boolean isCertificateSigned = TlsHelper.verifyCertificateSignature(certificate, [certificate])
- assert isCertificateSigned
- }
-
- @Test
- void testShouldVerifyCertificateSignatureWithMultipleSigningCerts() {
- File certificateFile = new File("src/test/resources/rootCert.crt")
- FileReader certReader = new FileReader(certificateFile)
- X509Certificate certificate = TlsHelper.parseCertificate(certReader)
-
- X509Certificate mockCertificate = [
- getSubjectX500Principal: { -> new X500Principal("CN=Mock Certificate") },
- getPublicKey : { -> badPublicKey }
- ] as X509Certificate
-
- boolean isCertificateSigned = TlsHelper.verifyCertificateSignature(certificate, [mockCertificate, certificate])
- assert isCertificateSigned
- }
-
- @Test
- void testShouldNotVerifyCertificateSignatureWithNoSigningCerts() {
- File certificateFile = new File("src/test/resources/rootCert.crt")
- FileReader certReader = new FileReader(certificateFile)
- X509Certificate certificate = TlsHelper.parseCertificate(certReader)
-
- boolean isCertificateSigned = TlsHelper.verifyCertificateSignature(certificate, [])
- assert !isCertificateSigned
- }
-
- @Test
- void testShouldNotVerifyCertificateSignatureWithWrongSigningCert() {
- File certificateFile = new File("src/test/resources/rootCert.crt")
- FileReader certReader = new FileReader(certificateFile)
- X509Certificate certificate = TlsHelper.parseCertificate(certReader)
-
- X509Certificate mockCertificate = [
- getSubjectX500Principal: { -> new X500Principal("CN=Mock Certificate") },
- getPublicKey : { -> badPublicKey }
- ] as X509Certificate
-
- boolean isCertificateSigned = TlsHelper.verifyCertificateSignature(certificate, [mockCertificate])
- assert !isCertificateSigned
- }
-
- @Test
- void testParseKeyPairFromReaderShouldHandlePKCS8PrivateKey() {
- File keyFile = new File("src/test/resources/rootCert-pkcs8.key")
- FileReader keyReader = new FileReader(keyFile)
-
- final KeyPair expectedKeyPair = TlsHelper.parseKeyPairFromReader(new FileReader(new File ("src/test/resources/rootCert.key")))
- final PrivateKey EXPECTED_PRIVATE_KEY = expectedKeyPair.getPrivate()
-
- KeyPair keyPair = TlsHelper.parseKeyPairFromReader(keyReader)
- assert keyPair.private == EXPECTED_PRIVATE_KEY
- }
-}
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneTest.java b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneTest.java
index 974ee849d3..d4bd6f839b 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneTest.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneTest.java
@@ -17,77 +17,79 @@
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.KeystoreType;
+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.TlsConfig;
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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+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.UUID;
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";
- public static final Logger logger = LoggerFactory.getLogger(TlsToolkitStandaloneTest.class);
private SystemExitCapturer systemExitCapturer;
+ @TempDir
private File tempDir;
@BeforeEach
public void setup() throws IOException {
- tempDir = File.createTempFile("tls-test", UUID.randomUUID().toString());
- if (!tempDir.delete()) {
- throw new IOException("Couldn't delete " + tempDir);
- }
-
- if (!tempDir.mkdirs()) {
- throw new IOException("Couldn't make directory " + tempDir);
- }
systemExitCapturer = new SystemExitCapturer();
}
@AfterEach
- public void teardown() throws IOException {
+ public void teardown() {
systemExitCapturer.close();
- FileUtils.deleteDirectory(tempDir);
}
@Test
@@ -104,7 +106,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testDirOutput() throws Exception {
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertNull(nifiProperties.get("nifi.fake.property"));
@@ -114,7 +116,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testDifferentArg() throws Exception {
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertNull(nifiProperties.get("nifi.fake.property"));
@@ -124,7 +126,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testFileArg() throws Exception {
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-f", TEST_NIFI_PROPERTIES, "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertEquals(FAKE_VALUE, nifiProperties.get(NIFI_FAKE_PROPERTY));
@@ -137,7 +139,7 @@ public class TlsToolkitStandaloneTest {
String nifi3 = "nifi3";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi1 + "," + nifi2);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi3);
checkHostDirAndReturnNifiProperties(nifi1, x509Certificate);
@@ -152,7 +154,7 @@ public class TlsToolkitStandaloneTest {
String nifi = "nifi";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
checkHostDirAndReturnNifiProperties(nifi, x509Certificate);
runAndAssertExitCode(ExitCode.ERROR_GENERATING_CONFIG, "-o", tempDir.getAbsolutePath(), "-n", nifi);
}
@@ -161,7 +163,7 @@ public class TlsToolkitStandaloneTest {
public void testKeyPasswordArg() throws Exception {
String testKey = "testKey";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-K", testKey, "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertEquals(testKey, nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD));
@@ -171,7 +173,7 @@ public class TlsToolkitStandaloneTest {
public void testKeyStorePasswordArg() throws Exception {
String testKeyStore = "testKeyStore";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-S", testKeyStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertEquals(testKeyStore, nifiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD));
@@ -181,7 +183,7 @@ public class TlsToolkitStandaloneTest {
public void testTrustStorePasswordArg() throws Exception {
String testTrustStore = "testTrustStore";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-P", testTrustStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertEquals(testTrustStore, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD));
@@ -193,7 +195,7 @@ public class TlsToolkitStandaloneTest {
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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, nifiDnPrefix, nifiDnSuffix, x509Certificate);
}
@@ -202,7 +204,7 @@ public class TlsToolkitStandaloneTest {
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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
}
@@ -211,7 +213,7 @@ public class TlsToolkitStandaloneTest {
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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
checkClientCert(clientDn, x509Certificate);
checkClientCert(clientDn2, x509Certificate);
@@ -224,7 +226,7 @@ public class TlsToolkitStandaloneTest {
public void testClientDnsArgNoOverwrite() throws Exception {
String clientDn = "OU=NIFI,CN=testuser";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-C", clientDn, "-B", "passwor");
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
checkClientCert(clientDn, x509Certificate);
@@ -236,7 +238,7 @@ public class TlsToolkitStandaloneTest {
String hostname = "static.nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", hostname);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Certificate[] certificateChain = loadCertificateChain(hostname, x509Certificate);
X509Certificate clientCert = (X509Certificate) certificateChain[0];
Collection> clientSaNames = clientCert.getSubjectAlternativeNames();
@@ -255,7 +257,7 @@ public class TlsToolkitStandaloneTest {
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", hostname, "--subjectAlternativeName", san);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Certificate[] certificateChain = loadCertificateChain(hostname, x509Certificate);
X509Certificate clientCert = (X509Certificate) certificateChain[0];
Collection> clientSaNames = clientCert.getSubjectAlternativeNames();
@@ -273,7 +275,7 @@ public class TlsToolkitStandaloneTest {
String san = "alternative.nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", san);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Stream hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
for (InstanceIdentifier hostInstance : (Iterable) hostIds::iterator) {
@@ -295,7 +297,7 @@ public class TlsToolkitStandaloneTest {
String saNames = "alternative[1-2].nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Stream hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
Stream sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
@@ -331,7 +333,7 @@ public class TlsToolkitStandaloneTest {
String saNames = "alternative[3-4].nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Stream hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
Stream sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
@@ -367,7 +369,7 @@ public class TlsToolkitStandaloneTest {
String saNames = "alternative[5-7].nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Stream hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
Stream sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
@@ -400,7 +402,7 @@ public class TlsToolkitStandaloneTest {
String saNames = "alternative[2-1].nifi.apache.org";
runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
- X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ X509Certificate x509Certificate = checkLoadCertPrivateKey();
Stream hostIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{nodeNames}));
Stream sansIds = InstanceIdentifier.createIdentifiers(Arrays.stream(new String[]{saNames}));
@@ -438,11 +440,122 @@ public class TlsToolkitStandaloneTest {
runAndAssertExitCode(ExitCode.ERROR_PARSING_INT_ARG, "-o", tempDir.getAbsolutePath(), "-n", nodeNames, "--subjectAlternativeName", saNames);
}
- private X509Certificate checkLoadCertPrivateKey(String algorithm) throws IOException, CertificateException {
+ @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(algorithm, keyPair.getPrivate().getAlgorithm());
- assertEquals(algorithm, keyPair.getPublic().getAlgorithm());
+ 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());
@@ -485,7 +598,7 @@ public class TlsToolkitStandaloneTest {
}
char[] keyPassword = nifiProperties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD).toCharArray();
- if (keyPassword == null || keyPassword.length == 0) {
+ if(ArrayUtils.isEmpty(keyPassword)) {
keyPassword = keyStorePassword;
}
@@ -529,7 +642,6 @@ public class TlsToolkitStandaloneTest {
certificateChain[0].verify(rootCert.getPublicKey());
PublicKey publicKey = certificateChain[0].getPublicKey();
TlsCertificateAuthorityTest.assertPrivateAndPublicKeyMatch(privateKey, publicKey);
-
}
private Certificate[] loadCertificateChain(String hostname, X509Certificate rootCert) throws Exception {
@@ -550,4 +662,65 @@ public class TlsToolkitStandaloneTest {
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);
+ }
}
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/util/TlsHelperTest.java b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/util/TlsHelperTest.java
index 191be74c91..738cefbd0e 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/util/TlsHelperTest.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/util/TlsHelperTest.java
@@ -34,14 +34,13 @@ import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
import org.bouncycastle.util.IPAddress;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.security.auth.x500.X500Principal;
import java.io.BufferedReader;
@@ -58,6 +57,7 @@ import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.UnrecoverableKeyException;
@@ -67,6 +67,7 @@ import java.security.cert.X509Certificate;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -75,31 +76,19 @@ import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class TlsHelperTest {
- public static final Logger logger = LoggerFactory.getLogger(TlsHelperTest.class);
-
+ private static final String PASSWORD = "changeit";
+ private static X509Certificate rootCert;
private int days;
-
private int keySize;
-
private String keyPairAlgorithm;
- private String signingAlgorithm;
-
- private KeyPairGenerator keyPairGenerator;
-
- private final String password = "changeit";
-
- @Mock(lenient = true)
- OutputStreamFactory outputStreamFactory;
-
- private File file;
-
public static KeyPair loadKeyPair(final Reader reader) throws IOException {
try (PEMParser pemParser = new PEMParser(reader)) {
Object object = pemParser.readObject();
@@ -128,19 +117,16 @@ public class TlsHelperTest {
}
}
+ @BeforeAll
+ static void setUpBeforeAll() throws Exception {
+ rootCert = TlsHelper.parseCertificate(new FileReader("src/test/resources/rootCert.crt"));
+ }
+
@BeforeEach
public void setup() throws Exception {
days = 360;
keySize = 2048;
keyPairAlgorithm = "RSA";
- signingAlgorithm = "SHA256withRSA";
- keyPairGenerator = KeyPairGenerator.getInstance(keyPairAlgorithm);
- keyPairGenerator.initialize(keySize);
-
- file = File.createTempFile("keystore", "file");
- file.deleteOnExit();
- ByteArrayOutputStream tmpFileOutputStream = new ByteArrayOutputStream();
- when(outputStreamFactory.create(file)).thenReturn(tmpFileOutputStream);
}
private Date inFuture(int days) {
@@ -149,13 +135,8 @@ public class TlsHelperTest {
@Test
public void testTokenLengthInCalculateHmac() throws GeneralSecurityException {
- List badTokens = new ArrayList<>();
- List goodTokens = new ArrayList<>();
- badTokens.add(null);
- badTokens.add("");
- badTokens.add("123");
- goodTokens.add("0123456789abcdefghijklm");
- goodTokens.add("0123456789abcdef");
+ List badTokens = Arrays.asList(null, "", "123");
+ List goodTokens = Arrays.asList("0123456789abcdefghijklm", "0123456789abcdef");
String dn = "CN=testDN,O=testOrg";
X509Certificate x509Certificate = new StandardCertificateBuilder(TlsHelper.generateKeyPair(keyPairAlgorithm, keySize), new X500Principal(dn), Duration.ofDays(days)).build();
@@ -193,14 +174,15 @@ public class TlsHelperTest {
assertTrue(notBefore.before(inFuture(1)));
assertEquals(dn, x509Certificate.getIssuerX500Principal().getName());
- assertEquals(signingAlgorithm, x509Certificate.getSigAlgName());
+ assertEquals("SHA256withRSA", x509Certificate.getSigAlgName());
assertEquals(keyPairAlgorithm, x509Certificate.getPublicKey().getAlgorithm());
x509Certificate.checkValidity();
}
@Test
- public void testWriteKeyStoreSuccess() throws IOException, GeneralSecurityException {
+ public void testWriteKeyStoreSuccess(@Mock OutputStreamFactory outputStreamFactory, @TempDir File file) throws IOException, GeneralSecurityException {
+ when(outputStreamFactory.create(file)).thenReturn(new ByteArrayOutputStream());
String testPassword = "testPassword";
final KeyStore keyStore = setupKeystore();
assertEquals(testPassword, TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, false));
@@ -209,32 +191,29 @@ public class TlsHelperTest {
@Test
public void testShouldIncludeSANFromCSR() throws Exception {
// Arrange
- final List SAN_ENTRIES = Arrays.asList("127.0.0.1", "nifi.nifi.apache.org");
- final int SAN_COUNT = SAN_ENTRIES.size();
- final String DN = "CN=localhost";
+ final List sanEntries = Arrays.asList("127.0.0.1", "nifi.nifi.apache.org");
+ final int sanCount = sanEntries.size();
+ final String dn = "CN=localhost";
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyPairAlgorithm);
+ keyPairGenerator.initialize(keySize);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
- logger.info("Generating CSR with DN: " + DN);
// Act
- JcaPKCS10CertificationRequest csrWithSan = TlsHelper.generateCertificationRequest(DN, SAN_ENTRIES, keyPair, TlsConfig.DEFAULT_SIGNING_ALGORITHM);
- logger.info("Created CSR with SAN: " + SAN_ENTRIES);
- String testCsrPem = TlsHelper.pemEncodeJcaObject(csrWithSan);
- logger.info("Encoded CSR as PEM: " + testCsrPem);
+ JcaPKCS10CertificationRequest csrWithSan = TlsHelper.generateCertificationRequest(dn, sanEntries, keyPair, TlsConfig.DEFAULT_SIGNING_ALGORITHM);
// Assert
String subjectName = csrWithSan.getSubject().toString();
- logger.info("CSR Subject Name: " + subjectName);
- assert subjectName.equals(DN);
+ assertEquals(dn, subjectName);
List extractedSans = extractSanFromCsr(csrWithSan);
- assert extractedSans.size() == SAN_COUNT + 1;
- List formattedSans = SAN_ENTRIES.stream()
+ assertEquals(sanCount + 1, extractedSans.size());
+ List formattedSans = sanEntries.stream()
.map(s -> (IPAddress.isValid(s) ? "IP Address: " + new GeneralName(GeneralName.iPAddress, s).getName() : "DNS: " + s))
.collect(Collectors.toList());
- assert extractedSans.containsAll(formattedSans);
+ assertTrue(extractedSans.containsAll(formattedSans));
// We check that the SANs also contain the CN
- assert extractedSans.contains("DNS: localhost");
+ assertTrue(extractedSans.contains("DNS: localhost"));
}
private List extractSanFromCsr(JcaPKCS10CertificationRequest csr) {
@@ -246,7 +225,6 @@ public class TlsHelperTest {
GeneralNames gns = GeneralNames.fromExtensions(extensions, Extension.subjectAlternativeName);
GeneralName[] names = gns.getNames();
for (GeneralName name : names) {
- logger.info("Type: " + name.getTagNo() + " | Name: " + name.getName());
String title = "";
if (name.getTagNo() == GeneralName.dNSName) {
title = "DNS";
@@ -325,7 +303,7 @@ public class TlsHelperTest {
private KeyStore setupKeystore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
KeyStore ks = KeyStore.getInstance("JKS");
try (InputStream readStream = getClass().getClassLoader().getResourceAsStream("keystore.jks")) {
- ks.load(readStream, password.toCharArray());
+ ks.load(readStream, PASSWORD.toCharArray());
}
return ks;
}
@@ -338,7 +316,7 @@ public class TlsHelperTest {
HashMap certs = TlsHelper.extractCerts(keyStore);
TlsHelper.outputCertsAsPem(certs, folder,".crt");
- assertEquals(folder.listFiles().length, 2);
+ assertEquals(2, folder.listFiles().length);
for (File file : folder.listFiles()) {
X509Certificate certFromFile = loadCertificate(file);
@@ -354,7 +332,7 @@ public class TlsHelperTest {
@Test
public void testOutputToFileOneKeyAsPem(@TempDir final File folder) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
KeyStore keyStore = setupKeystore();
- HashMap keys = TlsHelper.extractKeys(keyStore, password.toCharArray());
+ HashMap keys = TlsHelper.extractKeys(keyStore, PASSWORD.toCharArray());
TlsHelper.outputKeysAsPem(keys, folder, ".key");
for (File file : folder.listFiles()) {
@@ -379,8 +357,39 @@ public class TlsHelperTest {
@Test
public void testExtractKeys() throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
KeyStore keyStore = setupKeystore();
- HashMap keys = TlsHelper.extractKeys(keyStore, password.toCharArray());
+ HashMap keys = TlsHelper.extractKeys(keyStore, PASSWORD.toCharArray());
assertEquals(1, keys.size());
keys.forEach((String alias, Key key) -> assertEquals("PKCS#8", key.getFormat()));
}
+
+ @Test
+ public void testShouldVerifyCertificateSignatureWhenSelfSigned() {
+ assertTrue(TlsHelper.verifyCertificateSignature(rootCert, Collections.singletonList(rootCert)));
+ }
+
+ @Test
+ public void testShouldVerifyCertificateSignatureWithMultipleSigningCerts(@Mock X509Certificate mockCertificate) {
+ when(mockCertificate.getSubjectX500Principal()).thenReturn(new X500Principal("CN=Mock Certificate"));
+ assertTrue(TlsHelper.verifyCertificateSignature(rootCert, Arrays.asList(mockCertificate, rootCert)));
+ }
+
+ @Test
+ public void testShouldNotVerifyCertificateSignatureWithNoSigningCerts() {
+ assertFalse(TlsHelper.verifyCertificateSignature(rootCert, new ArrayList<>()));
+ }
+
+ @Test
+ public void testShouldNotVerifyCertificateSignatureWithWrongSigningCert(@Mock X509Certificate mockCertificate) {
+ when(mockCertificate.getSubjectX500Principal()).thenReturn(new X500Principal("CN=Mock Certificate"));
+ assertFalse(TlsHelper.verifyCertificateSignature(rootCert, Collections.singletonList(mockCertificate)));
+ }
+
+ @Test
+ public void testParseKeyPairFromReaderShouldHandlePKCS8PrivateKey() throws Exception {
+ final KeyPair expectedKeyPair = TlsHelper.parseKeyPairFromReader(new FileReader("src/test/resources/rootCert.key"));
+ final PrivateKey expectedPrivateKey = expectedKeyPair.getPrivate();
+ final KeyPair keyPair = TlsHelper.parseKeyPairFromReader(new FileReader("src/test/resources/rootCert-pkcs8.key"));
+
+ assertEquals(expectedPrivateKey, keyPair.getPrivate());
+ }
}