You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2016/08/15 14:22:37 UTC
[1/2] nifi git commit: NIFI-2526 - DN order, multiple standalone runs,
client certificates - Logic for sorting DN,
reversing X500Names before using them to generate certificate - Logging
reordered dn - Accounting for limited crypto pkcs12, allowing passw
Repository: nifi
Updated Branches:
refs/heads/master fd0dd51ff -> fa5da543e
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneTest.java
----------------------------------------------------------------------
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 6746c40..af81eae 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
@@ -18,27 +18,36 @@
package org.apache.nifi.toolkit.tls.standalone;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
+import org.apache.nifi.toolkit.tls.manager.BaseTlsManager;
+import org.apache.nifi.toolkit.tls.service.TlsCertificateAuthorityTest;
import org.apache.nifi.toolkit.tls.util.TlsHelperTest;
import org.apache.nifi.util.NiFiProperties;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
+import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
+import java.util.List;
import java.util.Properties;
import java.util.UUID;
@@ -95,18 +104,18 @@ public class TlsToolkitStandaloneTest {
@Test
public void testBadParse() {
- runAndAssertExitCode(ExitCode.ERROR_PARSING_COMMAND_LINE.ordinal(), "--unknownArgument");
+ runAndAssertExitCode(ExitCode.ERROR_PARSING_COMMAND_LINE, "--unknownArgument");
}
@Test
public void testHelp() {
- runAndAssertExitCode(ExitCode.HELP.ordinal(), "-h");
- runAndAssertExitCode(ExitCode.HELP.ordinal(), "--help");
+ runAndAssertExitCode(ExitCode.HELP, "-h");
+ runAndAssertExitCode(ExitCode.HELP, "--help");
}
@Test
public void testDirOutput() throws Exception {
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath());
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
@@ -116,7 +125,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testDifferentArg() throws Exception {
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-g");
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
@@ -126,7 +135,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testFileArg() throws Exception {
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-f", TEST_NIFI_PROPERTIES);
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-f", TEST_NIFI_PROPERTIES, "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
@@ -134,23 +143,36 @@ public class TlsToolkitStandaloneTest {
}
@Test
- public void testHostnamesArgument() throws Exception {
+ public void testHostnamesArgumentOverwrite() throws Exception {
String nifi1 = "nifi1";
String nifi2 = "nifi2";
String nifi3 = "nifi3";
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-n", nifi1 + "," + nifi2 + "," + nifi3);
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-n", nifi1 + "," + nifi2);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ 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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+ checkHostDirAndReturnNifiProperties(nifi, x509Certificate);
+ runAndAssertExitCode(ExitCode.ERROR_GENERATING_CONFIG, "-o", tempDir.getAbsolutePath(), "-n", nifi);
}
@Test
public void testKeyPasswordArg() throws Exception {
String testKey = "testKey";
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-K", testKey);
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-K", testKey, "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
@@ -160,7 +182,7 @@ public class TlsToolkitStandaloneTest {
@Test
public void testKeyStorePasswordArg() throws Exception {
String testKeyStore = "testKeyStore";
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-S", testKeyStore);
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-S", testKeyStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
@@ -170,13 +192,38 @@ public class TlsToolkitStandaloneTest {
@Test
public void testTrustStorePasswordArg() throws Exception {
String testTrustStore = "testTrustStore";
- runAndAssertExitCode(0, "-o", tempDir.getAbsolutePath(), "-P", testTrustStore);
+ runAndAssertExitCode(ExitCode.SUCCESS, "-o", tempDir.getAbsolutePath(), "-P", testTrustStore, "-n", TlsConfig.DEFAULT_HOSTNAME);
X509Certificate x509Certificate = checkLoadCertPrivateKey(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
Properties nifiProperties = checkHostDirAndReturnNifiProperties(TlsConfig.DEFAULT_HOSTNAME, x509Certificate);
assertEquals(testTrustStore, nifiProperties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD));
}
+ @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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+
+ 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(TlsConfig.DEFAULT_KEY_PAIR_ALGORITHM);
+
+ checkClientCert(clientDn, x509Certificate);
+
+ runAndAssertExitCode(ExitCode.ERROR_GENERATING_CONFIG, "-o", tempDir.getAbsolutePath(), "-C", clientDn);
+ }
+
private X509Certificate checkLoadCertPrivateKey(String algorithm) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, CertificateException {
KeyPair keyPair = TlsHelperTest.loadKeyPair(new File(tempDir, TlsToolkitStandalone.NIFI_KEY + ".key"));
@@ -227,15 +274,40 @@ public class TlsToolkitStandaloneTest {
assertEquals(rootCert, certificateChain[1]);
certificateChain[1].verify(rootCert.getPublicKey());
certificateChain[0].verify(rootCert.getPublicKey());
+ TlsCertificateAuthorityTest.assertPrivateAndPublicKeyMatch(privateKeyEntry.getPrivateKey(), certificateChain[0].getPublicKey());
return nifiProperties;
}
- private void runAndAssertExitCode(int exitCode, String... args) {
+ private void checkClientCert(String clientDn, X509Certificate rootCert) throws Exception {
+ String clientDnFile = TlsToolkitStandalone.getClientDnFile(CertificateUtils.reorderDn(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 = KeyStore.getInstance(BaseTlsManager.PKCS_12, BouncyCastleProvider.PROVIDER_NAME);
+ try (FileInputStream fileInputStream = new FileInputStream(new File(tempDir, clientDnFile + ".p12"))) {
+ keyStore.load(fileInputStream, password.toCharArray());
+ }
+ PrivateKey privateKey = (PrivateKey) keyStore.getKey(TlsToolkitStandalone.NIFI_KEY, new char[0]);
+ 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 void runAndAssertExitCode(ExitCode exitCode, String... args) {
try {
TlsToolkitStandaloneCommandLine.main(args);
fail("Expecting exit code: " + exitCode);
} catch (ExitException e) {
- assertEquals(exitCode, e.getExitCode());
+ assertEquals(exitCode, ExitCode.values()[e.getExitCode()]);
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/util/TlsHelperTest.java
----------------------------------------------------------------------
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 a900a4f..66ec890 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
@@ -25,23 +25,32 @@ import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.operator.OperatorCreationException;
+import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.AdditionalMatchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
+import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.security.SecureRandom;
+import java.security.Provider;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateException;
@@ -51,9 +60,17 @@ import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+@RunWith(MockitoJUnitRunner.class)
public class TlsHelperTest {
+ private static final boolean originalUnlimitedCrypto = TlsHelper.isUnlimitedStrengthCryptographyEnabled();
+
private int days;
private int keySize;
@@ -62,11 +79,32 @@ public class TlsHelperTest {
private String signingAlgorithm;
- private String keyStoreType;
+ private KeyPairGenerator keyPairGenerator;
- private SecureRandom secureRandom;
+ private KeyStore keyStore;
- private KeyPairGenerator keyPairGenerator;
+ @Mock
+ KeyStoreSpi keyStoreSpi;
+
+ @Mock
+ Provider keyStoreProvider;
+
+ @Mock
+ OutputStreamFactory outputStreamFactory;
+
+ private ByteArrayOutputStream tmpFileOutputStream;
+
+ private File file;
+
+ private static void setUnlimitedCrypto(boolean value) {
+ try {
+ Field isUnlimitedStrengthCryptographyEnabled = TlsHelper.class.getDeclaredField("isUnlimitedStrengthCryptographyEnabled");
+ isUnlimitedStrengthCryptographyEnabled.setAccessible(true);
+ isUnlimitedStrengthCryptographyEnabled.set(null, value);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
public static KeyPair loadKeyPair(Reader reader) throws IOException {
try (PEMParser pemParser = new PEMParser(reader)) {
@@ -98,15 +136,25 @@ public class TlsHelperTest {
}
@Before
- public void setup() throws NoSuchAlgorithmException {
+ public void setup() throws Exception {
days = 360;
keySize = 2048;
keyPairAlgorithm = "RSA";
signingAlgorithm = "SHA1WITHRSA";
- keyStoreType = KeyStore.getDefaultType();
- secureRandom = mock(SecureRandom.class);
keyPairGenerator = KeyPairGenerator.getInstance(keyPairAlgorithm);
keyPairGenerator.initialize(keySize);
+ Constructor<KeyStore> keyStoreConstructor = KeyStore.class.getDeclaredConstructor(KeyStoreSpi.class, Provider.class, String.class);
+ keyStoreConstructor.setAccessible(true);
+ keyStore = keyStoreConstructor.newInstance(keyStoreSpi, keyStoreProvider, "faketype");
+ keyStore.load(null, null);
+ file = File.createTempFile("keystore", "file");
+ when(outputStreamFactory.create(file)).thenReturn(tmpFileOutputStream);
+ }
+
+ @After
+ public void tearDown() {
+ setUnlimitedCrypto(originalUnlimitedCrypto);
+ file.delete();
}
private Date inFuture(int days) {
@@ -127,7 +175,7 @@ public class TlsHelperTest {
assertTrue(notBefore.after(inFuture(-1)));
assertTrue(notBefore.before(inFuture(1)));
- assertEquals(dn, x509Certificate.getIssuerDN().getName());
+ assertEquals(dn, x509Certificate.getIssuerX500Principal().getName());
assertEquals(signingAlgorithm, x509Certificate.getSigAlgName());
assertEquals(keyPairAlgorithm, x509Certificate.getPublicKey().getAlgorithm());
@@ -139,12 +187,12 @@ public class TlsHelperTest {
X509Certificate issuer = loadCertificate(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("rootCert.crt")));
KeyPair issuerKeyPair = loadKeyPair(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("rootCert.key")));
- String dn = "CN=testIssued,O=testOrg";
+ String dn = "CN=testIssued, O=testOrg";
KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
X509Certificate x509Certificate = CertificateUtils.generateIssuedCertificate(dn, keyPair.getPublic(), issuer, issuerKeyPair, signingAlgorithm, days);
- assertEquals(dn, x509Certificate.getSubjectDN().toString());
- assertEquals(issuer.getSubjectDN().toString(), x509Certificate.getIssuerDN().toString());
+ assertEquals(dn, x509Certificate.getSubjectX500Principal().toString());
+ assertEquals(issuer.getSubjectX500Principal().toString(), x509Certificate.getIssuerX500Principal().toString());
assertEquals(keyPair.getPublic(), x509Certificate.getPublicKey());
Date notAfter = x509Certificate.getNotAfter();
@@ -160,4 +208,83 @@ public class TlsHelperTest {
x509Certificate.verify(issuerKeyPair.getPublic());
}
+
+ @Test
+ public void testWriteKeyStoreSuccess() throws IOException, GeneralSecurityException {
+ setUnlimitedCrypto(false);
+ String testPassword = "testPassword";
+ assertEquals(testPassword, TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, false));
+ verify(keyStoreSpi, times(1)).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ }
+
+ @Test
+ public void testWriteKeyStoreFailure() throws IOException, GeneralSecurityException {
+ setUnlimitedCrypto(false);
+ String testPassword = "testPassword";
+ IOException ioException = new IOException("Fail");
+ doThrow(ioException).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ try {
+ TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, true);
+ fail("Expected " + ioException);
+ } catch (IOException e) {
+ assertEquals(ioException, e);
+ }
+ }
+
+ @Test
+ public void testWriteKeyStoreTruncate() throws IOException, GeneralSecurityException {
+ setUnlimitedCrypto(false);
+ String testPassword = "testPassword";
+ String truncatedPassword = testPassword.substring(0, 7);
+ IOException ioException = new IOException(TlsHelper.ILLEGAL_KEY_SIZE);
+ doThrow(ioException).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ assertEquals(truncatedPassword, TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, true));
+ verify(keyStoreSpi, times(1)).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ verify(keyStoreSpi, times(1)).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(truncatedPassword.toCharArray()));
+ }
+
+ @Test
+ public void testWriteKeyStoreUnlimitedWontTruncate() throws GeneralSecurityException, IOException {
+ setUnlimitedCrypto(true);
+ String testPassword = "testPassword";
+ IOException ioException = new IOException(TlsHelper.ILLEGAL_KEY_SIZE);
+ doThrow(ioException).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ try {
+ TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, true);
+ fail("Expected " + ioException);
+ } catch (IOException e) {
+ assertEquals(ioException, e);
+ }
+ }
+
+ @Test
+ public void testWriteKeyStoreNoTruncate() throws IOException, GeneralSecurityException {
+ setUnlimitedCrypto(false);
+ String testPassword = "testPassword";
+ IOException ioException = new IOException(TlsHelper.ILLEGAL_KEY_SIZE);
+ doThrow(ioException).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ try {
+ TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, false);
+ fail("Expected " + GeneralSecurityException.class);
+ } catch (GeneralSecurityException e) {
+ assertTrue("Expected exception to contain " + TlsHelper.JCE_URL, e.getMessage().contains(TlsHelper.JCE_URL));
+ }
+ }
+
+ @Test
+ public void testWriteKeyStoreTruncateFailure() throws IOException, GeneralSecurityException {
+ setUnlimitedCrypto(false);
+ String testPassword = "testPassword";
+ String truncatedPassword = testPassword.substring(0, 7);
+ IOException ioException = new IOException(TlsHelper.ILLEGAL_KEY_SIZE);
+ IOException ioException2 = new IOException(TlsHelper.ILLEGAL_KEY_SIZE);
+ doThrow(ioException).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(testPassword.toCharArray()));
+ doThrow(ioException2).when(keyStoreSpi).engineStore(eq(tmpFileOutputStream), AdditionalMatchers.aryEq(truncatedPassword.toCharArray()));
+ try {
+ TlsHelper.writeKeyStore(keyStore, outputStreamFactory, file, testPassword, true);
+ fail("Expected " + ioException2);
+ } catch (IOException e) {
+ assertEquals(ioException2, e);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/resources/log4j.properties b/nifi-toolkit/nifi-toolkit-tls/src/test/resources/log4j.properties
new file mode 100644
index 0000000..fc2aaf1
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/resources/log4j.properties
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+log4j.rootLogger=INFO,console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
\ No newline at end of file
[2/2] nifi git commit: NIFI-2526 - DN order, multiple standalone runs,
client certificates - Logic for sorting DN,
reversing X500Names before using them to generate certificate - Logging
reordered dn - Accounting for limited crypto pkcs12, allowing passw
Posted by bb...@apache.org.
NIFI-2526 - DN order, multiple standalone runs, client certificates
- Logic for sorting DN, reversing X500Names before using them to generate certificate
- Logging reordered dn
- Accounting for limited crypto pkcs12, allowing password specification for client certificates
- Updating tests to work with or without jce unlimited
- Loading keystore for test in try-with
This closes #824.
Signed-off-by: Bryan Bende <bb...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/fa5da543
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/fa5da543
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/fa5da543
Branch: refs/heads/master
Commit: fa5da543e6334aec363f5fb0c470a7e0b682042d
Parents: fd0dd51
Author: Bryan Rosander <br...@gmail.com>
Authored: Tue Aug 9 11:11:21 2016 -0400
Committer: Bryan Bende <bb...@apache.org>
Committed: Mon Aug 15 10:21:34 2016 -0400
----------------------------------------------------------------------
.../nifi/security/util/CertificateUtils.java | 99 ++++++++++-
.../security/util/CertificateUtilsTest.groovy | 26 ++-
.../nifi/toolkit/tls/commandLine/ExitCode.java | 1 -
.../tls/configuration/StandaloneConfig.java | 125 ++++++++++++++
.../toolkit/tls/configuration/TlsConfig.java | 3 +-
.../toolkit/tls/manager/BaseTlsManager.java | 14 +-
.../manager/TlsCertificateAuthorityManager.java | 2 +-
.../toolkit/tls/manager/TlsClientManager.java | 13 +-
.../TlsCertificateSigningRequestPerformer.java | 8 +-
.../TlsCertificateAuthorityServiceHandler.java | 6 +-
.../tls/standalone/TlsToolkitStandalone.java | 168 +++++++++++++++----
.../TlsToolkitStandaloneCommandLine.java | 118 +++++++------
.../apache/nifi/toolkit/tls/util/TlsHelper.java | 99 ++++++++++-
.../service/TlsCertificateAuthorityTest.java | 4 +-
...sCertificateAuthorityServiceHandlerTest.java | 2 +-
.../TlsToolkitStandaloneCommandLineTest.java | 107 ++++++++----
.../standalone/TlsToolkitStandaloneTest.java | 98 +++++++++--
.../nifi/toolkit/tls/util/TlsHelperTest.java | 151 +++++++++++++++--
.../src/test/resources/log4j.properties | 22 +++
19 files changed, 882 insertions(+), 184 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
index 2049718..760e82e 100644
--- a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
+++ b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
@@ -17,7 +17,11 @@
package org.apache.nifi.security.util;
import org.apache.commons.lang3.StringUtils;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
+import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
@@ -57,16 +61,37 @@ import java.security.cert.CertificateFactory;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
public final class CertificateUtils {
-
private static final Logger logger = LoggerFactory.getLogger(CertificateUtils.class);
private static final String PEER_NOT_AUTHENTICATED_MSG = "peer not authenticated";
+ private static final Map<ASN1ObjectIdentifier, Integer> dnOrderMap = createDnOrderMap();
+
+ private static Map<ASN1ObjectIdentifier, Integer> createDnOrderMap() {
+ Map<ASN1ObjectIdentifier, Integer> orderMap = new HashMap<>();
+ int count = 0;
+ orderMap.put(BCStyle.CN, count++);
+ orderMap.put(BCStyle.L, count++);
+ orderMap.put(BCStyle.ST, count++);
+ orderMap.put(BCStyle.O, count++);
+ orderMap.put(BCStyle.OU, count++);
+ orderMap.put(BCStyle.C, count++);
+ orderMap.put(BCStyle.STREET, count++);
+ orderMap.put(BCStyle.DC, count++);
+ orderMap.put(BCStyle.UID, count++);
+ return Collections.unmodifiableMap(orderMap);
+ }
+
public enum ClientAuth {
NONE(0, "none"),
WANT(1, "want"),
@@ -350,6 +375,70 @@ public final class CertificateUtils {
}
/**
+ * Reorders DN to the order the elements appear in the RFC 2253 table
+ *
+ * https://www.ietf.org/rfc/rfc2253.txt
+ *
+ * String X.500 AttributeType
+ * ------------------------------
+ * CN commonName
+ * L localityName
+ * ST stateOrProvinceName
+ * O organizationName
+ * OU organizationalUnitName
+ * C countryName
+ * STREET streetAddress
+ * DC domainComponent
+ * UID userid
+ *
+ * @param dn a possibly unordered DN
+ * @return the ordered dn
+ */
+ public static String reorderDn(String dn) {
+ RDN[] rdNs = new X500Name(dn).getRDNs();
+ Arrays.sort(rdNs, new Comparator<RDN>() {
+ @Override
+ public int compare(RDN o1, RDN o2) {
+ AttributeTypeAndValue o1First = o1.getFirst();
+ AttributeTypeAndValue o2First = o2.getFirst();
+
+ ASN1ObjectIdentifier o1Type = o1First.getType();
+ ASN1ObjectIdentifier o2Type = o2First.getType();
+
+ Integer o1Rank = dnOrderMap.get(o1Type);
+ Integer o2Rank = dnOrderMap.get(o2Type);
+ if (o1Rank == null) {
+ if (o2Rank == null) {
+ int idComparison = o1Type.getId().compareTo(o2Type.getId());
+ if (idComparison != 0) {
+ return idComparison;
+ }
+ return String.valueOf(o1Type).compareTo(String.valueOf(o2Type));
+ }
+ return 1;
+ } else if (o2Rank == null) {
+ return -1;
+ }
+ return o1Rank - o2Rank;
+ }
+ });
+ return new X500Name(rdNs).toString();
+ }
+
+ /**
+ * Reverses the X500Name in order make the certificate be in the right order
+ * [see http://stackoverflow.com/questions/7567837/attributes-reversed-in-certificate-subject-and-issuer/12645265]
+ *
+ * @param x500Name the X500Name created with the intended order
+ * @return the X500Name reversed
+ */
+ private static X500Name reverseX500Name(X500Name x500Name) {
+ List<RDN> rdns = Arrays.asList(x500Name.getRDNs());
+ Collections.reverse(rdns);
+ return new X500Name(rdns.toArray(new RDN[rdns.size()]));
+ }
+
+ /**
* Generates a self-signed {@link X509Certificate} suitable for use as a Certificate Authority.
*
* @param keyPair the {@link KeyPair} to generate the {@link X509Certificate} for
@@ -368,10 +457,10 @@ public final class CertificateUtils {
Date endDate = new Date(startDate.getTime() + TimeUnit.DAYS.toMillis(certificateDurationDays));
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
- new X500Name(dn),
+ reverseX500Name(new X500Name(dn)),
BigInteger.valueOf(System.currentTimeMillis()),
startDate, endDate,
- new X500Name(dn),
+ reverseX500Name(new X500Name(dn)),
subPubKeyInfo);
// Set certificate extensions
@@ -417,10 +506,10 @@ public final class CertificateUtils {
Date endDate = new Date(startDate.getTime() + TimeUnit.DAYS.toMillis(days));
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
- new X500Name(issuer.getSubjectDN().getName()),
+ reverseX500Name(new X500Name(issuer.getSubjectX500Principal().getName())),
BigInteger.valueOf(System.currentTimeMillis()),
startDate, endDate,
- new X500Name(dn),
+ reverseX500Name(new X500Name(dn)),
subPubKeyInfo);
certBuilder.addExtension(Extension.subjectKeyIdentifier, false, new JcaX509ExtensionUtils().createSubjectKeyIdentifier(publicKey));
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy b/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
index 7f93f51..6727364 100644
--- a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
+++ b/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
@@ -443,7 +443,7 @@ class CertificateUtilsTest extends GroovyTestCase {
assertTrue(notBefore.after(inFuture(-1)));
assertTrue(notBefore.before(inFuture(1)));
- assertEquals(dn, x509Certificate.getIssuerDN().getName());
+ assertEquals(dn, x509Certificate.getIssuerX500Principal().getName());
assertEquals(SIGNATURE_ALGORITHM.toUpperCase(), x509Certificate.getSigAlgName().toUpperCase());
assertEquals("RSA", x509Certificate.getPublicKey().getAlgorithm());
@@ -458,12 +458,12 @@ class CertificateUtilsTest extends GroovyTestCase {
KeyPair issuerKeyPair = generateKeyPair();
X509Certificate issuer = CertificateUtils.generateSelfSignedX509Certificate(issuerKeyPair, "CN=testCa,O=testOrg", SIGNATURE_ALGORITHM, days);
- String dn = "CN=testIssued,O=testOrg";
+ String dn = "CN=testIssued, O=testOrg";
KeyPair keyPair = generateKeyPair();
X509Certificate x509Certificate = CertificateUtils.generateIssuedCertificate(dn, keyPair.getPublic(), issuer, issuerKeyPair, SIGNATURE_ALGORITHM, days);
- assertEquals(dn, x509Certificate.getSubjectDN().toString());
- assertEquals(issuer.getSubjectDN().toString(), x509Certificate.getIssuerDN().toString());
+ assertEquals(dn, x509Certificate.getSubjectX500Principal().toString());
+ assertEquals(issuer.getSubjectX500Principal().toString(), x509Certificate.getIssuerX500Principal().toString());
assertEquals(keyPair.getPublic(), x509Certificate.getPublicKey());
Date notAfter = x509Certificate.getNotAfter();
@@ -479,4 +479,22 @@ class CertificateUtilsTest extends GroovyTestCase {
x509Certificate.verify(issuerKeyPair.getPublic());
}
+
+ @Test
+ public void reorderShouldPutElementsInCorrectOrder() {
+ String cn = "CN=testcn";
+ String l = "L=testl";
+ String st = "ST=testst";
+ String o = "O=testo";
+ String ou = "OU=testou";
+ String c = "C=testc";
+ String street = "STREET=teststreet";
+ String dc = "DC=testdc";
+ String uid = "UID=testuid";
+ String surname = "SURNAME=testsurname";
+ String initials = "INITIALS=testinitials";
+ String givenName = "GIVENNAME=testgivenname";
+ assertEquals("$cn,$l,$st,$o,$ou,$c,$street,$dc,$uid,$surname,$givenName,$initials".toString(),
+ CertificateUtils.reorderDn("$surname,$st,$o,$initials,$givenName,$uid,$street,$c,$cn,$ou,$l,$dc"));
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/commandLine/ExitCode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/commandLine/ExitCode.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/commandLine/ExitCode.java
index b99b1af..f06ac2d 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/commandLine/ExitCode.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/commandLine/ExitCode.java
@@ -24,7 +24,6 @@ public enum ExitCode {
SERVICE_ERROR,
ERROR_PARSING_COMMAND_LINE,
ERROR_GENERATING_CONFIG,
- ERROR_SAME_KEY_AND_KEY_PASSWORD,
ERROR_INCORRECT_NUMBER_OF_PASSWORDS,
ERROR_PARSING_INT_ARG,
ERROR_TOKEN_ARG_EMPTY,
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/StandaloneConfig.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/StandaloneConfig.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/StandaloneConfig.java
new file mode 100644
index 0000000..342e1e5
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/StandaloneConfig.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.toolkit.tls.configuration;
+
+import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
+
+import java.io.File;
+import java.util.List;
+
+public class StandaloneConfig extends TlsConfig {
+ private File baseDir;
+ private NiFiPropertiesWriterFactory niFiPropertiesWriterFactory;
+ private List<String> hostnames;
+ private List<String> keyStorePasswords;
+ private List<String> keyPasswords;
+ private List<String> trustStorePasswords;
+ private List<String> clientDns;
+ private List<String> clientPasswords;
+ private boolean clientPasswordsGenerated;
+ private int httpsPort;
+ private boolean overwrite;
+
+ public List<String> getClientDns() {
+ return clientDns;
+ }
+
+ public void setClientDns(List<String> clientDns) {
+ this.clientDns = clientDns;
+ }
+
+ public boolean isOverwrite() {
+ return overwrite;
+ }
+
+ public void setOverwrite(boolean overwrite) {
+ this.overwrite = overwrite;
+ }
+
+ public File getBaseDir() {
+ return baseDir;
+ }
+
+ public void setBaseDir(File baseDir) {
+ this.baseDir = baseDir;
+ }
+
+ public NiFiPropertiesWriterFactory getNiFiPropertiesWriterFactory() {
+ return niFiPropertiesWriterFactory;
+ }
+
+ public void setNiFiPropertiesWriterFactory(NiFiPropertiesWriterFactory niFiPropertiesWriterFactory) {
+ this.niFiPropertiesWriterFactory = niFiPropertiesWriterFactory;
+ }
+
+ public List<String> getHostnames() {
+ return hostnames;
+ }
+
+ public void setHostnames(List<String> hostnames) {
+ this.hostnames = hostnames;
+ }
+
+ public List<String> getKeyStorePasswords() {
+ return keyStorePasswords;
+ }
+
+ public void setKeyStorePasswords(List<String> keyStorePasswords) {
+ this.keyStorePasswords = keyStorePasswords;
+ }
+
+ public List<String> getKeyPasswords() {
+ return keyPasswords;
+ }
+
+ public void setKeyPasswords(List<String> keyPasswords) {
+ this.keyPasswords = keyPasswords;
+ }
+
+ public List<String> getTrustStorePasswords() {
+ return trustStorePasswords;
+ }
+
+ public void setTrustStorePasswords(List<String> trustStorePasswords) {
+ this.trustStorePasswords = trustStorePasswords;
+ }
+
+ public List<String> getClientPasswords() {
+ return clientPasswords;
+ }
+
+ public void setClientPasswords(List<String> clientPasswords) {
+ this.clientPasswords = clientPasswords;
+ }
+
+ public int getHttpsPort() {
+ return httpsPort;
+ }
+
+ public void setHttpsPort(int httpsPort) {
+ this.httpsPort = httpsPort;
+ }
+
+ public boolean isClientPasswordsGenerated() {
+ return clientPasswordsGenerated;
+ }
+
+ public void setClientPasswordsGenerated(boolean clientPasswordsGenerated) {
+ this.clientPasswordsGenerated = clientPasswordsGenerated;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/TlsConfig.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/TlsConfig.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/TlsConfig.java
index 819b41b..8aa3e40 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/TlsConfig.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/configuration/TlsConfig.java
@@ -17,6 +17,7 @@
package org.apache.nifi.toolkit.tls.configuration;
+import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.util.StringUtils;
public class TlsConfig {
@@ -43,7 +44,7 @@ public class TlsConfig {
private int port = DEFAULT_PORT;
public static String calcDefaultDn(String hostname) {
- return "CN=" + hostname + ",OU=NIFI";
+ return CertificateUtils.reorderDn("CN=" + hostname + ",OU=NIFI");
}
public int getPort() {
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/BaseTlsManager.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/BaseTlsManager.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/BaseTlsManager.java
index 5a5e049..6215fc0 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/BaseTlsManager.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/BaseTlsManager.java
@@ -22,6 +22,7 @@ import org.apache.nifi.toolkit.tls.manager.writer.ConfigurationWriter;
import org.apache.nifi.toolkit.tls.util.InputStreamFactory;
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
+import org.apache.nifi.toolkit.tls.util.TlsHelper;
import org.apache.nifi.util.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -29,7 +30,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyStore;
@@ -38,7 +38,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +49,7 @@ public class BaseTlsManager {
private final KeyStore keyStore;
private final List<ConfigurationWriter<TlsConfig>> configurationWriters;
private boolean differentKeyAndKeyStorePassword = false;
+ private boolean keyStorePasswordGenerated = false;
public BaseTlsManager(TlsConfig tlsConfig) throws GeneralSecurityException, IOException {
this(tlsConfig, new PasswordUtil(), FileInputStream::new);
@@ -107,13 +107,14 @@ public class BaseTlsManager {
String result = tlsConfig.getKeyStorePassword();
if (StringUtils.isEmpty(result)) {
result = passwordUtil.generatePassword();
+ keyStorePasswordGenerated = true;
tlsConfig.setKeyStorePassword(result);
}
return result;
}
private KeyStore getInstance(String keyStoreType) throws KeyStoreException, NoSuchProviderException {
- if (PKCS_12.equals(keyStoreType)) {
+ if (PKCS_12.equalsIgnoreCase(keyStoreType)) {
return KeyStore.getInstance(keyStoreType, BouncyCastleProvider.PROVIDER_NAME);
} else {
return KeyStore.getInstance(keyStoreType);
@@ -133,12 +134,9 @@ public class BaseTlsManager {
return result;
}
- public void write(OutputStreamFactory outputStreamFactory) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
+ public void write(OutputStreamFactory outputStreamFactory) throws IOException, GeneralSecurityException {
String keyStorePassword = getKeyStorePassword();
-
- try (OutputStream outputStream = outputStreamFactory.create(new File(tlsConfig.getKeyStore()))) {
- keyStore.store(outputStream, keyStorePassword.toCharArray());
- }
+ tlsConfig.setKeyStorePassword(TlsHelper.writeKeyStore(keyStore, outputStreamFactory, new File(tlsConfig.getKeyStore()), keyStorePassword, keyStorePasswordGenerated));
for (ConfigurationWriter<TlsConfig> configurationWriter : configurationWriters) {
configurationWriter.write(tlsConfig);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsCertificateAuthorityManager.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsCertificateAuthorityManager.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsCertificateAuthorityManager.java
index 39faf28..2fa0534 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsCertificateAuthorityManager.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsCertificateAuthorityManager.java
@@ -38,7 +38,7 @@ public class TlsCertificateAuthorityManager extends BaseTlsManager {
if (entry == null) {
TlsConfig tlsConfig = getTlsConfig();
KeyPair keyPair = TlsHelper.generateKeyPair(tlsConfig.getKeyPairAlgorithm(), tlsConfig.getKeySize());
- X509Certificate caCert = CertificateUtils.generateSelfSignedX509Certificate(keyPair, tlsConfig.getDn(), tlsConfig.getSigningAlgorithm(), tlsConfig.getDays());
+ X509Certificate caCert = CertificateUtils.generateSelfSignedX509Certificate(keyPair, CertificateUtils.reorderDn(tlsConfig.getDn()), tlsConfig.getSigningAlgorithm(), tlsConfig.getDays());
entry = addPrivateKeyToKeyStore(keyPair, TlsToolkitStandalone.NIFI_KEY, caCert);
} else if (!KeyStore.PrivateKeyEntry.class.isInstance(entry)) {
throw new IOException("Expected " + TlsToolkitStandalone.NIFI_KEY + " alias to contain a private key entry");
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsClientManager.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsClientManager.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsClientManager.java
index 52ea5db..3113701 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsClientManager.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/manager/TlsClientManager.java
@@ -22,6 +22,7 @@ import org.apache.nifi.toolkit.tls.manager.writer.ConfigurationWriter;
import org.apache.nifi.toolkit.tls.util.InputStreamFactory;
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
+import org.apache.nifi.toolkit.tls.util.TlsHelper;
import org.apache.nifi.util.StringUtils;
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
import org.bouncycastle.util.io.pem.PemWriter;
@@ -34,10 +35,8 @@ import java.io.OutputStreamWriter;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -73,18 +72,18 @@ public class TlsClientManager extends BaseTlsManager {
}
@Override
- public void write(OutputStreamFactory outputStreamFactory) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
+ public void write(OutputStreamFactory outputStreamFactory) throws IOException, GeneralSecurityException {
super.write(outputStreamFactory);
String trustStorePassword = tlsClientConfig.getTrustStorePassword();
+ boolean trustStorePasswordGenerated = false;
if (StringUtils.isEmpty(trustStorePassword)) {
trustStorePassword = getPasswordUtil().generatePassword();
- tlsClientConfig.setTrustStorePassword(trustStorePassword);
+ trustStorePasswordGenerated = true;
}
- try (OutputStream outputStream = outputStreamFactory.create(new File(tlsClientConfig.getTrustStore()))) {
- trustStore.store(outputStream, trustStorePassword.toCharArray());
- }
+ trustStorePassword = TlsHelper.writeKeyStore(trustStore, outputStreamFactory, new File(tlsClientConfig.getTrustStore()), trustStorePassword, trustStorePasswordGenerated);
+ tlsClientConfig.setTrustStorePassword(trustStorePassword);
for (ConfigurationWriter<TlsClientConfig> configurationWriter : configurationWriters) {
configurationWriter.write(tlsClientConfig);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/client/TlsCertificateSigningRequestPerformer.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/client/TlsCertificateSigningRequestPerformer.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/client/TlsCertificateSigningRequestPerformer.java
index 2c65964..889f217 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/client/TlsCertificateSigningRequestPerformer.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/client/TlsCertificateSigningRequestPerformer.java
@@ -28,6 +28,7 @@ import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.nifi.security.util.CertificateUtils;
import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
import org.apache.nifi.toolkit.tls.service.dto.TlsCertificateAuthorityRequest;
import org.apache.nifi.toolkit.tls.service.dto.TlsCertificateAuthorityResponse;
@@ -38,6 +39,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.MessageDigest;
@@ -73,7 +75,7 @@ public class TlsCertificateSigningRequestPerformer {
private TlsCertificateSigningRequestPerformer(Supplier<HttpClientBuilder> httpClientBuilderSupplier, String caHostname, String dn, String token, int port, String signingAlgorithm) {
this.httpClientBuilderSupplier = httpClientBuilderSupplier;
this.caHostname = caHostname;
- this.dn = dn;
+ this.dn = CertificateUtils.reorderDn(dn);
this.token = token;
this.port = port;
this.objectMapper = new ObjectMapper();
@@ -141,10 +143,10 @@ public class TlsCertificateSigningRequestPerformer {
if (!tlsCertificateAuthorityResponse.hasCertificate()) {
throw new IOException(EXPECTED_RESPONSE_TO_CONTAIN_CERTIFICATE);
}
- X509Certificate x509Certificate = TlsHelper.parseCertificate(tlsCertificateAuthorityResponse.getPemEncodedCertificate());
+ X509Certificate x509Certificate = TlsHelper.parseCertificate(new StringReader(tlsCertificateAuthorityResponse.getPemEncodedCertificate()));
x509Certificate.verify(caCertificate.getPublicKey());
if (logger.isInfoEnabled()) {
- logger.info("Got certificate with dn " + x509Certificate.getSubjectDN());
+ logger.info("Got certificate with dn " + x509Certificate.getSubjectX500Principal());
}
return new X509Certificate[]{x509Certificate, caCertificate};
} catch (IOException e) {
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandler.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandler.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandler.java
index fb83498..27d995e 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandler.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandler.java
@@ -82,7 +82,11 @@ public class TlsCertificateAuthorityServiceHandler extends AbstractHandler {
byte[] expectedHmac = TlsHelper.calculateHMac(token, jcaPKCS10CertificationRequest.getPublicKey());
if (MessageDigest.isEqual(expectedHmac, tlsCertificateAuthorityRequest.getHmac())) {
- X509Certificate x509Certificate = CertificateUtils.generateIssuedCertificate(jcaPKCS10CertificationRequest.getSubject().toString(),
+ String dn = jcaPKCS10CertificationRequest.getSubject().toString();
+ if (logger.isInfoEnabled()) {
+ logger.info("Received CSR with DN " + dn);
+ }
+ X509Certificate x509Certificate = CertificateUtils.generateIssuedCertificate(dn,
jcaPKCS10CertificationRequest.getPublicKey(), caCert, keyPair, signingAlgorithm, days);
writeResponse(objectMapper, request, response, new TlsCertificateAuthorityResponse(TlsHelper.calculateHMac(token, caCert.getPublicKey()),
TlsHelper.pemEncodeJcaObject(x509Certificate)), Response.SC_OK);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandalone.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandalone.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandalone.java
index 0136e64..c91e7fa 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandalone.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandalone.java
@@ -18,14 +18,17 @@
package org.apache.nifi.toolkit.tls.standalone;
import org.apache.nifi.security.util.CertificateUtils;
+import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig;
import org.apache.nifi.toolkit.tls.configuration.TlsClientConfig;
import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
+import org.apache.nifi.toolkit.tls.manager.BaseTlsManager;
import org.apache.nifi.toolkit.tls.manager.TlsCertificateAuthorityManager;
import org.apache.nifi.toolkit.tls.manager.TlsClientManager;
import org.apache.nifi.toolkit.tls.manager.writer.NifiPropertiesTlsClientConfigWriter;
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
import org.apache.nifi.toolkit.tls.util.OutputStreamFactory;
import org.apache.nifi.toolkit.tls.util.TlsHelper;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
import org.bouncycastle.util.io.pem.PemWriter;
import org.slf4j.Logger;
@@ -33,11 +36,14 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyStore;
+import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;
@@ -57,17 +63,8 @@ public class TlsToolkitStandalone {
this.outputStreamFactory = outputStreamFactory;
}
- public void createNifiKeystoresAndTrustStores(File baseDir, TlsConfig tlsConfig, NiFiPropertiesWriterFactory niFiPropertiesWriterFactory, List<String> hostnames, List<String> keyStorePasswords,
- List<String> keyPasswords, List<String> trustStorePasswords, int httpsPort) throws GeneralSecurityException, IOException {
- String signingAlgorithm = tlsConfig.getSigningAlgorithm();
- int days = tlsConfig.getDays();
- String keyPairAlgorithm = tlsConfig.getKeyPairAlgorithm();
- int keySize = tlsConfig.getKeySize();
- TlsCertificateAuthorityManager tlsCertificateAuthorityManager = new TlsCertificateAuthorityManager(tlsConfig);
- KeyStore.PrivateKeyEntry privateKeyEntry = tlsCertificateAuthorityManager.getOrGenerateCertificateAuthority();
- X509Certificate certificate = (X509Certificate) privateKeyEntry.getCertificateChain()[0];
- KeyPair caKeyPair = new KeyPair(certificate.getPublicKey(), privateKeyEntry.getPrivateKey());
-
+ public void createNifiKeystoresAndTrustStores(StandaloneConfig standaloneConfig) throws GeneralSecurityException, IOException {
+ File baseDir = standaloneConfig.getBaseDir();
if (!baseDir.exists() && !baseDir.mkdirs()) {
throw new IOException(baseDir + " doesn't exist and unable to create it.");
}
@@ -76,48 +73,107 @@ public class TlsToolkitStandalone {
throw new IOException("Expected directory to output to");
}
- if (logger.isInfoEnabled()) {
- logger.info("Running standalone certificate generation with output directory " + baseDir + " and hostnames " + hostnames);
- }
+ String signingAlgorithm = standaloneConfig.getSigningAlgorithm();
+ int days = standaloneConfig.getDays();
+ String keyPairAlgorithm = standaloneConfig.getKeyPairAlgorithm();
+ int keySize = standaloneConfig.getKeySize();
File nifiCert = new File(baseDir, NIFI_CERT + ".pem");
- if (nifiCert.exists()) {
- throw new IOException(nifiCert.getAbsolutePath() + " exists already.");
- }
-
File nifiKey = new File(baseDir, NIFI_KEY + ".key");
- if (nifiKey.exists()) {
- throw new IOException(nifiKey.getAbsolutePath() + " exists already.");
+
+ X509Certificate certificate;
+ KeyPair caKeyPair;
+
+ List<String> hostnames = standaloneConfig.getHostnames();
+ if (logger.isInfoEnabled()) {
+ logger.info("Running standalone certificate generation with output directory " + baseDir);
}
+ if (nifiCert.exists()) {
+ if (!nifiKey.exists()) {
+ throw new IOException(nifiCert + " exists already, but " + nifiKey + " does not, we need both certificate and key to continue with an existing CA.");
+ }
+ try (FileReader pemEncodedCertificate = new FileReader(nifiCert)) {
+ certificate = TlsHelper.parseCertificate(pemEncodedCertificate);
+ }
+ try (FileReader pemEncodedKeyPair = new FileReader(nifiKey)) {
+ caKeyPair = TlsHelper.parseKeyPair(pemEncodedKeyPair);
+ }
- for (String hostname : hostnames) {
- File hostDirectory = new File(baseDir, hostname);
- if (hostDirectory.exists()) {
- throw new IOException("Output destination for host " + hostname + " (" + hostDirectory.getAbsolutePath() + ") exists already.");
+ certificate.verify(caKeyPair.getPublic());
+ if (!caKeyPair.getPublic().equals(certificate.getPublicKey())) {
+ throw new IOException("Expected " + nifiKey + " to correspond to CA certificate at " + nifiCert);
}
- }
- try (PemWriter pemWriter = new PemWriter(new OutputStreamWriter(outputStreamFactory.create(nifiCert)))) {
- pemWriter.writeObject(new JcaMiscPEMGenerator(certificate));
- }
+ if (logger.isInfoEnabled()) {
+ logger.info("Using existing CA certificate " + nifiCert + " and key " + nifiKey);
+ }
+ } else if (nifiKey.exists()) {
+ throw new IOException(nifiKey + " exists already, but " + nifiCert + " does not, we need both certificate and key to continue with an existing CA.");
+ } else {
+ TlsCertificateAuthorityManager tlsCertificateAuthorityManager = new TlsCertificateAuthorityManager(standaloneConfig);
+ KeyStore.PrivateKeyEntry privateKeyEntry = tlsCertificateAuthorityManager.getOrGenerateCertificateAuthority();
+ certificate = (X509Certificate) privateKeyEntry.getCertificateChain()[0];
+ caKeyPair = new KeyPair(certificate.getPublicKey(), privateKeyEntry.getPrivateKey());
+
+ try (PemWriter pemWriter = new PemWriter(new OutputStreamWriter(outputStreamFactory.create(nifiCert)))) {
+ pemWriter.writeObject(new JcaMiscPEMGenerator(certificate));
+ }
- try (PemWriter pemWriter = new PemWriter(new OutputStreamWriter(outputStreamFactory.create(nifiKey)))) {
- pemWriter.writeObject(new JcaMiscPEMGenerator(caKeyPair));
+ try (PemWriter pemWriter = new PemWriter(new OutputStreamWriter(outputStreamFactory.create(nifiKey)))) {
+ pemWriter.writeObject(new JcaMiscPEMGenerator(caKeyPair));
+ }
+
+ if (logger.isInfoEnabled()) {
+ logger.info("Generated new CA certificate " + nifiCert + " and key " + nifiKey);
+ }
}
+ List<String> keyStorePasswords = standaloneConfig.getKeyStorePasswords();
+ List<String> keyPasswords = standaloneConfig.getKeyPasswords();
+ List<String> trustStorePasswords = standaloneConfig.getTrustStorePasswords();
+ NiFiPropertiesWriterFactory niFiPropertiesWriterFactory = standaloneConfig.getNiFiPropertiesWriterFactory();
+ int httpsPort = standaloneConfig.getHttpsPort();
+ boolean overwrite = standaloneConfig.isOverwrite();
+
+ if (hostnames.isEmpty() && logger.isInfoEnabled()) {
+ logger.info("No " + TlsToolkitStandaloneCommandLine.HOSTNAMES_ARG + " specified, not generating any host certificates or configuration.");
+ }
for (int i = 0; i < hostnames.size(); i++) {
String hostname = hostnames.get(i);
File hostDir = new File(baseDir, hostname);
- if (!hostDir.mkdirs()) {
+ TlsClientConfig tlsClientConfig = new TlsClientConfig(standaloneConfig);
+ File keystore = new File(hostDir, "keystore." + tlsClientConfig.getKeyStoreType().toLowerCase());
+ File truststore = new File(hostDir, "truststore." + tlsClientConfig.getTrustStoreType().toLowerCase());
+
+ if (hostDir.exists()) {
+ if (!hostDir.isDirectory()) {
+ throw new IOException(hostDir + " exists but is not a directory.");
+ } else if (overwrite) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Overwriting any existing ssl configuration in " + hostDir);
+ }
+ keystore.delete();
+ if (keystore.exists()) {
+ throw new IOException("Keystore " + keystore + " already exists and couldn't be deleted.");
+ }
+ truststore.delete();
+ if (truststore.exists()) {
+ throw new IOException("Truststore " + truststore + " already exists and couldn't be deleted.");
+ }
+ } else {
+ throw new IOException(hostDir + " exists and overwrite is not set.");
+ }
+ } else if (!hostDir.mkdirs()) {
throw new IOException("Unable to make directory: " + hostDir.getAbsolutePath());
+ } else if (logger.isInfoEnabled()) {
+ logger.info("Writing new ssl configuration to " + hostDir);
}
- TlsClientConfig tlsClientConfig = new TlsClientConfig(tlsConfig);
- tlsClientConfig.setKeyStore(new File(hostDir, "keystore." + tlsClientConfig.getKeyStoreType().toLowerCase()).getAbsolutePath());
+ tlsClientConfig.setKeyStore(keystore.getAbsolutePath());
tlsClientConfig.setKeyStorePassword(keyStorePasswords.get(i));
tlsClientConfig.setKeyPassword(keyPasswords.get(i));
- tlsClientConfig.setTrustStore(new File(hostDir, "truststore." + tlsClientConfig.getTrustStoreType().toLowerCase()).getAbsolutePath());
+ tlsClientConfig.setTrustStore(truststore.getAbsolutePath());
tlsClientConfig.setTrustStorePassword(trustStorePasswords.get(i));
TlsClientManager tlsClientManager = new TlsClientManager(tlsClientConfig);
KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
@@ -132,8 +188,50 @@ public class TlsToolkitStandalone {
}
}
+ List<String> clientDns = standaloneConfig.getClientDns();
+ if (standaloneConfig.getClientDns().isEmpty() && logger.isInfoEnabled()) {
+ logger.info("No " + TlsToolkitStandaloneCommandLine.CLIENT_CERT_DN_ARG + " specified, not generating any client certificates.");
+ }
+
+ List<String> clientPasswords = standaloneConfig.getClientPasswords();
+ for (int i = 0; i < clientDns.size(); i++) {
+ String reorderedDn = CertificateUtils.reorderDn(clientDns.get(i));
+ String clientDnFile = getClientDnFile(reorderedDn);
+ File clientCertFile = new File(baseDir, clientDnFile + ".p12");
+
+ if (clientCertFile.exists()) {
+ if (overwrite) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Overwriting existing client cert " + clientCertFile);
+ }
+ } else {
+ throw new IOException(clientCertFile + " exists and overwrite is not set.");
+ }
+ } else if (logger.isInfoEnabled()) {
+ logger.info("Generating new client certificate " + clientCertFile);
+ }
+ KeyPair keyPair = TlsHelper.generateKeyPair(keyPairAlgorithm, keySize);
+ X509Certificate clientCert = CertificateUtils.generateIssuedCertificate(reorderedDn, keyPair.getPublic(), certificate, caKeyPair, signingAlgorithm, days);
+ KeyStore keyStore = KeyStore.getInstance(BaseTlsManager.PKCS_12, BouncyCastleProvider.PROVIDER_NAME);
+ keyStore.load(null, null);
+ keyStore.setKeyEntry(NIFI_KEY, keyPair.getPrivate(), null, new Certificate[]{clientCert, certificate});
+ String password = TlsHelper.writeKeyStore(keyStore, outputStreamFactory, clientCertFile, clientPasswords.get(i), standaloneConfig.isClientPasswordsGenerated());
+
+ try (FileWriter fileWriter = new FileWriter(new File(baseDir, clientDnFile + ".password"))) {
+ fileWriter.write(password);
+ }
+
+ if (logger.isInfoEnabled()) {
+ logger.info("Successfully generated client certificate " + clientCertFile);
+ }
+ }
+
if (logger.isInfoEnabled()) {
- logger.info("Successfully generated TLS configuration for all hosts");
+ logger.info("tls-toolkit standalone completed successfully");
}
}
+
+ protected static String getClientDnFile(String clientDn) {
+ return clientDn.replace(',', '_').replace(' ', '_');
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLine.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLine.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLine.java
index 697148f..602fce4 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLine.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLine.java
@@ -21,7 +21,7 @@ import org.apache.commons.cli.CommandLine;
import org.apache.nifi.toolkit.tls.commandLine.BaseCommandLine;
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
-import org.apache.nifi.toolkit.tls.configuration.TlsConfig;
+import org.apache.nifi.toolkit.tls.configuration.StandaloneConfig;
import org.apache.nifi.toolkit.tls.properties.NiFiPropertiesWriterFactory;
import org.apache.nifi.toolkit.tls.util.PasswordUtil;
import org.apache.nifi.toolkit.tls.util.TlsHelper;
@@ -48,9 +48,12 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
public static final String KEY_PASSWORD_ARG = "keyPassword";
public static final String HOSTNAMES_ARG = "hostnames";
public static final String HTTPS_PORT_ARG = "httpsPort";
+ public static final String OVERWRITE_ARG = "isOverwrite";
+ public static final String CLIENT_CERT_DN_ARG = "clientCertDn";
+ public static final String CLIENT_CERT_PASSWORD_ARG = "clientCertPassword";
public static final String DEFAULT_OUTPUT_DIRECTORY = "../" + Paths.get(".").toAbsolutePath().normalize().getFileName().toString();
- public static final int DEFAULT_HTTPS_PORT = 10443;
+ public static final int DEFAULT_HTTPS_PORT = 9091;
public static final String DESCRIPTION = "Creates certificates and config files for nifi cluster.";
@@ -64,6 +67,10 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
private List<String> keyStorePasswords;
private List<String> keyPasswords;
private List<String> trustStorePasswords;
+ private List<String> clientDns;
+ private List<String> clientPasswords;
+ private boolean clientPasswordsGenerated;
+ private boolean overwrite;
public TlsToolkitStandaloneCommandLine() {
this(new PasswordUtil());
@@ -73,12 +80,15 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
super(DESCRIPTION);
this.passwordUtil = passwordUtil;
addOptionWithArg("o", OUTPUT_DIRECTORY_ARG, "The directory to output keystores, truststore, config files.", DEFAULT_OUTPUT_DIRECTORY);
- addOptionWithArg("n", HOSTNAMES_ARG, "Comma separated list of hostnames.", TlsConfig.DEFAULT_HOSTNAME);
+ addOptionWithArg("n", HOSTNAMES_ARG, "Comma separated list of hostnames.");
addOptionWithArg("p", HTTPS_PORT_ARG, "Https port to use.", DEFAULT_HTTPS_PORT);
addOptionWithArg("f", NIFI_PROPERTIES_FILE_ARG, "Base nifi.properties file to update. (Embedded file identical to the one in a default NiFi install will be used if not specified.)");
addOptionWithArg("S", KEY_STORE_PASSWORD_ARG, "Keystore password to use. Must either be one value or one for each host. (autogenerate if not specified)");
addOptionWithArg("K", KEY_PASSWORD_ARG, "Key password to use. Must either be one value or one for each host. (autogenerate if not specified)");
addOptionWithArg("P", TRUST_STORE_PASSWORD_ARG, "Keystore password to use. Must either be one value or one for each host. (autogenerate if not specified)");
+ addOptionWithArg("C", CLIENT_CERT_DN_ARG, "Generate client certificate suitable for use in browser with specified DN. (Can be specified multiple times.)");
+ addOptionWithArg("B", CLIENT_CERT_PASSWORD_ARG, "Password for client certificate. Must either be one value or one for each client DN. (autogenerate if not specified)");
+ addOptionNoArg("O", OVERWRITE_ARG, "Overwrite existing host output.");
}
public static void main(String[] args) {
@@ -90,9 +100,7 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
System.exit(e.getExitCode());
}
try {
- new TlsToolkitStandalone().createNifiKeystoresAndTrustStores(tlsToolkitStandaloneCommandLine.getBaseDir(), tlsToolkitStandaloneCommandLine.createConfig(),
- tlsToolkitStandaloneCommandLine.getNiFiPropertiesWriterFactory(), tlsToolkitStandaloneCommandLine.getHostnames(), tlsToolkitStandaloneCommandLine.getKeyStorePasswords(),
- tlsToolkitStandaloneCommandLine.getKeyPasswords(), tlsToolkitStandaloneCommandLine.getTrustStorePasswords(), tlsToolkitStandaloneCommandLine.getHttpsPort());
+ new TlsToolkitStandalone().createNifiKeystoresAndTrustStores(tlsToolkitStandaloneCommandLine.createConfig());
} catch (Exception e) {
tlsToolkitStandaloneCommandLine.printUsage("Error creating generating tls configuration. (" + e.getMessage() + ")");
System.exit(ExitCode.ERROR_GENERATING_CONFIG.ordinal());
@@ -105,13 +113,29 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
CommandLine commandLine = super.doParse(args);
String outputDirectory = commandLine.getOptionValue(OUTPUT_DIRECTORY_ARG, DEFAULT_OUTPUT_DIRECTORY);
baseDir = new File(outputDirectory);
- hostnames = Arrays.stream(commandLine.getOptionValue(HOSTNAMES_ARG, TlsConfig.DEFAULT_HOSTNAME).split(",")).map(String::trim).collect(Collectors.toList());
+
+ if (commandLine.hasOption(HOSTNAMES_ARG)) {
+ hostnames = Collections.unmodifiableList(Arrays.stream(commandLine.getOptionValue(HOSTNAMES_ARG).split(",")).map(String::trim).collect(Collectors.toList()));
+ } else {
+ hostnames = Collections.emptyList();
+ }
+
+ String[] clientDnValues = commandLine.getOptionValues(CLIENT_CERT_DN_ARG);
+ if (clientDnValues != null) {
+ clientDns = Collections.unmodifiableList(Arrays.stream(clientDnValues).collect(Collectors.toList()));
+ } else {
+ clientDns = Collections.emptyList();
+ }
+
httpsPort = getIntValue(commandLine, HTTPS_PORT_ARG, DEFAULT_HTTPS_PORT);
int numHosts = hostnames.size();
- keyStorePasswords = Collections.unmodifiableList(getPasswords(KEY_STORE_PASSWORD_ARG, commandLine, numHosts));
+ keyStorePasswords = Collections.unmodifiableList(getPasswords(KEY_STORE_PASSWORD_ARG, commandLine, numHosts, HOSTNAMES_ARG));
keyPasswords = Collections.unmodifiableList(getKeyPasswords(commandLine, keyStorePasswords));
- trustStorePasswords = Collections.unmodifiableList(getPasswords(TRUST_STORE_PASSWORD_ARG, commandLine, numHosts));
+ trustStorePasswords = Collections.unmodifiableList(getPasswords(TRUST_STORE_PASSWORD_ARG, commandLine, numHosts, HOSTNAMES_ARG));
+ clientPasswords = Collections.unmodifiableList(getPasswords(CLIENT_CERT_PASSWORD_ARG, commandLine, clientDns.size(), CLIENT_CERT_DN_ARG));
+ clientPasswordsGenerated = commandLine.getOptionValues(CLIENT_CERT_PASSWORD_ARG) == null;
+ overwrite = commandLine.hasOption(OVERWRITE_ARG);
String nifiPropertiesFile = commandLine.getOptionValue(NIFI_PROPERTIES_FILE_ARG, "");
try {
@@ -128,64 +152,50 @@ public class TlsToolkitStandaloneCommandLine extends BaseCommandLine {
return commandLine;
}
- private List<String> getPasswords(String arg, CommandLine commandLine, int numHosts) throws CommandLineParseException {
+ private List<String> getPasswords(String arg, CommandLine commandLine, int num, String numArg) throws CommandLineParseException {
String[] optionValues = commandLine.getOptionValues(arg);
if (optionValues == null) {
- return IntStream.range(0, numHosts).mapToObj(operand -> passwordUtil.generatePassword()).collect(Collectors.toList());
+ return IntStream.range(0, num).mapToObj(operand -> passwordUtil.generatePassword()).collect(Collectors.toList());
}
if (optionValues.length == 1) {
- return IntStream.range(0, numHosts).mapToObj(value -> optionValues[0]).collect(Collectors.toList());
- } else if (optionValues.length == numHosts) {
+ return IntStream.range(0, num).mapToObj(value -> optionValues[0]).collect(Collectors.toList());
+ } else if (optionValues.length == num) {
return Arrays.stream(optionValues).collect(Collectors.toList());
}
- return printUsageAndThrow("Expected either 1 value or " + numHosts + " (the number of hostnames) values for " + arg, ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS);
+ return printUsageAndThrow("Expected either 1 value or " + num + " (the number of " + numArg + ") values for " + arg, ExitCode.ERROR_INCORRECT_NUMBER_OF_PASSWORDS);
}
private List<String> getKeyPasswords(CommandLine commandLine, List<String> keyStorePasswords) throws CommandLineParseException {
if (differentPasswordForKeyAndKeystore() || commandLine.hasOption(KEY_PASSWORD_ARG)) {
- return getPasswords(KEY_PASSWORD_ARG, commandLine, keyStorePasswords.size());
+ return getPasswords(KEY_PASSWORD_ARG, commandLine, keyStorePasswords.size(), HOSTNAMES_ARG);
}
return new ArrayList<>(keyStorePasswords);
}
- public File getBaseDir() {
- return baseDir;
- }
-
- public List<String> getHostnames() {
- return hostnames;
- }
-
- public int getHttpsPort() {
- return httpsPort;
- }
-
- public NiFiPropertiesWriterFactory getNiFiPropertiesWriterFactory() {
- return niFiPropertiesWriterFactory;
- }
-
- public List<String> getKeyStorePasswords() {
- return keyStorePasswords;
- }
-
- public List<String> getKeyPasswords() {
- return keyPasswords;
- }
-
- public List<String> getTrustStorePasswords() {
- return trustStorePasswords;
- }
-
- public TlsConfig createConfig() throws IOException {
- TlsConfig tlsConfig = new TlsConfig();
- tlsConfig.setCaHostname(getCertificateAuthorityHostname());
- tlsConfig.setKeyStore("nifi-ca-" + KEYSTORE + getKeyStoreType().toLowerCase());
- tlsConfig.setKeyStoreType(getKeyStoreType());
- tlsConfig.setKeySize(getKeySize());
- tlsConfig.setKeyPairAlgorithm(getKeyAlgorithm());
- tlsConfig.setSigningAlgorithm(getSigningAlgorithm());
- tlsConfig.setDays(getDays());
- tlsConfig.initDefaults();
- return tlsConfig;
+ public StandaloneConfig createConfig() {
+ StandaloneConfig standaloneConfig = new StandaloneConfig();
+
+ standaloneConfig.setBaseDir(baseDir);
+ standaloneConfig.setNiFiPropertiesWriterFactory(niFiPropertiesWriterFactory);
+ standaloneConfig.setHostnames(hostnames);
+ standaloneConfig.setKeyStorePasswords(keyStorePasswords);
+ standaloneConfig.setKeyPasswords(keyPasswords);
+ standaloneConfig.setTrustStorePasswords(trustStorePasswords);
+ standaloneConfig.setHttpsPort(httpsPort);
+ standaloneConfig.setOverwrite(overwrite);
+ standaloneConfig.setClientDns(clientDns);
+ standaloneConfig.setClientPasswords(clientPasswords);
+ standaloneConfig.setClientPasswordsGenerated(clientPasswordsGenerated);
+
+ standaloneConfig.setCaHostname(getCertificateAuthorityHostname());
+ standaloneConfig.setKeyStore("nifi-ca-" + KEYSTORE + getKeyStoreType().toLowerCase());
+ standaloneConfig.setKeyStoreType(getKeyStoreType());
+ standaloneConfig.setKeySize(getKeySize());
+ standaloneConfig.setKeyPairAlgorithm(getKeyAlgorithm());
+ standaloneConfig.setSigningAlgorithm(getSigningAlgorithm());
+ standaloneConfig.setDays(getDays());
+ standaloneConfig.initDefaults();
+
+ return standaloneConfig;
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/util/TlsHelper.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/util/TlsHelper.java b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/util/TlsHelper.java
index 0622b9e..05a5dcb 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/util/TlsHelper.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/main/java/org/apache/nifi/toolkit/tls/util/TlsHelper.java
@@ -17,29 +17,38 @@
package org.apache.nifi.toolkit.tls.util;
+import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
import org.bouncycastle.util.io.pem.PemWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
-import javax.security.auth.x500.X500Principal;
+import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
@@ -47,10 +56,78 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class TlsHelper {
+ private static final Logger logger = LoggerFactory.getLogger(TlsHelper.class);
+ private static final int DEFAULT_MAX_ALLOWED_KEY_LENGTH = 128;
+ public static final String JCE_URL = "http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html";
+ public static final String ILLEGAL_KEY_SIZE = "illegal key size";
+ private static boolean isUnlimitedStrengthCryptographyEnabled;
+
+ // Evaluate an unlimited strength algorithm to determine if we support the capability we have on the system
+ static {
+ try {
+ isUnlimitedStrengthCryptographyEnabled = (Cipher.getMaxAllowedKeyLength("AES") > DEFAULT_MAX_ALLOWED_KEY_LENGTH);
+ } catch (NoSuchAlgorithmException e) {
+ // if there are issues with this, we default back to the value established
+ isUnlimitedStrengthCryptographyEnabled = false;
+ }
+ }
+
+ private static void logTruncationWarning(File file) {
+ String fileToString = file.toString();
+ String fileName = file.getName();
+ logger.warn("**********************************************************************************");
+ logger.warn(" WARNING!!!!");
+ logger.warn("**********************************************************************************");
+ logger.warn("Unlimited JCE Policy is not installed which means we cannot utilize a");
+ logger.warn("PKCS12 password longer than 7 characters.");
+ logger.warn("Autogenerated password has been reduced to 7 characters.");
+ logger.warn("");
+ logger.warn("Please strongly consider installing Unlimited JCE Policy at");
+ logger.warn(JCE_URL);
+ logger.warn("");
+ logger.warn("Another alternative is to add a stronger password with the openssl tool to the");
+ logger.warn("resulting client certificate: " + fileToString);
+ logger.warn("");
+ logger.warn("openssl pkcs12 -in '" + fileToString + "' -out '/tmp/" + fileName + "'");
+ logger.warn("openssl pkcs12 -export -in '/tmp/" + fileName + "' -out '" + fileToString + "'");
+ logger.warn("rm -f '/tmp/" + fileName + "'");
+ logger.warn("");
+ logger.warn("**********************************************************************************");
+
+ }
+
private TlsHelper() {
}
+ public static boolean isUnlimitedStrengthCryptographyEnabled() {
+ return isUnlimitedStrengthCryptographyEnabled;
+ }
+
+ public static String writeKeyStore(KeyStore keyStore, OutputStreamFactory outputStreamFactory, File file, String password, boolean generatedPassword) throws IOException, GeneralSecurityException {
+ try (OutputStream fileOutputStream = outputStreamFactory.create(file)) {
+ keyStore.store(fileOutputStream, password.toCharArray());
+ } catch (IOException e) {
+ if (e.getMessage().toLowerCase().contains(ILLEGAL_KEY_SIZE) && !isUnlimitedStrengthCryptographyEnabled()) {
+ if (generatedPassword) {
+ file.delete();
+ String truncatedPassword = password.substring(0, 7);
+ try (OutputStream fileOutputStream = outputStreamFactory.create(file)) {
+ keyStore.store(fileOutputStream, truncatedPassword.toCharArray());
+ }
+ logTruncationWarning(file);
+ return truncatedPassword;
+ } else {
+ throw new GeneralSecurityException("Specified password for " + file + " too long to work without unlimited JCE policy installed."
+ + System.lineSeparator() + "Please see " + JCE_URL);
+ }
+ } else {
+ throw e;
+ }
+ }
+ return password;
+ }
+
public static void addBouncyCastleProvider() {
Security.addProvider(new BouncyCastleProvider());
}
@@ -90,13 +167,21 @@ public class TlsHelper {
}
}
- public static X509Certificate parseCertificate(String pemEncodedCertificate) throws IOException, CertificateException {
- try (PEMParser pemParser = new PEMParser(new StringReader(pemEncodedCertificate))) {
+ public static X509Certificate parseCertificate(Reader pemEncodedCertificate) throws IOException, CertificateException {
+ return new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate(parsePem(X509CertificateHolder.class, pemEncodedCertificate));
+ }
+
+ public static KeyPair parseKeyPair(Reader pemEncodedKeyPair) throws IOException {
+ return new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getKeyPair(parsePem(PEMKeyPair.class, pemEncodedKeyPair));
+ }
+
+ public static <T> T parsePem(Class<T> clazz, Reader pemReader) throws IOException {
+ try (PEMParser pemParser = new PEMParser(pemReader)) {
Object object = pemParser.readObject();
- if (!X509CertificateHolder.class.isInstance(object)) {
- throw new IOException("Expected " + X509CertificateHolder.class);
+ if (!clazz.isInstance(object)) {
+ throw new IOException("Expected " + clazz);
}
- return new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate((X509CertificateHolder) object);
+ return (T) object;
}
}
@@ -105,7 +190,7 @@ public class TlsHelper {
}
public static JcaPKCS10CertificationRequest generateCertificationRequest(String requestedDn, KeyPair keyPair, String signingAlgorithm) throws OperatorCreationException {
- JcaPKCS10CertificationRequestBuilder jcaPKCS10CertificationRequestBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Principal(requestedDn), keyPair.getPublic());
+ JcaPKCS10CertificationRequestBuilder jcaPKCS10CertificationRequestBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(requestedDn), keyPair.getPublic());
JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signingAlgorithm);
return new JcaPKCS10CertificationRequest(jcaPKCS10CertificationRequestBuilder.build(jcaContentSignerBuilder.build(keyPair.getPrivate())));
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/TlsCertificateAuthorityTest.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/TlsCertificateAuthorityTest.java b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/TlsCertificateAuthorityTest.java
index 7881500..ad5fa12 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/TlsCertificateAuthorityTest.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/TlsCertificateAuthorityTest.java
@@ -107,7 +107,7 @@ public class TlsCertificateAuthorityTest {
clientConfig = new TlsClientConfig();
clientConfig.setCaHostname("localhost");
- clientConfig.setDn("CN=otherHostname,OU=NIFI");
+ clientConfig.setDn("OU=NIFI,CN=otherHostname");
clientConfig.setKeyStore(clientKeyStore);
clientConfig.setTrustStore(clientTrustStore);
clientConfig.setToken(myTestTokenUseSomethingStronger);
@@ -227,7 +227,7 @@ public class TlsCertificateAuthorityTest {
assertEquals(caCertificate, clientTrustStore.getCertificate(TlsToolkitStandalone.NIFI_CERT));
}
- private void assertPrivateAndPublicKeyMatch(PrivateKey privateKey, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ public static void assertPrivateAndPublicKeyMatch(PrivateKey privateKey, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = Signature.getInstance(TlsConfig.DEFAULT_SIGNING_ALGORITHM);
signature.initSign(privateKey);
byte[] bytes = "test string".getBytes(StandardCharsets.UTF_8);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandlerTest.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandlerTest.java b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandlerTest.java
index bf355fa..09bc8f0 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandlerTest.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/service/server/TlsCertificateAuthorityServiceHandlerTest.java
@@ -145,7 +145,7 @@ public class TlsCertificateAuthorityServiceHandlerTest {
tlsCertificateAuthorityServiceHandler.handle(null, baseRequest, httpServletRequest, httpServletResponse);
assertEquals(Response.SC_OK, statusCode);
assertArrayEquals(testCaHmac, getResponse().getHmac());
- X509Certificate certificate = TlsHelper.parseCertificate(getResponse().getPemEncodedCertificate());
+ X509Certificate certificate = TlsHelper.parseCertificate(new StringReader(getResponse().getPemEncodedCertificate()));
assertEquals(certificateKeyPair.getPublic(), certificate.getPublicKey());
assertEquals(new X500Name(requestedDn), new X500Name(certificate.getSubjectDN().toString()));
certificate.verify(caCert.getPublicKey());
http://git-wip-us.apache.org/repos/asf/nifi/blob/fa5da543/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLineTest.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLineTest.java b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLineTest.java
index fd45eb4..82c67d9 100644
--- a/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLineTest.java
+++ b/nifi-toolkit/nifi-toolkit-tls/src/test/java/org/apache/nifi/toolkit/tls/standalone/TlsToolkitStandaloneCommandLineTest.java
@@ -19,6 +19,8 @@ package org.apache.nifi.toolkit.tls.standalone;
import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException;
import org.apache.nifi.toolkit.tls.commandLine.ExitCode;
+import org.apache.nifi.toolkit.tls.configuration.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.Assert;
@@ -31,6 +33,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
+import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Random;
@@ -75,7 +78,7 @@ public class TlsToolkitStandaloneCommandLineTest {
}
@Test
- public void testKeyAlgorithm() throws CommandLineParseException, IOException {
+ public void testKeyAlgorithm() throws CommandLineParseException {
String testKeyAlgorithm = "testKeyAlgorithm";
tlsToolkitStandaloneCommandLine.parse("-a", testKeyAlgorithm);
assertEquals(testKeyAlgorithm, tlsToolkitStandaloneCommandLine.createConfig().getKeyPairAlgorithm());
@@ -115,7 +118,7 @@ public class TlsToolkitStandaloneCommandLineTest {
}
@Test
- public void testDays() throws CommandLineParseException, IOException {
+ public void testDays() throws CommandLineParseException {
int testDays = 29;
tlsToolkitStandaloneCommandLine.parse("-d", Integer.toString(testDays));
assertEquals(testDays, tlsToolkitStandaloneCommandLine.createConfig().getDays());
@@ -132,7 +135,7 @@ public class TlsToolkitStandaloneCommandLineTest {
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.getBaseDir().getPath());
+ assertEquals(testPath, tlsToolkitStandaloneCommandLine.createConfig().getBaseDir().getPath());
}
@Test
@@ -142,7 +145,7 @@ public class TlsToolkitStandaloneCommandLineTest {
tlsToolkitStandaloneCommandLine.parse("-n", nifi1 + " , " + nifi2);
- List<String> hostnames = tlsToolkitStandaloneCommandLine.getHostnames();
+ List<String> hostnames = tlsToolkitStandaloneCommandLine.createConfig().getHostnames();
assertEquals(2, hostnames.size());
assertEquals(nifi1, hostnames.get(0));
assertEquals(nifi2, hostnames.get(1));
@@ -152,7 +155,7 @@ public class TlsToolkitStandaloneCommandLineTest {
public void testHttpsPort() throws CommandLineParseException {
int testPort = 8998;
tlsToolkitStandaloneCommandLine.parse("-p", Integer.toString(testPort));
- assertEquals(testPort, tlsToolkitStandaloneCommandLine.getHttpsPort());
+ assertEquals(testPort, tlsToolkitStandaloneCommandLine.createConfig().getHttpsPort());
}
@Test
@@ -179,10 +182,10 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testNotSameKeyAndKeystorePassword() throws CommandLineParseException {
- tlsToolkitStandaloneCommandLine.parse("-g");
- List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.getKeyStorePasswords();
- List<String> keyPasswords = tlsToolkitStandaloneCommandLine.getKeyPasswords();
- assertEquals(1, tlsToolkitStandaloneCommandLine.getHostnames().size());
+ tlsToolkitStandaloneCommandLine.parse("-g", "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
+ List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
+ assertEquals(1, tlsToolkitStandaloneCommandLine.createConfig().getHostnames().size());
assertEquals(1, keyStorePasswords.size());
assertEquals(1, keyPasswords.size());
assertNotEquals(keyStorePasswords.get(0), keyPasswords.get(0));
@@ -190,10 +193,10 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testSameKeyAndKeystorePassword() throws CommandLineParseException {
- tlsToolkitStandaloneCommandLine.parse();
- List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.getKeyStorePasswords();
- List<String> keyPasswords = tlsToolkitStandaloneCommandLine.getKeyPasswords();
- assertEquals(1, tlsToolkitStandaloneCommandLine.getHostnames().size());
+ tlsToolkitStandaloneCommandLine.parse("-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
+ List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
+ assertEquals(1, tlsToolkitStandaloneCommandLine.createConfig().getHostnames().size());
assertEquals(1, keyStorePasswords.size());
assertEquals(1, keyPasswords.size());
assertEquals(keyStorePasswords.get(0), keyPasswords.get(0));
@@ -202,19 +205,19 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testSameKeyAndKeystorePasswordWithKeystorePasswordSpecified() throws CommandLineParseException {
String testPassword = "testPassword";
- tlsToolkitStandaloneCommandLine.parse("-S", testPassword);
- List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.getKeyStorePasswords();
+ tlsToolkitStandaloneCommandLine.parse("-S", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
assertEquals(1, keyStorePasswords.size());
assertEquals(testPassword, keyStorePasswords.get(0));
- assertEquals(keyStorePasswords, tlsToolkitStandaloneCommandLine.getKeyPasswords());
+ assertEquals(keyStorePasswords, tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords());
}
@Test
public void testSameKeyAndKeystorePasswordWithKeyPasswordSpecified() throws CommandLineParseException {
String testPassword = "testPassword";
- tlsToolkitStandaloneCommandLine.parse("-K", testPassword);
- List<String> keyPasswords = tlsToolkitStandaloneCommandLine.getKeyPasswords();
- assertNotEquals(tlsToolkitStandaloneCommandLine.getKeyStorePasswords(), keyPasswords);
+ tlsToolkitStandaloneCommandLine.parse("-K", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
+ assertNotEquals(tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords(), keyPasswords);
assertEquals(1, keyPasswords.size());
assertEquals(testPassword, keyPasswords.get(0));
}
@@ -222,8 +225,8 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testKeyStorePasswordArg() throws CommandLineParseException {
String testPassword = "testPassword";
- tlsToolkitStandaloneCommandLine.parse("-S", testPassword);
- List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.getKeyStorePasswords();
+ tlsToolkitStandaloneCommandLine.parse("-S", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
assertEquals(1, keyStorePasswords.size());
assertEquals(testPassword, keyStorePasswords.get(0));
}
@@ -233,7 +236,7 @@ public class TlsToolkitStandaloneCommandLineTest {
String testPassword1 = "testPassword1";
String testPassword2 = "testPassword2";
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-S", testPassword1, "-S", testPassword2);
- List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.getKeyStorePasswords();
+ List<String> keyStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyStorePasswords();
assertEquals(2, keyStorePasswords.size());
assertEquals(testPassword1, keyStorePasswords.get(0));
assertEquals(testPassword2, keyStorePasswords.get(1));
@@ -254,8 +257,8 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testKeyPasswordArg() throws CommandLineParseException {
String testPassword = "testPassword";
- tlsToolkitStandaloneCommandLine.parse("-K", testPassword);
- List<String> keyPasswords = tlsToolkitStandaloneCommandLine.getKeyPasswords();
+ tlsToolkitStandaloneCommandLine.parse("-K", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
assertEquals(1, keyPasswords.size());
assertEquals(testPassword, keyPasswords.get(0));
}
@@ -265,7 +268,7 @@ public class TlsToolkitStandaloneCommandLineTest {
String testPassword1 = "testPassword1";
String testPassword2 = "testPassword2";
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-K", testPassword1, "-K", testPassword2);
- List<String> keyPasswords = tlsToolkitStandaloneCommandLine.getKeyPasswords();
+ List<String> keyPasswords = tlsToolkitStandaloneCommandLine.createConfig().getKeyPasswords();
assertEquals(2, keyPasswords.size());
assertEquals(testPassword1, keyPasswords.get(0));
assertEquals(testPassword2, keyPasswords.get(1));
@@ -286,8 +289,8 @@ public class TlsToolkitStandaloneCommandLineTest {
@Test
public void testTruststorePasswordArg() throws CommandLineParseException {
String testPassword = "testPassword";
- tlsToolkitStandaloneCommandLine.parse("-P", testPassword);
- List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.getTrustStorePasswords();
+ tlsToolkitStandaloneCommandLine.parse("-P", testPassword, "-n", TlsConfig.DEFAULT_HOSTNAME);
+ List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getTrustStorePasswords();
assertEquals(1, trustStorePasswords.size());
assertEquals(testPassword, trustStorePasswords.get(0));
}
@@ -297,7 +300,7 @@ public class TlsToolkitStandaloneCommandLineTest {
String testPassword1 = "testPassword1";
String testPassword2 = "testPassword2";
tlsToolkitStandaloneCommandLine.parse("-n", "nifi1,nifi2", "-P", testPassword1, "-P", testPassword2);
- List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.getTrustStorePasswords();
+ List<String> trustStorePasswords = tlsToolkitStandaloneCommandLine.createConfig().getTrustStorePasswords();
assertEquals(2, trustStorePasswords.size());
assertEquals(testPassword1, trustStorePasswords.get(0));
assertEquals(testPassword2, trustStorePasswords.get(1));
@@ -315,8 +318,54 @@ public class TlsToolkitStandaloneCommandLineTest {
}
}
+ @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));
+ }
+
private Properties getProperties() throws IOException {
- NiFiPropertiesWriter niFiPropertiesWriter = tlsToolkitStandaloneCommandLine.getNiFiPropertiesWriterFactory().create();
+ NiFiPropertiesWriter niFiPropertiesWriter = tlsToolkitStandaloneCommandLine.createConfig().getNiFiPropertiesWriterFactory().create();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
niFiPropertiesWriter.writeNiFiProperties(byteArrayOutputStream);
Properties properties = new Properties();