NIFI-9228 Refactored tests using TemporaryKeyStoreBuilder

- Added TemporaryKeyStoreBuilder with File.deleteOnExit() for KeyStore and TrustStore files
- Removed JKS files from nifi-security-utils tests
- Refactored usage of KeyStoreUtils.createKeyStoreAndGetX509Certificate() to TemporaryKeyStoreBuilder
- Removed unnecesary hadoop-minikdc test dependency in security-utils
- Replaced Mini KDC Hex utility with Bouncy Castle Hex utility in unit tests

Signed-off-by: Matthew Burgess <mattyb149@apache.org>

This closes #5406
This commit is contained in:
exceptionfactory 2021-09-21 12:29:49 -05:00 committed by Matthew Burgess
parent e78674ec59
commit b4e0416b5e
No known key found for this signature in database
GPG Key ID: 05D3DEB8126DAD24
43 changed files with 769 additions and 937 deletions

View File

@ -28,8 +28,8 @@ import org.apache.nifi.bootstrap.notification.NotificationType;
import org.apache.nifi.bootstrap.notification.http.HttpNotificationService;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.junit.After;
import org.junit.Before;
@ -38,8 +38,6 @@ import org.junit.Test;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
@ -133,34 +131,29 @@ public class HttpNotificationServiceTest {
}
@Test
public void testStartNotificationHttps() throws GeneralSecurityException, NotificationFailedException, InterruptedException, IOException {
final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
public void testStartNotificationHttps() throws GeneralSecurityException, NotificationFailedException, InterruptedException {
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
try {
final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration);
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
mockWebServer.useHttps(sslSocketFactory, false);
final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration);
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
mockWebServer.useHttps(sslSocketFactory, false);
enqueueResponseCode(200);
enqueueResponseCode(200);
final Map<PropertyDescriptor, PropertyValue> properties = getProperties();
final Map<PropertyDescriptor, PropertyValue> properties = getProperties();
properties.put(PROP_KEYSTORE, createPropertyValue(tlsConfiguration.getKeystorePath()));
properties.put(PROP_KEYSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getKeystorePassword()));
properties.put(PROP_KEY_PASSWORD, createPropertyValue(tlsConfiguration.getKeyPassword()));
properties.put(PROP_KEYSTORE_TYPE, createPropertyValue(tlsConfiguration.getKeystoreType().getType()));
properties.put(PROP_TRUSTSTORE, createPropertyValue(tlsConfiguration.getTruststorePath()));
properties.put(PROP_TRUSTSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getTruststorePassword()));
properties.put(PROP_TRUSTSTORE_TYPE, createPropertyValue(tlsConfiguration.getTruststoreType().getType()));
properties.put(PROP_KEYSTORE, createPropertyValue(tlsConfiguration.getKeystorePath()));
properties.put(PROP_KEYSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getKeystorePassword()));
properties.put(PROP_KEY_PASSWORD, createPropertyValue(tlsConfiguration.getKeyPassword()));
properties.put(PROP_KEYSTORE_TYPE, createPropertyValue(tlsConfiguration.getKeystoreType().getType()));
properties.put(PROP_TRUSTSTORE, createPropertyValue(tlsConfiguration.getTruststorePath()));
properties.put(PROP_TRUSTSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getTruststorePassword()));
properties.put(PROP_TRUSTSTORE_TYPE, createPropertyValue(tlsConfiguration.getTruststoreType().getType()));
final HttpNotificationService service = getHttpNotificationService(properties);
service.notify(getNotificationContext(), NotificationType.NIFI_STARTED, SUBJECT, MESSAGE);
final HttpNotificationService service = getHttpNotificationService(properties);
service.notify(getNotificationContext(), NotificationType.NIFI_STARTED, SUBJECT, MESSAGE);
assertRequestMatches(NotificationType.NIFI_STARTED);
} finally {
Files.deleteIfExists(Paths.get(tlsConfiguration.getKeystorePath()));
Files.deleteIfExists(Paths.get(tlsConfiguration.getTruststorePath()));
}
assertRequestMatches(NotificationType.NIFI_STARTED);
}
private void assertRequestMatches(final NotificationType notificationType) throws InterruptedException {

View File

@ -19,7 +19,7 @@ package org.apache.nifi.bootstrap.util;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.nifi.properties.NiFiPropertiesLoader;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.StandardTlsConfiguration;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.util.StringUtils;
@ -52,7 +52,7 @@ import java.util.Set;
public class TestSecureNiFiConfigUtil {
public static final String TEST_RESOURCE_DIR = "src/test/resources/";
private Logger logger = LoggerFactory.getLogger("org.apache.nifi.bootstrap.util.TestSecureNiFiConfigUtil");
private final Logger logger = LoggerFactory.getLogger("org.apache.nifi.bootstrap.util.TestSecureNiFiConfigUtil");
private static final String PROPERTIES_PREFIX = "nifi-properties";
private static final boolean EXPECT_STORES_TO_EXIST = true;
@ -60,8 +60,8 @@ public class TestSecureNiFiConfigUtil {
private Path nifiPropertiesFile;
private Path keystorePath;
private Path truststorePath;
private Path existingKeystorePath = getTestFilePath("existing-keystore.p12");
private Path existingTruststorePath = getTestFilePath("existing-truststore.p12");
private final Path existingKeystorePath = getTestFilePath("existing-keystore.p12");
private final Path existingTruststorePath = getTestFilePath("existing-truststore.p12");
private NiFiProperties configureSecureNiFiProperties(Path testPropertiesFile) throws IOException {
Files.copy(testPropertiesFile, nifiPropertiesFile, StandardCopyOption.REPLACE_EXISTING);
@ -87,9 +87,9 @@ public class TestSecureNiFiConfigUtil {
}
@Before
public void init() throws IOException, GeneralSecurityException {
public void init() throws IOException {
nifiPropertiesFile = Files.createTempFile(PROPERTIES_PREFIX, ".properties");
TlsConfiguration tlsConfig = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore(new StandardTlsConfiguration());
TlsConfiguration tlsConfig = new TemporaryKeyStoreBuilder().build();
Files.move(Paths.get(tlsConfig.getKeystorePath()), existingKeystorePath, StandardCopyOption.REPLACE_EXISTING);
Files.move(Paths.get(tlsConfig.getTruststorePath()), existingTruststorePath, StandardCopyOption.REPLACE_EXISTING);
}
@ -159,12 +159,12 @@ public class TestSecureNiFiConfigUtil {
}
}
private void runTestWithNoExpectedUpdates(String testPropertiesFile, boolean expectBothStoresToExist) throws IOException, GeneralSecurityException {
private void runTestWithNoExpectedUpdates(String testPropertiesFile, boolean expectBothStoresToExist) throws IOException {
this.runTestWithNoExpectedUpdates(testPropertiesFile, expectBothStoresToExist, expectBothStoresToExist);
}
private void runTestWithNoExpectedUpdates(String testPropertiesFile, boolean expectKeystoreToExist, boolean expectTruststoreToExist)
throws IOException, GeneralSecurityException {
throws IOException {
Path testPropertiesFilePath = getPathFromClasspath(testPropertiesFile);
NiFiProperties niFiProperties = this.configureSecureNiFiProperties(testPropertiesFilePath);
keystorePath = Paths.get(niFiProperties.getProperty(NiFiProperties.SECURITY_KEYSTORE));
@ -179,52 +179,52 @@ public class TestSecureNiFiConfigUtil {
@Test
public void testSuccessfulConfiguration() throws IOException, GeneralSecurityException {
runTestWithExpectedSuccess("nifi.properties.success", Collections.EMPTY_LIST);
runTestWithExpectedSuccess("nifi.properties.success", Collections.emptyList());
}
@Test
public void testSuccessfulDNSSANs() throws IOException, GeneralSecurityException {
runTestWithExpectedSuccess("nifi.properties.dns-sans",
Arrays.asList(new String[] {"test-host", "remote-host", "proxy-host", "cluster-host"}));
Arrays.asList("test-host", "remote-host", "proxy-host", "cluster-host"));
}
@Test
public void testNoHttps() throws IOException, GeneralSecurityException {
public void testNoHttps() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.no-https", !EXPECT_STORES_TO_EXIST);
}
@Test
public void testNoKeystores() throws IOException, GeneralSecurityException {
public void testNoKeystores() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.no-keystores", !EXPECT_STORES_TO_EXIST);
}
@Test
public void testTruststorePasswordSet() throws IOException, GeneralSecurityException {
public void testTruststorePasswordSet() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.truststore-password", !EXPECT_STORES_TO_EXIST);
}
@Test
public void testKeystorePasswordSet() throws IOException, GeneralSecurityException {
public void testKeystorePasswordSet() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.keystore-password", !EXPECT_STORES_TO_EXIST);
}
@Test
public void test_keystoreAndTruststoreAlreadyExist() throws IOException, GeneralSecurityException {
public void test_keystoreAndTruststoreAlreadyExist() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.stores-exist", EXPECT_STORES_TO_EXIST);
}
@Test
public void testNoKeystoresTypes() throws IOException, GeneralSecurityException {
runTestWithExpectedSuccess("nifi.properties.no-keystore-types", Collections.EMPTY_LIST);
runTestWithExpectedSuccess("nifi.properties.no-keystore-types", Collections.emptyList());
}
@Test
public void testFailure_onlyTruststoreExists() throws IOException, GeneralSecurityException {
public void testFailure_onlyTruststoreExists() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.only-truststore", !EXPECT_STORES_TO_EXIST, EXPECT_STORES_TO_EXIST);
}
@Test
public void testFailure_onlyKeystoreExists() throws IOException, GeneralSecurityException {
public void testFailure_onlyKeystoreExists() throws IOException {
runTestWithNoExpectedUpdates("nifi.properties.only-keystore", EXPECT_STORES_TO_EXIST, !EXPECT_STORES_TO_EXIST);
}
}

View File

@ -34,8 +34,8 @@ import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.security.util.TlsPlatform;
import org.junit.Assume;
@ -45,7 +45,6 @@ import org.junit.Test;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.InetSocketAddress;
@ -101,10 +100,8 @@ public class SSLSocketChannelTest {
private static SSLContext sslContext;
@BeforeClass
public static void setConfiguration() throws GeneralSecurityException, IOException {
final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
public static void setConfiguration() throws GeneralSecurityException {
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
sslContext = SslContextFactory.createSslContext(tlsConfiguration);
}

View File

@ -47,15 +47,10 @@
<artifactId>nifi-security-kms</artifactId>
<version>1.15.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
@ -80,18 +75,6 @@
<artifactId>bcrypt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-minikdc</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>

View File

@ -0,0 +1,48 @@
/*
* 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.security.configuration;
import java.util.Objects;
/**
* KeyStore Configuration properties
*/
public class KeyStoreConfiguration {
private final String location;
private final String password;
private final String keyStoreType;
public KeyStoreConfiguration(final String location, final String password, final String keyStoreType) {
this.location = Objects.requireNonNull(location, "Location required");
this.password = Objects.requireNonNull(password, "Password required");
this.keyStoreType = Objects.requireNonNull(keyStoreType, "KeyStore Type required");
}
public String getLocation() {
return location;
}
public String getPassword() {
return password;
}
public String getKeyStoreType() {
return keyStoreType;
}
}

View File

@ -190,26 +190,6 @@ public class KeyStoreUtils {
}
}
/**
* Creates a temporary default Keystore and Truststore and returns it wrapped in a TLS configuration.
*
* @return a {@link org.apache.nifi.security.util.TlsConfiguration}
*/
public static TlsConfiguration createTlsConfigAndNewKeystoreTruststore() throws IOException, GeneralSecurityException {
return createTlsConfigAndNewKeystoreTruststore(new StandardTlsConfiguration());
}
/**
* Creates a temporary Keystore and Truststore and returns it wrapped in a new TLS configuration with the given values.
* Specifies an expiration duration of 365 days.
*
* @param tlsConfiguration a {@link org.apache.nifi.security.util.TlsConfiguration}
* @return a {@link org.apache.nifi.security.util.TlsConfiguration}
*/
public static TlsConfiguration createTlsConfigAndNewKeystoreTruststore(final TlsConfiguration tlsConfiguration) throws IOException, GeneralSecurityException {
return createTlsConfigAndNewKeystoreTruststore(tlsConfiguration, CERT_DURATION_DAYS, null);
}
/**
* Creates a temporary Keystore and Truststore and returns it wrapped in a new TLS configuration with the given values.
*

View File

@ -20,6 +20,7 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@ -138,7 +139,6 @@ public final class SslContextFactory {
* @return an array of KeyManagers (can be {@code null})
* @throws TlsException if there is a problem reading the keystore to create the key managers
*/
@SuppressWarnings("RedundantCast")
protected static KeyManager[] getKeyManagers(TlsConfiguration tlsConfiguration) throws TlsException {
KeyManager[] keyManagers = null;
if (tlsConfiguration.isKeystoreValid()) {
@ -168,8 +168,8 @@ public final class SslContextFactory {
* @return the loaded trust managers
* @throws TlsException if there is a problem reading from the truststore
*/
@SuppressWarnings("RedundantCast")
public static TrustManager[] getTrustManagers(TlsConfiguration tlsConfiguration) throws TlsException {
public static TrustManager[] getTrustManagers(final TlsConfiguration tlsConfiguration) throws TlsException {
Objects.requireNonNull(tlsConfiguration, "TLS Configuration required");
TrustManager[] trustManagers = null;
if (tlsConfiguration.isTruststoreValid()) {
TrustManagerFactory trustManagerFactory = KeyStoreUtils.loadTrustManagerFactory(tlsConfiguration);
@ -193,7 +193,7 @@ public final class SslContextFactory {
sslContext.init(keyManagers, trustManagers, new SecureRandom());
return sslContext;
} catch (final NoSuchAlgorithmException | KeyManagementException e) {
logger.error("Encountered an error creating SSLContext from TLS configuration ({}): {}", tlsConfiguration.toString(), e.getLocalizedMessage());
logger.error("Encountered an error creating SSLContext from TLS configuration ({}): {}", tlsConfiguration, e.getLocalizedMessage());
throw new TlsException("Error creating SSL context", e);
}
}

View File

@ -0,0 +1,206 @@
/*
* 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.security.util;
import org.apache.nifi.security.configuration.KeyStoreConfiguration;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Objects;
import java.util.UUID;
/**
* KeyStore Factory for creating temporary files primarily used for testing
*/
public class TemporaryKeyStoreBuilder {
private static final String KEY_PAIR_ALGORITHM = "RSA";
private static final int KEY_SIZE = 2048;
private static final int RANDOM_BYTES_LENGTH = 16;
private static final Base64.Encoder ENCODER = Base64.getEncoder().withoutPadding();
private static final String SIGNING_ALGORITHM = "SHA256withRSA";
private static final String DISTINGUISHED_NAME_FORMAT = "CN=%s";
private static final int CERTIFICATE_VALID_DAYS = 1;
private static final KeystoreType KEYSTORE_TYPE = KeystoreType.PKCS12;
private static final String KEY_STORE_EXTENSION = ".p12";
private static final String KEY_STORE_PREFIX = "TemporaryKeyStore-";
private static final String DEFAULT_HOSTNAME = "localhost";
private String hostname = DEFAULT_HOSTNAME;
private String trustStorePassword = generateSecureRandomPassword();
private String trustStoreType = KEYSTORE_TYPE.getType();
/**
* Set Hostname used for Certificate Common Name and DNS Subject Alternative Names
*
* @param hostname Hostname is required
* @return Builder
*/
public TemporaryKeyStoreBuilder hostname(final String hostname) {
this.hostname = Objects.requireNonNull(hostname, "Hostname required");
return this;
}
/**
* Set Trust Store Password used for protected generated Trust Store file
*
* @param trustStorePassword Trust Store Password is required
* @return Builder
*/
public TemporaryKeyStoreBuilder trustStorePassword(final String trustStorePassword) {
this.trustStorePassword = Objects.requireNonNull(trustStorePassword, "TrustStore Password required");
return this;
}
/**
* Set Trust Store Type used for storing Trust Store files
*
* @param trustStoreType Trust Store type must be a supported value for KeyStore.getInstance()
* @return Builder
*/
public TemporaryKeyStoreBuilder trustStoreType(final String trustStoreType) {
this.trustStoreType = Objects.requireNonNull(trustStoreType, "TrustStore Type required");
return this;
}
/**
* Build Temporary KeyStore and TrustStore with configured values and set files with File.deleteOnExit()
*
* @return TLS Configuration with KeyStore and TrustStore properties
*/
public TlsConfiguration build() {
final KeyPair keyPair = generateKeyPair();
final X509Certificate certificate = generateCertificate(hostname, keyPair);
final KeyStoreConfiguration keyStoreConfiguration = setKeyStore(keyPair.getPrivate(), certificate);
final KeyStoreConfiguration trustStoreConfiguration = setTrustStore(certificate);
return new StandardTlsConfiguration(
keyStoreConfiguration.getLocation(),
keyStoreConfiguration.getPassword(),
keyStoreConfiguration.getPassword(),
keyStoreConfiguration.getKeyStoreType(),
trustStoreConfiguration.getLocation(),
trustStoreConfiguration.getPassword(),
trustStoreConfiguration.getKeyStoreType(),
TlsPlatform.getLatestProtocol()
);
}
private KeyStoreConfiguration setKeyStore(final PrivateKey privateKey, final X509Certificate certificate) {
final KeyStore keyStore = getNewKeyStore(KEYSTORE_TYPE.getType());
final String password = generateSecureRandomPassword();
final String alias = UUID.randomUUID().toString();
try {
keyStore.setKeyEntry(alias, privateKey, password.toCharArray(), new Certificate[]{certificate});
} catch (final KeyStoreException e) {
throw new RuntimeException("Set Key Entry Failed", e);
}
final File keyStoreFile = storeKeyStore(keyStore, password.toCharArray());
return new KeyStoreConfiguration(keyStoreFile.getAbsolutePath(), password, KEYSTORE_TYPE.getType());
}
private KeyStoreConfiguration setTrustStore(final X509Certificate certificate) {
final KeyStore keyStore = getNewKeyStore(trustStoreType);
final String alias = UUID.randomUUID().toString();
try {
keyStore.setCertificateEntry(alias, certificate);
} catch (final KeyStoreException e) {
throw new RuntimeException("Set Certificate Entry Failed", e);
}
final File trustStoreFile = storeKeyStore(keyStore, trustStorePassword.toCharArray());
return new KeyStoreConfiguration(trustStoreFile.getAbsolutePath(), trustStorePassword, trustStoreType);
}
private File storeKeyStore(final KeyStore keyStore, final char[] password) {
try {
final File keyStoreFile = File.createTempFile(KEY_STORE_PREFIX, KEY_STORE_EXTENSION);
keyStoreFile.deleteOnExit();
try (final OutputStream outputStream = new FileOutputStream(keyStoreFile)) {
keyStore.store(outputStream, password);
}
return keyStoreFile;
} catch (final IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
throw new RuntimeException("Store KeyStore Failed", e);
}
}
private KeyStore getNewKeyStore(final String newKeyStoreType) {
try {
final KeyStore keyStore = KeyStoreUtils.getKeyStore(newKeyStoreType);
keyStore.load(null);
return keyStore;
} catch (final KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
throw new RuntimeException(String.format("Create KeyStore [%s] Failed", KEYSTORE_TYPE), e);
}
}
private X509Certificate generateCertificate(final String hostname, final KeyPair keyPair) {
final String distinguishedName = String.format(DISTINGUISHED_NAME_FORMAT, hostname);
final String[] dnsNames = new String[] {hostname};
try {
return CertificateUtils.generateSelfSignedX509Certificate(keyPair, distinguishedName, SIGNING_ALGORITHM, CERTIFICATE_VALID_DAYS, dnsNames);
} catch (final CertificateException e) {
throw new RuntimeException("Certificate Generated Failed", e);
}
}
private KeyPair generateKeyPair() {
try {
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
return keyPairGenerator.generateKeyPair();
} catch (final NoSuchAlgorithmException e) {
throw new IllegalArgumentException(String.format("[%s] Algorithm not found", KEY_PAIR_ALGORITHM), e);
}
}
private String generateSecureRandomPassword() {
final SecureRandom secureRandom = new SecureRandom();
final byte[] randomBytes = new byte[RANDOM_BYTES_LENGTH];
secureRandom.nextBytes(randomBytes);
return ENCODER.encodeToString(randomBytes);
}
}

View File

@ -1,267 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.util
import org.apache.nifi.util.NiFiProperties
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLServerSocket
import java.security.Security
@RunWith(JUnit4.class)
class SslContextFactoryTest extends GroovyTestCase {
private static final Logger logger = LoggerFactory.getLogger(SslContextFactoryTest.class)
private static final String KEYSTORE_PATH = "src/test/resources/TlsConfigurationKeystore.jks"
private static final String KEYSTORE_PASSWORD = "keystorepassword"
private static final String KEY_PASSWORD = "keypassword"
private static final KeystoreType KEYSTORE_TYPE = KeystoreType.JKS
private static final String TRUSTSTORE_PATH = "src/test/resources/TlsConfigurationTruststore.jks"
private static final String TRUSTSTORE_PASSWORD = "truststorepassword"
private static final KeystoreType TRUSTSTORE_TYPE = KeystoreType.JKS
private static final String CONFIGURED_TLS_PROTOCOL = "TLSv1.2"
private static final Map<String, String> DEFAULT_PROPS = [
(NiFiProperties.SECURITY_KEYSTORE) : KEYSTORE_PATH,
(NiFiProperties.SECURITY_KEYSTORE_PASSWD) : KEYSTORE_PASSWORD,
(NiFiProperties.SECURITY_KEY_PASSWD) : KEY_PASSWORD,
(NiFiProperties.SECURITY_KEYSTORE_TYPE) : KEYSTORE_TYPE.getType(),
(NiFiProperties.SECURITY_TRUSTSTORE) : TRUSTSTORE_PATH,
(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): TRUSTSTORE_PASSWORD,
(NiFiProperties.SECURITY_TRUSTSTORE_TYPE) : TRUSTSTORE_TYPE.getType(),
]
private NiFiProperties mockNiFiProperties = NiFiProperties.createBasicNiFiProperties("", DEFAULT_PROPS)
private TlsConfiguration tlsConfiguration
@BeforeClass
static void setUpOnce() throws Exception {
Security.addProvider(new BouncyCastleProvider())
logger.metaClass.methodMissing = { String name, args ->
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
}
}
@Before
void setUp() {
tlsConfiguration = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
}
@After
void tearDown() {
}
/**
* Asserts that the protocol versions are correct. In recent versions of Java, this enforces order as well, but in older versions, it just enforces presence.
*
* @param enabledProtocols the actual protocols, either in {@code String[]} or {@code Collection<String>} form
* @param expectedProtocols the specific protocol versions to be present (ordered as desired)
*/
void assertProtocolVersions(def enabledProtocols, def expectedProtocols) {
if (TlsConfiguration.getJavaVersion() > 8) {
assert enabledProtocols == expectedProtocols as String[]
} else {
assert enabledProtocols as Set == expectedProtocols as Set
}
}
@Test
void testShouldCreateSslContextFromTlsConfiguration() {
// Arrange
logger.info("Creating SSL Context from TLS Configuration: ${tlsConfiguration}")
// Act
SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration)
logger.info("Created SSL Context: ${KeyStoreUtils.sslContextToString(sslContext)}")
// Assert
assert sslContext.protocol == tlsConfiguration.protocol
// Check a socket created from this context
assertSocketProtocols(sslContext)
}
@Test
void testCreateSslContextFromTlsConfigurationShouldHandleEmptyKeyPassword() {
// Arrange
// Change the keystore to one with the same keystore and key password, but don't provide the key password
Map missingKeyPasswordProps = DEFAULT_PROPS + [
(NiFiProperties.SECURITY_KEYSTORE) : "src/test/resources/samepassword.jks",
(NiFiProperties.SECURITY_KEY_PASSWD): "",
]
NiFiProperties propertiesWithoutKeyPassword = NiFiProperties.createBasicNiFiProperties("", missingKeyPasswordProps)
TlsConfiguration configWithoutKeyPassword = StandardTlsConfiguration.fromNiFiProperties(propertiesWithoutKeyPassword)
logger.info("Creating SSL Context from TLS Configuration: ${configWithoutKeyPassword}")
// Act
SSLContext sslContext = SslContextFactory.createSslContext(configWithoutKeyPassword)
logger.info("Created SSL Context: ${KeyStoreUtils.sslContextToString(sslContext)}")
// Assert
assert sslContext.protocol == configWithoutKeyPassword.protocol
// Check a socket created from this context
assertSocketProtocols(sslContext)
}
/**
* This test ensures that silent failures don't occur -- if some keystore/truststore properties
* are populated but not enough to be valid, throw an exception on failure.
*/
@Test
void testCreateSslContextFromTlsConfigurationShouldFailOnInvalidProperties() {
// Arrange
// Set up configurations missing the keystore path and truststore path
Map missingKeystorePathProps = DEFAULT_PROPS + [
(NiFiProperties.SECURITY_KEYSTORE): "",
]
NiFiProperties propsNoKeystorePath = NiFiProperties.createBasicNiFiProperties("", missingKeystorePathProps)
TlsConfiguration configNoKeystorePath = StandardTlsConfiguration.fromNiFiProperties(propsNoKeystorePath)
logger.info("Creating SSL Context from TLS Configuration: ${configNoKeystorePath}")
Map missingTruststorePathProps = DEFAULT_PROPS + [
(NiFiProperties.SECURITY_TRUSTSTORE) : "",
// Remove the keystore properties to ensure the right conditional is tested
(NiFiProperties.SECURITY_KEYSTORE) : "",
(NiFiProperties.SECURITY_KEYSTORE_PASSWD): "",
(NiFiProperties.SECURITY_KEY_PASSWD) : "",
(NiFiProperties.SECURITY_KEYSTORE_TYPE) : "",
]
NiFiProperties propsNoTruststorePath = NiFiProperties.createBasicNiFiProperties("", missingTruststorePathProps)
TlsConfiguration configNoTruststorePath = StandardTlsConfiguration.fromNiFiProperties(propsNoTruststorePath)
logger.info("Creating SSL Context from TLS Configuration: ${configNoTruststorePath}")
// Act
def noKeystorePathMsg = shouldFail(TlsException) {
SSLContext sslContext = SslContextFactory.createSslContext(configNoKeystorePath)
logger.info("Created SSL Context missing keystore path: ${KeyStoreUtils.sslContextToString(sslContext)}")
}
def noTruststorePathMsg = shouldFail(TlsException) {
SSLContext sslContext = SslContextFactory.createSslContext(configNoTruststorePath)
logger.info("Created SSL Context missing truststore path: ${KeyStoreUtils.sslContextToString(sslContext)}")
}
// Assert
assert noKeystorePathMsg =~ "The keystore properties are not valid"
assert noTruststorePathMsg =~ "The truststore properties are not valid"
}
/**
* This is a regression test to ensure that a truststore without a password is allowed (legacy truststores did not require a password).
*/
@Test
void testCreateSslContextFromTlsConfigurationShouldHandleEmptyTruststorePassword() {
// Arrange
// Change the truststore to one with no password
Map truststoreNoPasswordProps = DEFAULT_PROPS + [
(NiFiProperties.SECURITY_TRUSTSTORE) : "src/test/resources/no-password-truststore.jks",
(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): "",
]
NiFiProperties propertiesNoTruststorePassword = NiFiProperties.createBasicNiFiProperties("", truststoreNoPasswordProps)
TlsConfiguration configNoTruststorePassword = StandardTlsConfiguration.fromNiFiProperties(propertiesNoTruststorePassword)
logger.info("Creating SSL Context from TLS Configuration: ${configNoTruststorePassword}")
// Act
SSLContext sslContext = SslContextFactory.createSslContext(configNoTruststorePassword)
logger.info("Created SSL Context: ${KeyStoreUtils.sslContextToString(sslContext)}")
// Assert
assert sslContext.protocol == configNoTruststorePassword.protocol
// Check a socket created from this context
assertSocketProtocols(sslContext)
}
/**
* This test is for legacy expectations in nifi-framework-core. That {@code SslContextFactory}
* implementation threw an exception if the keystore properties were present and the truststore
* properties were not.
*/
@Test
void testCreateSslContextFromTlsConfigurationShouldHandleKeystorePropsWithoutTruststoreProps() {
// Arrange
// Change the keystore to one with the same keystore and key password, but don't provide the key password
Map keystoreOnlyProps = DEFAULT_PROPS.findAll { k, v -> k.contains("keystore") }
NiFiProperties keystoreNiFiProperties = NiFiProperties.createBasicNiFiProperties("", keystoreOnlyProps)
TlsConfiguration keystoreOnlyConfig = StandardTlsConfiguration.fromNiFiProperties(keystoreNiFiProperties)
logger.info("Creating SSL Context from TLS Configuration: ${keystoreOnlyConfig}")
// Act
def msg = shouldFail(TlsException) {
SSLContext sslContext = SslContextFactory.createSslContext(keystoreOnlyConfig)
logger.info("Created SSL Context: ${KeyStoreUtils.sslContextToString(sslContext)}")
}
logger.expected(msg)
// Assert
assert msg =~ "Truststore properties are required if keystore properties are present"
}
/**
* This test is for legacy expectations in nifi-framework-core. That {@code SslContextFactory}
* implementation returned {@code null} if none of the properties were populated.
*/
@Test
void testCreateSslContextFromTlsConfigurationShouldHandleEmptyConfiguration() {
// Arrange
TlsConfiguration emptyConfig = new StandardTlsConfiguration()
logger.info("Creating SSL Context from TLS Configuration: ${emptyConfig}")
// Act
SSLContext sslContext = SslContextFactory.createSslContext(emptyConfig)
// Assert
assert !sslContext
}
/**
* Asserts an {@link SSLServerSocket} from the provided {@link SSLContext} has the proper TLS protocols set.
*
* @param sslContext the context under test
*/
void assertSocketProtocols(SSLContext sslContext) {
SSLServerSocket sslSocket = sslContext.serverSocketFactory.createServerSocket() as SSLServerSocket
logger.info("Created SSL (server) socket: ${sslSocket}")
assert sslSocket.enabledProtocols.contains(CONFIGURED_TLS_PROTOCOL)
// Override the SSL parameters protocol version
SSLServerSocket customSslSocket = sslContext.serverSocketFactory.createServerSocket() as SSLServerSocket
def customParameters = customSslSocket.getSSLParameters()
customParameters.setProtocols([CONFIGURED_TLS_PROTOCOL] as String[])
customSslSocket.setSSLParameters(customParameters)
assertProtocolVersions(customSslSocket.enabledProtocols, [CONFIGURED_TLS_PROTOCOL])
}
}

View File

@ -1,257 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.util
import org.apache.nifi.util.NiFiProperties
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.security.Security
@RunWith(JUnit4.class)
class StandardTlsConfigurationTest extends GroovyTestCase {
private static final Logger logger = LoggerFactory.getLogger(StandardTlsConfigurationTest.class)
private static final String KEYSTORE_PATH = "src/test/resources/TlsConfigurationKeystore.jks"
private static final String KEYSTORE_PASSWORD = "keystorepassword"
private static final String KEY_PASSWORD = "keypassword"
private static final KeystoreType KEYSTORE_TYPE = KeystoreType.JKS
private static final String TRUSTSTORE_PATH = "src/test/resources/TlsConfigurationTruststore.jks"
private static final String TRUSTSTORE_PASSWORD = "truststorepassword"
private static final KeystoreType TRUSTSTORE_TYPE = KeystoreType.JKS
private static final Map<String, String> DEFAULT_PROPS = [
(NiFiProperties.SECURITY_KEYSTORE) : KEYSTORE_PATH,
(NiFiProperties.SECURITY_KEYSTORE_PASSWD) : KEYSTORE_PASSWORD,
(NiFiProperties.SECURITY_KEY_PASSWD) : KEY_PASSWORD,
(NiFiProperties.SECURITY_KEYSTORE_TYPE) : KEYSTORE_TYPE.getType(),
(NiFiProperties.SECURITY_TRUSTSTORE) : TRUSTSTORE_PATH,
(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): TRUSTSTORE_PASSWORD,
(NiFiProperties.SECURITY_TRUSTSTORE_TYPE) : TRUSTSTORE_TYPE.getType(),
]
private NiFiProperties mockNiFiProperties = NiFiProperties.createBasicNiFiProperties("", DEFAULT_PROPS)
private TlsConfiguration tlsConfiguration
@BeforeClass
static void setUpOnce() throws Exception {
Security.addProvider(new BouncyCastleProvider())
logger.metaClass.methodMissing = { String name, args ->
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
}
}
@Before
void setUp() throws Exception {
tlsConfiguration = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
}
@After
void tearDown() throws Exception {
}
@Test
void testShouldCreateFromNiFiProperties() {
// Arrange
// Act
TlsConfiguration fromProperties = StandardTlsConfiguration.fromNiFiProperties(mockNiFiProperties)
logger.info("Created TlsConfiguration: ${fromProperties}")
// Assert
assert fromProperties == tlsConfiguration
}
@Test
void testCreateFromNiFiPropertiesShouldHandleNullKeystoreTypes() {
// Arrange
def noKeystoreTypesProps = NiFiProperties.createBasicNiFiProperties("", DEFAULT_PROPS +
[(NiFiProperties.SECURITY_KEYSTORE_TYPE) : "",
(NiFiProperties.SECURITY_TRUSTSTORE_TYPE): ""
])
// Act
TlsConfiguration fromProperties = StandardTlsConfiguration.fromNiFiProperties(noKeystoreTypesProps)
logger.info("Created TlsConfiguration: ${fromProperties}")
// Assert
assert fromProperties.keystoreType == null
assert fromProperties.truststoreType == null
}
@Test
void testShouldGetFunctionalKeyPassword() {
// Arrange
TlsConfiguration withKeyPassword = tlsConfiguration
// A container where the keystore password is explicitly set as the key password as well
TlsConfiguration withoutKeyPassword = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
// A container where null is explicitly set as the key password
TlsConfiguration withNullPassword = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, null, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
// Act
String actualKeyPassword = withKeyPassword.getKeyPassword()
String functionalKeyPassword = withKeyPassword.getFunctionalKeyPassword()
String duplicateKeystorePassword = withoutKeyPassword.getKeyPassword()
String duplicateFunctionalKeyPassword = withoutKeyPassword.getFunctionalKeyPassword()
String missingKeyPassword = withNullPassword.getKeyPassword()
String keystorePassword = withNullPassword.getFunctionalKeyPassword()
// Assert
assert actualKeyPassword == KEY_PASSWORD
assert functionalKeyPassword == KEY_PASSWORD
assert duplicateKeystorePassword == KEYSTORE_PASSWORD
assert duplicateFunctionalKeyPassword == KEYSTORE_PASSWORD
assert missingKeyPassword == null
assert keystorePassword == KEYSTORE_PASSWORD
}
@Test
void testShouldCheckKeystorePopulation() {
// Arrange
TlsConfiguration empty = new StandardTlsConfiguration()
TlsConfiguration noKeystorePassword = new StandardTlsConfiguration(KEYSTORE_PATH, "", KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
// Act
boolean normalIsPopulated = tlsConfiguration.isKeystorePopulated()
boolean emptyIsPopulated = empty.isKeystorePopulated()
boolean noPasswordIsPopulated = noKeystorePassword.isKeystorePopulated()
// Assert
assert normalIsPopulated
assert !emptyIsPopulated
assert !noPasswordIsPopulated
}
@Test
void testShouldCheckTruststorePopulation() {
// Arrange
TlsConfiguration empty = new StandardTlsConfiguration()
TlsConfiguration noTruststorePassword = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, "", TRUSTSTORE_TYPE)
// Act
boolean normalIsPopulated = tlsConfiguration.isTruststorePopulated()
boolean emptyIsPopulated = empty.isTruststorePopulated()
boolean noPasswordIsPopulated = noTruststorePassword.isTruststorePopulated()
// Assert
assert normalIsPopulated
assert !emptyIsPopulated
assert noPasswordIsPopulated
}
@Test
void testIsKeystoreValidFalseNullKeystorePassword() {
TlsConfiguration configuration = new StandardTlsConfiguration(KEYSTORE_PATH, null, KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
assert !configuration.isKeystoreValid()
}
@Test
void testShouldValidateKeystoreConfiguration() {
// Arrange
TlsConfiguration empty = new StandardTlsConfiguration()
TlsConfiguration wrongPassword = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD.reverse(), KEY_PASSWORD.reverse(), KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD.reverse(), TRUSTSTORE_TYPE)
TlsConfiguration invalid = new StandardTlsConfiguration(KEYSTORE_PATH.reverse(), KEYSTORE_PASSWORD.reverse(), KEY_PASSWORD.reverse(), KEYSTORE_TYPE, TRUSTSTORE_PATH.reverse(), TRUSTSTORE_PASSWORD.reverse(), TRUSTSTORE_TYPE)
// Act
boolean normalIsValid = tlsConfiguration.isKeystoreValid()
boolean emptyIsValid = empty.isKeystoreValid()
boolean wrongPasswordIsValid = wrongPassword.isKeystoreValid()
boolean invalidIsValid = invalid.isKeystoreValid()
// Assert
assert normalIsValid
assert !emptyIsValid
assert !wrongPasswordIsValid
assert !invalidIsValid
}
@Test
void testShouldValidateTruststoreConfiguration() {
// Arrange
TlsConfiguration empty = new StandardTlsConfiguration()
TlsConfiguration wrongPassword = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD.reverse(), KEY_PASSWORD.reverse(), KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD.reverse(), TRUSTSTORE_TYPE)
TlsConfiguration invalid = new StandardTlsConfiguration(KEYSTORE_PATH.reverse(), KEYSTORE_PASSWORD.reverse(), KEY_PASSWORD.reverse(), KEYSTORE_TYPE, TRUSTSTORE_PATH.reverse(), TRUSTSTORE_PASSWORD.reverse(), TRUSTSTORE_TYPE)
// Act
boolean normalIsValid = tlsConfiguration.isTruststoreValid()
boolean emptyIsValid = empty.isTruststoreValid()
boolean wrongPasswordIsValid = wrongPassword.isTruststoreValid()
boolean invalidIsValid = invalid.isTruststoreValid()
// Assert
assert normalIsValid
assert !emptyIsValid
assert !wrongPasswordIsValid
assert !invalidIsValid
}
@Test
void testShouldReturnLegacyAndCurrentEnabledProtocolsForSsl() {
TlsConfiguration configuration = getTlsConfiguration(TlsConfiguration.SSL_PROTOCOL)
String[] enabledProtocols = configuration.enabledProtocols
assert enabledProtocols.toList().containsAll(TlsConfiguration.LEGACY_TLS_PROTOCOL_VERSIONS)
assert enabledProtocols.toList().containsAll(TlsConfiguration.getCurrentSupportedTlsProtocolVersions())
}
@Test
void testShouldReturnCurrentEnabledProtocolsForTls() {
TlsConfiguration configuration = getTlsConfiguration(TlsConfiguration.TLS_PROTOCOL)
String[] enabledProtocols = configuration.enabledProtocols
assert !enabledProtocols.toList().containsAll(TlsConfiguration.LEGACY_TLS_PROTOCOL_VERSIONS)
assert enabledProtocols.toList().containsAll(TlsConfiguration.getCurrentSupportedTlsProtocolVersions())
}
@Test
void testShouldReturnConfiguredEnabledProtocols() {
String currentProtocol = TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion()
TlsConfiguration configuration = getTlsConfiguration(currentProtocol)
String[] enabledProtocols = configuration.enabledProtocols
assert enabledProtocols == [currentProtocol] as String[]
}
@Test
void testShouldReturnEmptyEnabledProtocolsForNullProtocol() {
TlsConfiguration configuration = getTlsConfiguration(null)
String[] enabledProtocols = configuration.enabledProtocols
assert enabledProtocols.toList().isEmpty()
}
TlsConfiguration getTlsConfiguration(String protocol) {
new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEY_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, protocol)
}
}

View File

@ -16,10 +16,8 @@
*/
package org.apache.nifi.security.util.crypto
import org.apache.kerby.util.Hex
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.junit.After
import org.junit.Before
import org.bouncycastle.util.encoders.Hex
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Test
@ -44,14 +42,6 @@ class Argon2SecureHasherTest extends GroovyTestCase {
}
}
@Before
void setUp() throws Exception {
}
@After
void tearDown() throws Exception {
}
private static byte[] decodeHex(String hex) {
Hex.decode(hex?.replaceAll("[^0-9a-fA-F]", ""))
}
@ -103,7 +93,7 @@ class Argon2SecureHasherTest extends GroovyTestCase {
// Act
testIterations.times { int i ->
byte[] hash = a2sh.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
String hashHex = new String(Hex.encode(hash))
logger.info("Generated hash: ${hashHex}")
results << hashHex
}

View File

@ -17,8 +17,7 @@
package org.apache.nifi.security.util.crypto
import at.favre.lib.crypto.bcrypt.Radix64Encoder
import org.apache.kerby.util.Hex
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.util.encoders.Hex
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
@ -30,7 +29,6 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.charset.StandardCharsets
import java.security.Security
@RunWith(JUnit4.class)
class BcryptSecureHasherTest extends GroovyTestCase {
@ -38,8 +36,6 @@ class BcryptSecureHasherTest extends GroovyTestCase {
@BeforeClass
static void setupOnce() throws Exception {
Security.addProvider(new BouncyCastleProvider())
logger.metaClass.methodMissing = { String name, args ->
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
}
@ -53,10 +49,6 @@ class BcryptSecureHasherTest extends GroovyTestCase {
void tearDown() throws Exception {
}
private static byte[] decodeHex(String hex) {
Hex.decode(hex?.replaceAll("[^0-9a-fA-F]", ""))
}
@Test
void testShouldBeDeterministicWithStaticSalt() {
// Arrange
@ -75,7 +67,7 @@ class BcryptSecureHasherTest extends GroovyTestCase {
// Act
testIterations.times { int i ->
byte[] hash = bcryptSH.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
String hashHex = new String(Hex.encode(hash))
logger.info("Generated hash: ${hashHex}")
results << hashHex
}

View File

@ -16,36 +16,20 @@
*/
package org.apache.nifi.security.util.crypto
import org.apache.kerby.util.Hex
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.util.encoders.Hex
import org.junit.*
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.charset.StandardCharsets
import java.security.Security
@RunWith(JUnit4.class)
class PBKDF2SecureHasherTest extends GroovyTestCase {
private static final Logger logger = LoggerFactory.getLogger(PBKDF2SecureHasherTest)
@BeforeClass
static void setupOnce() throws Exception {
Security.addProvider(new BouncyCastleProvider())
logger.metaClass.methodMissing = { String name, args ->
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
}
}
@Before
void setUp() throws Exception {
}
@After
void tearDown() throws Exception {
}
@Test
@ -53,7 +37,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Arrange
int cost = 10_000
int dkLength = 32
logger.info("Generating PBKDF2 hash for iterations: ${cost}, desired key length: ${dkLength} bytes (${dkLength * 8} bits)")
int testIterations = 10
byte[] inputBytes = "This is a sensitive value".bytes
@ -67,8 +50,7 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
testIterations.times { int i ->
byte[] hash = pbkdf2SecureHasher.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex}")
String hashHex = new String(Hex.encode(hash))
results << hashHex
}
@ -83,7 +65,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
int cost = 10_000
int saltLength = 16
int dkLength = 32
logger.info("Generating PBKDF2 hash for prf: ${prf}, iterations: ${cost}, salt length: ${saltLength} bytes, desired key length: ${dkLength} bytes (${dkLength * 8} bits)")
int testIterations = 10
byte[] inputBytes = "This is a sensitive value".bytes
@ -98,7 +79,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
testIterations.times { int i ->
byte[] hash = pbkdf2SecureHasher.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex}")
results << hashHex
}
@ -114,7 +94,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
int cost = 10_000
int saltLength = 16
int dkLength = 32
logger.info("Generating PBKDF2 hash for prf: ${prf}, iterations: ${cost}, salt length: ${saltLength} bytes, desired key length: ${dkLength} bytes (${dkLength * 8} bits)")
def input = "This is a sensitive value"
byte[] inputBytes = input.bytes
@ -169,7 +148,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
int cost = 10_000
int saltLength = 16
int dkLength = 32
logger.info("Generating PBKDF2 hash for prf: ${prf}, iterations: ${cost}, salt length: ${saltLength} bytes, desired key length: ${dkLength} bytes (${dkLength * 8} bits)")
def input = "This is a sensitive value"
byte[] inputBytes = input.bytes
@ -182,7 +160,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
def initializeMsg = shouldFail(IllegalArgumentException) {
PBKDF2SecureHasher invalidSaltLengthHasher = new PBKDF2SecureHasher(prf, cost, 7, dkLength)
}
logger.expected(initializeMsg)
def arbitrarySaltRawMsg = shouldFail {
byte[] arbitrarySaltRaw = secureHasher.hashRaw(inputBytes, STATIC_SALT)
@ -213,7 +190,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
String hashHex = pbkdf2SecureHasher.hashHex(input)
logger.info("Generated hash: ${hashHex}")
// Assert
assert hashHex == EXPECTED_HASH_HEX
@ -230,7 +206,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
String hashB64 = pbkdf2SecureHasher.hashBase64(input)
logger.info("Generated hash: ${hashB64}")
// Assert
assert hashB64 == EXPECTED_HASH_BASE64
@ -252,11 +227,9 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
inputs.each { String input ->
String hashHex = pbkdf2SecureHasher.hashHex(input)
logger.info("Generated hex-encoded hash: ${hashHex}")
hexResults << hashHex
String hashB64 = pbkdf2SecureHasher.hashBase64(input)
logger.info("Generated B64-encoded hash: ${hashB64}")
B64Results << hashB64
}
@ -289,7 +262,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
long durationNanos = endNanos - startNanos
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex} in ${durationNanos} ns")
results << hashHex
resultDurations << durationNanos
@ -309,7 +281,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
def results = validIterationCounts.collect { int i ->
boolean valid = PBKDF2SecureHasher.isIterationCountValid(i)
logger.info("Iteration count ${i} is valid: ${valid}")
valid
}
@ -325,7 +296,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
def results = invalidIterationCounts.collect { i ->
boolean valid = PBKDF2SecureHasher.isIterationCountValid(i)
logger.info("Iteration count ${i} is valid: ${valid}")
valid
}
@ -347,7 +317,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
def results = validHLengths.collectEntries { int hLen ->
def dkResults = validDKLengths.collect { int dkLength ->
boolean valid = PBKDF2SecureHasher.isDKLengthValid(hLen, dkLength)
logger.info("Derived key length ${dkLength} bytes (${dkLength * 8} bits) with hLen ${hLen} bytes (${hLen * 8} bits) is valid: ${valid}")
valid
}
[hLen, dkResults]
@ -371,7 +340,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
def results = validHLengths.collectEntries { int hLen ->
def dkResults = invalidDKLengths.collect { int dkLength ->
boolean valid = PBKDF2SecureHasher.isDKLengthValid(hLen, dkLength)
logger.info("Derived key length ${dkLength} bytes (${dkLength * 8} bits) with hLen ${hLen} bytes (${hLen * 8} bits) is valid: ${valid}")
valid
}
[hLen, dkResults]
@ -391,7 +359,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
def results = saltLengths.collect { saltLength ->
def isValid = new PBKDF2SecureHasher().isSaltLengthValid(saltLength)
logger.info("Salt length ${saltLength} bytes is valid: ${isValid}")
isValid
}
@ -407,7 +374,6 @@ class PBKDF2SecureHasherTest extends GroovyTestCase {
// Act
def results = saltLengths.collect { saltLength ->
def isValid = new PBKDF2SecureHasher().isSaltLengthValid(saltLength)
logger.info("Salt length ${saltLength} bytes is valid: ${isValid}")
isValid
}

View File

@ -16,41 +16,15 @@
*/
package org.apache.nifi.security.util.crypto
import org.apache.kerby.util.Hex
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.util.encoders.Hex
import org.junit.*
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.charset.StandardCharsets
import java.security.Security
@RunWith(JUnit4.class)
class ScryptSecureHasherTest extends GroovyTestCase {
private static final Logger logger = LoggerFactory.getLogger(ScryptSecureHasherTest)
@BeforeClass
static void setupOnce() throws Exception {
Security.addProvider(new BouncyCastleProvider())
logger.metaClass.methodMissing = { String name, args ->
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
}
}
@Before
void setUp() throws Exception {
}
@After
void tearDown() throws Exception {
}
private static byte[] decodeHex(String hex) {
Hex.decode(hex?.replaceAll("[^0-9a-fA-F]", ""))
}
@Test
void testShouldBeDeterministicWithStaticSalt() {
@ -59,7 +33,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
int r = 8
int p = 2
int dkLength = 32
logger.info("Generating Scrypt hash for iterations: ${n}, mem: ${r} B, parallelism: ${p}, desired key length: ${dkLength}")
int testIterations = 10
byte[] inputBytes = "This is a sensitive value".bytes
@ -73,8 +46,7 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Act
testIterations.times { int i ->
byte[] hash = scryptSH.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex}")
String hashHex = new String(Hex.encode(hash))
results << hashHex
}
@ -89,7 +61,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
int r = 8
int p = 2
int dkLength = 128
logger.info("Generating Scrypt hash for iterations: ${n}, mem: ${r} B, parallelism: ${p}, desired key length: ${dkLength}")
int testIterations = 10
byte[] inputBytes = "This is a sensitive value".bytes
@ -103,8 +74,7 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Act
testIterations.times { int i ->
byte[] hash = scryptSH.hashRaw(inputBytes)
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex}")
String hashHex = new String(Hex.encode(hash))
results << hashHex
}
@ -120,7 +90,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
int r = 8
int p = 2
int dkLength = 32
logger.info("Generating Scrypt hash for iterations: ${n}, mem: ${r} B, parallelism: ${p}, desired key length: ${dkLength}")
def input = "This is a sensitive value"
byte[] inputBytes = input.bytes
@ -176,35 +145,29 @@ class ScryptSecureHasherTest extends GroovyTestCase {
int r = 8
int p = 2
int dkLength = 32
logger.info("Generating Scrypt hash for iterations: ${n}, mem: ${r} B, parallelism: ${p}, desired key length: ${dkLength}")
def input = "This is a sensitive value"
byte[] inputBytes = input.bytes
final String EXPECTED_HASH_HEX = "a67fd2f4b3aa577b8ecdb682e60b4451a84611dcbbc534bce17616056ef8965d"
final String EXPECTED_HASH_BASE64 = "pn/S9LOqV3uOzbaC5gtEUahGEdy7xTS84XYWBW74ll0="
final byte[] EXPECTED_HASH_BYTES = Hex.decode(EXPECTED_HASH_HEX)
// Static salt instance
ScryptSecureHasher secureHasher = new ScryptSecureHasher(n, r, p, dkLength, 16)
final byte[] STATIC_SALT = "bad_sal".bytes
// Act
def initializationMsg = shouldFail(IllegalArgumentException) {
ScryptSecureHasher invalidSaltLengthHasher = new ScryptSecureHasher(n, r, p, dkLength, 7)
shouldFail(IllegalArgumentException) {
new ScryptSecureHasher(n, r, p, dkLength, 7)
}
logger.expected(initializationMsg)
def arbitrarySaltRawMsg = shouldFail {
byte[] arbitrarySaltHash = secureHasher.hashRaw(inputBytes, STATIC_SALT)
secureHasher.hashRaw(inputBytes, STATIC_SALT)
}
def arbitrarySaltHexMsg = shouldFail {
String arbitrarySaltHashHex = secureHasher.hashHex(input, new String(STATIC_SALT, StandardCharsets.UTF_8))
secureHasher.hashHex(input, new String(STATIC_SALT, StandardCharsets.UTF_8))
}
def arbitrarySaltB64Msg = shouldFail {
String arbitrarySaltHashBase64 = secureHasher.hashBase64(input, new String(STATIC_SALT, StandardCharsets.UTF_8))
secureHasher.hashBase64(input, new String(STATIC_SALT, StandardCharsets.UTF_8))
}
def results = [arbitrarySaltRawMsg, arbitrarySaltHexMsg, arbitrarySaltB64Msg]
@ -224,7 +187,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Act
String hashHex = scryptSH.hashHex(input)
logger.info("Generated hash: ${hashHex}")
// Assert
assert hashHex == EXPECTED_HASH_HEX
@ -241,7 +203,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Act
String hashB64 = scryptSH.hashBase64(input)
logger.info("Generated hash: ${hashB64}")
// Assert
assert hashB64 == EXPECTED_HASH_BASE64
@ -263,11 +224,9 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Act
inputs.each { String input ->
String hashHex = scryptSH.hashHex(input)
logger.info("Generated hex-encoded hash: ${hashHex}")
hexResults << hashHex
String hashB64 = scryptSH.hashBase64(input)
logger.info("Generated B64-encoded hash: ${hashB64}")
B64Results << hashB64
}
@ -300,7 +259,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
long durationNanos = endNanos - startNanos
String hashHex = Hex.encode(hash)
logger.info("Generated hash: ${hashHex} in ${durationNanos} ns")
results << hashHex
resultDurations << durationNanos
@ -337,7 +295,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Assert
results.each { rValue, isRValid ->
logger.info("For R value ${rValue}, R is ${isRValid ? "valid" : "invalid"}")
assert !isRValid
}
}
@ -368,7 +325,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Assert
results.each { n, isNValid ->
logger.info("For N value ${n}, N is ${isNValid ? "valid" : "invalid"}")
assert !isNValid
}
}
@ -383,7 +339,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
def pResults = ps.collectEntries { int p ->
def rResults = rs.collectEntries { int r ->
boolean valid = ScryptSecureHasher.isPValid(p, r)
logger.info("p ${p} is valid for r ${r}: ${valid}")
[r, valid]
}
[p, rResults]
@ -405,7 +360,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
def pResults = ps.collectEntries { int p ->
def rResults = rs.collectEntries { int r ->
boolean valid = ScryptSecureHasher.isPValid(p, r)
logger.info("p ${p} is valid for r ${r}: ${valid}")
[r, valid]
}
[p, rResults]
@ -442,7 +396,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Assert
results.each { dKLength, isDKLengthValid ->
logger.info("For Desired Key Length value ${dKLength}, dkLength is ${isDKLengthValid ? "valid" : "invalid"}")
assert !isDKLengthValid
}
}
@ -477,7 +430,6 @@ class ScryptSecureHasherTest extends GroovyTestCase {
// Assert
results.each { saltLength, isSaltLengthValid ->
logger.info("For Salt Length value ${saltLength}, saltLength is ${isSaltLengthValid ? "valid" : "invalid"}")
assert !isSaltLengthValid
}
}

View File

@ -50,7 +50,8 @@ public class KeyStoreUtilsTest {
private static final char[] STORE_PASSWORD = UUID.randomUUID().toString().toCharArray();
private static final String ALIAS = "alias";
private static final String KEY_ALGORITHM = "RSA";
private static final String SUBJECT_DN = "CN=localhost";
private static final String HOSTNAME = "localhost";
private static final String SUBJECT_DN = String.format("CN=%s", HOSTNAME);
private static final String SECRET_KEY_ALGORITHM = "AES";
private static final String KEY_PROTECTION_ALGORITHM = "PBEWithHmacSHA256AndAES_256";
private static final String HYPHEN_SEPARATOR = "-";
@ -69,7 +70,25 @@ public class KeyStoreUtilsTest {
@Test
public void testCreateTlsConfigAndNewKeystoreTruststore() throws GeneralSecurityException, IOException {
final TlsConfiguration configuration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
final File keyStoreFile = File.createTempFile(KeyStoreUtilsTest.class.getSimpleName(), ".keystore.p12");
keyStoreFile.deleteOnExit();
final File trustStoreFile = File.createTempFile(KeyStoreUtilsTest.class.getSimpleName(), ".truststore.p12");
trustStoreFile.deleteOnExit();
final String password = UUID.randomUUID().toString();
final String keyStoreType = KeystoreType.PKCS12.getType();
final TlsConfiguration requested = new StandardTlsConfiguration(
keyStoreFile.getAbsolutePath(),
password,
password,
keyStoreType,
trustStoreFile.getAbsolutePath(),
password,
keyStoreType,
TlsConfiguration.TLS_PROTOCOL
);
final TlsConfiguration configuration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore(requested, 1, new String[] { HOSTNAME });
final File keystoreFile = new File(configuration.getKeystorePath());
assertTrue("Keystore File not found", keystoreFile.exists());
keystoreFile.deleteOnExit();

View File

@ -0,0 +1,105 @@
/*
* 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.security.util;
import org.apache.nifi.util.StringUtils;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
public class SslSocketFactoryTest {
private static TlsConfiguration tlsConfiguration;
@BeforeAll
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Test
public void testCreateSslContextNullTlsConfiguration() throws TlsException {
final SSLContext sslContext = SslContextFactory.createSslContext(null);
assertNull(sslContext);
}
@Test
public void testCreateSslContextEmptyTlsConfiguration() throws TlsException {
final SSLContext sslContext = SslContextFactory.createSslContext(new StandardTlsConfiguration());
assertNull(sslContext);
}
@Test
public void testCreateSslContextEmptyKeyPassword() throws TlsException {
final TlsConfiguration customTlsConfiguration = new StandardTlsConfiguration(
tlsConfiguration.getKeystorePath(),
tlsConfiguration.getKeystorePassword(),
StringUtils.EMPTY,
tlsConfiguration.getKeystoreType(),
tlsConfiguration.getTruststorePath(),
tlsConfiguration.getTruststorePassword(),
tlsConfiguration.getTruststoreType(),
tlsConfiguration.getProtocol()
);
final SSLContext sslContext = SslContextFactory.createSslContext(customTlsConfiguration);
assertNotNull(sslContext);
assertEquals(customTlsConfiguration.getProtocol(), sslContext.getProtocol());
}
@Test
public void testCreateSslContextEmptyTrustStorePasswordJks() throws TlsException {
final TlsConfiguration customTlsConfiguration = new TemporaryKeyStoreBuilder()
.trustStorePassword(StringUtils.EMPTY)
.trustStoreType(KeystoreType.JKS.getType())
.build();
final SSLContext sslContext = SslContextFactory.createSslContext(customTlsConfiguration);
assertNotNull(sslContext);
assertEquals(customTlsConfiguration.getProtocol(), sslContext.getProtocol());
}
@Test
public void testCreateSslContext() throws TlsException {
final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration);
assertNotNull(sslContext);
assertEquals(tlsConfiguration.getProtocol(), sslContext.getProtocol());
}
@Test
public void testGetTrustManager() throws TlsException {
final X509TrustManager trustManager = SslContextFactory.getX509TrustManager(tlsConfiguration);
assertNotNull(trustManager);
assertEquals(1, trustManager.getAcceptedIssuers().length);
}
@Test
public void testGetTrustManagers() throws TlsException {
final TrustManager[] trustManagers = SslContextFactory.getTrustManagers(tlsConfiguration);
assertNotNull(trustManagers);
assertEquals(1, trustManagers.length);
}
@Test
public void testGetTrustManagersEmptyTlsConfiguration() throws TlsException {
final TrustManager[] trustManagers = SslContextFactory.getTrustManagers(new StandardTlsConfiguration());
assertNull(trustManagers);
}
}

View File

@ -0,0 +1,265 @@
/*
* 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.security.util;
import org.apache.nifi.util.NiFiProperties;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StandardTlsConfigurationTest {
private static final String KEY_STORE_PATH = UUID.randomUUID().toString();
private static final String KEY_STORE_PASSWORD = UUID.randomUUID().toString();
private static final String KEY_PASSWORD = UUID.randomUUID().toString();
private static final String KEY_STORE_TYPE = KeystoreType.PKCS12.getType();
private static final String TRUST_STORE_PATH = UUID.randomUUID().toString();
private static final String TRUST_STORE_PASSWORD = UUID.randomUUID().toString();
private static final String TRUST_STORE_TYPE = KeystoreType.JKS.getType();
private static final String PROTOCOL = TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion();
private static TlsConfiguration tlsConfiguration;
@BeforeAll
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Test
public void testIsKeyStoreValid() {
assertTrue(tlsConfiguration.isKeystoreValid());
}
@Test
public void testIsTrustStoreValid() {
assertTrue(tlsConfiguration.isTruststoreValid());
}
@Test
public void testEqualsNullProperties() {
final StandardTlsConfiguration configuration = new StandardTlsConfiguration();
assertEquals(new StandardTlsConfiguration(), configuration);
}
@Test
public void testHashCodeNullProperties() {
final StandardTlsConfiguration configuration = new StandardTlsConfiguration();
assertEquals(new StandardTlsConfiguration().hashCode(), configuration.hashCode());
}
@Test
public void testFromNiFiPropertiesEmptyProperties() {
final NiFiProperties niFiProperties = NiFiProperties.createBasicNiFiProperties(null);
final TlsConfiguration configuration = StandardTlsConfiguration.fromNiFiProperties(niFiProperties);
assertNotNull(configuration);
assertEquals(PROTOCOL, configuration.getProtocol());
}
@Test
public void testFromNiFiProperties() {
final Map<String, String> properties = new HashMap<>();
properties.put(NiFiProperties.SECURITY_KEYSTORE, KEY_STORE_PATH);
properties.put(NiFiProperties.SECURITY_KEYSTORE_PASSWD, KEY_STORE_PASSWORD);
properties.put(NiFiProperties.SECURITY_KEY_PASSWD, KEY_PASSWORD);
properties.put(NiFiProperties.SECURITY_KEYSTORE_TYPE, KEY_STORE_TYPE);
properties.put(NiFiProperties.SECURITY_TRUSTSTORE, TRUST_STORE_PATH);
properties.put(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD, TRUST_STORE_PASSWORD);
properties.put(NiFiProperties.SECURITY_TRUSTSTORE_TYPE, TRUST_STORE_TYPE);
final NiFiProperties niFiProperties = NiFiProperties.createBasicNiFiProperties(null, properties);
final TlsConfiguration configuration = StandardTlsConfiguration.fromNiFiProperties(niFiProperties);
assertNotNull(configuration);
assertEquals(PROTOCOL, configuration.getProtocol());
assertEquals(KEY_STORE_PATH, configuration.getKeystorePath());
assertEquals(KEY_STORE_PASSWORD, configuration.getKeystorePassword());
assertEquals(KEY_PASSWORD, configuration.getKeyPassword());
assertEquals(KEY_STORE_TYPE, configuration.getKeystoreType().getType());
assertEquals(TRUST_STORE_PATH, configuration.getTruststorePath());
assertEquals(TRUST_STORE_PASSWORD, configuration.getTruststorePassword());
assertEquals(TRUST_STORE_TYPE, configuration.getTruststoreType().getType());
}
@Test
public void testFromNiFiPropertiesTrustStoreProperties() {
final Map<String, String> properties = new HashMap<>();
properties.put(NiFiProperties.SECURITY_TRUSTSTORE, TRUST_STORE_PATH);
properties.put(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD, TRUST_STORE_PASSWORD);
properties.put(NiFiProperties.SECURITY_TRUSTSTORE_TYPE, TRUST_STORE_TYPE);
final NiFiProperties niFiProperties = NiFiProperties.createBasicNiFiProperties(null, properties);
final TlsConfiguration configuration = StandardTlsConfiguration.fromNiFiPropertiesTruststoreOnly(niFiProperties);
assertNotNull(configuration);
assertNull(configuration.getKeystorePath());
assertEquals(PROTOCOL, configuration.getProtocol());
assertEquals(TRUST_STORE_PATH, configuration.getTruststorePath());
assertEquals(TRUST_STORE_PASSWORD, configuration.getTruststorePassword());
assertEquals(TRUST_STORE_TYPE, configuration.getTruststoreType().getType());
}
@Test
public void testFunctionalKeyPasswordFromKeyStorePassword() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
null,
KEY_STORE_TYPE,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
PROTOCOL
);
assertEquals(KEY_STORE_PASSWORD, configuration.getFunctionalKeyPassword());
}
@Test
public void testIsKeyStorePopulated() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
KEY_PASSWORD,
KEY_STORE_TYPE,
null,
null,
null,
PROTOCOL
);
assertTrue(configuration.isKeystorePopulated());
assertTrue(configuration.isAnyKeystorePopulated());
}
@Test
public void testIsKeyStorePopulatedMissingProperties() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
null,
null,
null,
null,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
PROTOCOL
);
assertFalse(configuration.isKeystorePopulated());
assertFalse(configuration.isAnyKeystorePopulated());
}
@Test
public void testIsTrustStorePopulated() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
null,
null,
null,
null,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
PROTOCOL
);
assertTrue(configuration.isTruststorePopulated());
assertTrue(configuration.isAnyTruststorePopulated());
}
@Test
public void testIsTrustStorePopulatedMissingProperties() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
KEY_PASSWORD,
KEY_STORE_TYPE,
null,
null,
null,
PROTOCOL
);
assertFalse(configuration.isTruststorePopulated());
assertFalse(configuration.isAnyTruststorePopulated());
}
@Test
public void testGetEnabledProtocolsVersionMatched() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
KEY_PASSWORD,
KEY_STORE_TYPE,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
PROTOCOL
);
final String[] enabledProtocols = configuration.getEnabledProtocols();
assertArrayEquals(new String[]{PROTOCOL}, enabledProtocols);
}
@Test
public void testGetEnabledProtocolsTlsProtocol() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
KEY_PASSWORD,
KEY_STORE_TYPE,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
TlsConfiguration.TLS_PROTOCOL
);
final String[] enabledProtocols = configuration.getEnabledProtocols();
assertArrayEquals(TlsConfiguration.getCurrentSupportedTlsProtocolVersions(), enabledProtocols);
}
@Test
public void testGetEnabledProtocolsSslProtocol() {
final TlsConfiguration configuration = new StandardTlsConfiguration(
KEY_STORE_PATH,
KEY_STORE_PASSWORD,
KEY_PASSWORD,
KEY_STORE_TYPE,
TRUST_STORE_PATH,
TRUST_STORE_PASSWORD,
TRUST_STORE_TYPE,
TlsConfiguration.SSL_PROTOCOL
);
final String[] enabledProtocols = configuration.getEnabledProtocols();
final List<String> expectedProtocols = new ArrayList<>();
expectedProtocols.addAll(Arrays.asList(TlsConfiguration.LEGACY_TLS_PROTOCOL_VERSIONS));
expectedProtocols.addAll(Arrays.asList(TlsConfiguration.getCurrentSupportedTlsProtocolVersions()));
assertArrayEquals(expectedProtocols.toArray(), enabledProtocols);
}
}

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%-4r [%t] %-5p %c{3} - %m%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>./target/log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
</encoder>
</appender>
<logger name="org.apache.nifi" level="INFO"/>
<logger name="org.apache.nifi.security.util" level="DEBUG"/>
<logger name="org.apache.nifi.security.util.crypto" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>

View File

@ -32,14 +32,12 @@ import static org.junit.Assume.assumeFalse;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@ -68,7 +66,7 @@ import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
import org.apache.nifi.remote.protocol.http.HttpHeaders;
import org.apache.nifi.remote.protocol.http.HttpProxy;
import org.apache.nifi.remote.util.StandardDataPacket;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.stream.io.StreamUtils;
import org.apache.nifi.web.api.dto.ControllerDTO;
@ -1402,9 +1400,7 @@ public class TestHttpClient {
}
}
private static void setTlsConfiguration() throws GeneralSecurityException, IOException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
private static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
}

View File

@ -16,7 +16,7 @@
*/
package org.apache.nifi.vault.hashicorp;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultProperties;
import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultSslProperties;
@ -28,8 +28,6 @@ import org.mockito.Mockito;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;
@ -96,26 +94,22 @@ public class TestStandardHashiCorpVaultCommunicationService {
}
@Test
public void testTLS() throws GeneralSecurityException, IOException {
TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
try {
Mockito.when(sslProperties.getKeyStore()).thenReturn(tlsConfiguration.getKeystorePath());
Mockito.when(sslProperties.getKeyStorePassword()).thenReturn(tlsConfiguration.getKeystorePassword());
Mockito.when(sslProperties.getKeyStoreType()).thenReturn(tlsConfiguration.getKeystoreType().getType());
Mockito.when(sslProperties.getTrustStore()).thenReturn(tlsConfiguration.getTruststorePath());
Mockito.when(sslProperties.getTrustStorePassword()).thenReturn(tlsConfiguration.getTruststorePassword());
Mockito.when(sslProperties.getTrustStoreType()).thenReturn(tlsConfiguration.getTruststoreType().getType());
Mockito.when(sslProperties.getEnabledProtocols()).thenReturn(Arrays.stream(tlsConfiguration.getEnabledProtocols())
.collect(Collectors.joining(",")));
Mockito.when(sslProperties.getEnabledCipherSuites()).thenReturn(CIPHER_SUITE_VALUE);
public void testTLS() {
TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
Mockito.when(properties.getUri()).thenReturn(URI_VALUE.replace("http", "https"));
this.configureService();
Mockito.when(sslProperties.getKeyStore()).thenReturn(tlsConfiguration.getKeystorePath());
Mockito.when(sslProperties.getKeyStorePassword()).thenReturn(tlsConfiguration.getKeystorePassword());
Mockito.when(sslProperties.getKeyStoreType()).thenReturn(tlsConfiguration.getKeystoreType().getType());
Mockito.when(sslProperties.getTrustStore()).thenReturn(tlsConfiguration.getTruststorePath());
Mockito.when(sslProperties.getTrustStorePassword()).thenReturn(tlsConfiguration.getTruststorePassword());
Mockito.when(sslProperties.getTrustStoreType()).thenReturn(tlsConfiguration.getTruststoreType().getType());
Mockito.when(sslProperties.getEnabledProtocols()).thenReturn(Arrays.stream(tlsConfiguration.getEnabledProtocols())
.collect(Collectors.joining(",")));
Mockito.when(sslProperties.getEnabledCipherSuites()).thenReturn(CIPHER_SUITE_VALUE);
this.ensureTlsPropertiesAccessed(1);
} finally {
Files.deleteIfExists(Paths.get(tlsConfiguration.getKeystorePath()));
Files.deleteIfExists(Paths.get(tlsConfiguration.getTruststorePath()));
}
Mockito.when(properties.getUri()).thenReturn(URI_VALUE.replace("http", "https"));
this.configureService();
this.ensureTlsPropertiesAccessed(1);
}
}

View File

@ -22,8 +22,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Properties;
import javax.mail.Message;
@ -37,9 +35,9 @@ import javax.net.ssl.SSLContext;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.ClientAuth;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.StandardTlsConfiguration;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.ssl.RestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
@ -58,10 +56,8 @@ public class TestListenSMTP {
private static final int MESSAGES = 2;
@BeforeClass
public static void setTlsConfiguration() throws IOException, GeneralSecurityException {
final TlsConfiguration testTlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(testTlsConfiguration.getKeystorePath()).deleteOnExit();
new File(testTlsConfiguration.getTruststorePath()).deleteOnExit();
public static void setTlsConfiguration() throws GeneralSecurityException {
final TlsConfiguration testTlsConfiguration = new TemporaryKeyStoreBuilder().build();
tlsConfiguration = new StandardTlsConfiguration(
testTlsConfiguration.getKeystorePath(),

View File

@ -27,8 +27,8 @@ import org.apache.nifi.event.transport.message.ByteArrayMessage;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.security.util.ClientAuth;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -36,8 +36,6 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
@ -153,12 +151,8 @@ public class StringNettyEventSenderFactoryTest {
return factory;
}
private SSLContext getSslContext() throws GeneralSecurityException, IOException {
final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
final File keystoreFile = new File(tlsConfiguration.getKeystorePath());
keystoreFile.deleteOnExit();
final File truststoreFile = new File(tlsConfiguration.getTruststorePath());
truststoreFile.deleteOnExit();
private SSLContext getSslContext() throws GeneralSecurityException {
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
return SslContextFactory.createSslContext(tlsConfiguration);
}
}

View File

@ -18,7 +18,7 @@
package org.apache.nifi.cluster.coordination.http.replication.okhttp
import org.apache.nifi.security.util.KeyStoreUtils
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder
import org.apache.nifi.security.util.TlsConfiguration
import org.apache.nifi.util.NiFiProperties
import org.junit.BeforeClass
@ -32,9 +32,7 @@ class OkHttpReplicationClientTest extends GroovyTestCase {
@BeforeClass
static void setUpOnce() throws Exception {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore()
new File(tlsConfiguration.keystorePath).deleteOnExit()
new File(tlsConfiguration.truststorePath).deleteOnExit()
tlsConfiguration = new TemporaryKeyStoreBuilder().build()
}
private static NiFiProperties mockNiFiProperties() {

View File

@ -18,8 +18,8 @@ package org.apache.nifi.controller.queue.clustered.server
import org.apache.nifi.events.EventReporter
import org.apache.nifi.reporting.Severity
import org.apache.nifi.security.util.KeyStoreUtils
import org.apache.nifi.security.util.SslContextFactory
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder
import org.apache.nifi.security.util.TlsConfiguration
import org.junit.After
import org.junit.Before
@ -46,9 +46,7 @@ class ConnectionLoadBalanceServerTest extends GroovyTestCase {
@BeforeClass
static void setUpOnce() throws Exception {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore()
new File(tlsConfiguration.keystorePath).deleteOnExit()
new File(tlsConfiguration.truststorePath).deleteOnExit()
tlsConfiguration = new TemporaryKeyStoreBuilder().build()
sslContext = SslContextFactory.createSslContext(tlsConfiguration)
}

View File

@ -56,8 +56,8 @@ import org.apache.nifi.controller.repository.claim.ResourceClaimManager;
import org.apache.nifi.controller.repository.claim.StandardResourceClaimManager;
import org.apache.nifi.events.EventReporter;
import org.apache.nifi.provenance.ProvenanceRepository;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.junit.Before;
import org.junit.Test;
@ -68,7 +68,6 @@ import org.mockito.stubbing.Answer;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -190,9 +189,7 @@ public class LoadBalancedQueueIT {
clientRepoRecords = Collections.synchronizedList(new ArrayList<>());
clientFlowFileRepo = createFlowFileRepository(clientRepoRecords);
TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
sslContext = SslContextFactory.createSslContext(tlsConfiguration);
}

View File

@ -28,7 +28,7 @@ import org.apache.nifi.controller.state.providers.AbstractTestStateProvider;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.mock.MockComponentLogger;
import org.apache.nifi.parameter.ParameterLookup;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.NiFiProperties;
import org.apache.zookeeper.server.ServerCnxnFactory;
@ -47,7 +47,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@ -71,10 +70,8 @@ public class ITZooKeeperStateProvider extends AbstractTestStateProvider {
private static TlsConfiguration tlsConfiguration;
@BeforeClass
public static void setTlsConfiguration() throws GeneralSecurityException, IOException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Before

View File

@ -24,7 +24,7 @@ import org.apache.curator.utils.DefaultZookeeperFactory;
import org.apache.curator.utils.ZookeeperFactory;
import org.apache.nifi.controller.cluster.SecureClientZooKeeperFactory;
import org.apache.nifi.controller.cluster.ZooKeeperClientConfig;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.NiFiProperties;
import org.apache.zookeeper.KeeperException;
@ -42,7 +42,6 @@ import org.junit.rules.ExpectedException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -70,10 +69,8 @@ public class ITZooKeeperStateServerTLS {
public ExpectedException expectedException = ExpectedException.none();
@BeforeClass
public static void setTlsConfiguration() throws GeneralSecurityException, IOException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
SECURE_NIFI_PROPS.put(NiFiProperties.STATE_MANAGEMENT_ZOOKEEPER_PROPERTIES, SECURE_ZOOKEEPER_PROPS);
SECURE_NIFI_PROPS.put(NiFiProperties.WEB_HTTPS_PORT, "8443");

View File

@ -17,7 +17,7 @@
package org.apache.nifi.controller.state.server;
import org.apache.commons.io.FileUtils;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.NiFiProperties;
import org.apache.zookeeper.server.ServerCnxnFactory;
@ -30,7 +30,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -66,10 +65,8 @@ public class TestZooKeeperStateServerConfigurations {
private static TlsConfiguration tlsConfiguration;
@BeforeClass
public static void setTlsConfiguration() throws GeneralSecurityException, IOException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
SECURE_NIFI_PROPS.put(NiFiProperties.STATE_MANAGEMENT_ZOOKEEPER_PROPERTIES, SECURE_ZOOKEEPER_PROPS);
SECURE_NIFI_PROPS.put(NiFiProperties.WEB_HTTPS_PORT, "8443");

View File

@ -20,8 +20,8 @@ import org.apache.nifi.bundle.Bundle
import org.apache.nifi.nar.ExtensionManagerHolder
import org.apache.nifi.processor.DataUnit
import org.apache.nifi.remote.io.socket.NetworkUtils
import org.apache.nifi.security.util.KeyStoreUtils
import org.apache.nifi.security.util.StandardTlsConfiguration
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder
import org.apache.nifi.security.util.TlsConfiguration
import org.apache.nifi.security.util.TlsPlatform
import org.apache.nifi.util.NiFiProperties
@ -81,7 +81,7 @@ class JettyServerGroovyTest extends GroovyTestCase {
private static final String TLS_1_3_PROTOCOL = "TLSv1.3"
private static final List<String> TLS_1_3_CIPHER_SUITES = ["TLS_AES_128_GCM_SHA256"]
private static final TlsConfiguration TLS_CONFIGURATION = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore()
private static final TlsConfiguration TLS_CONFIGURATION = new TemporaryKeyStoreBuilder().build()
// These protocol versions should not ever be supported
static private final List<String> LEGACY_TLS_PROTOCOLS = ["TLS", "TLSv1", "TLSv1.1", "SSL", "SSLv2", "SSLv2Hello", "SSLv3"]

View File

@ -16,11 +16,10 @@
*/
package org.apache.nifi.web.server.util;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -29,9 +28,7 @@ import org.mockito.Mockito;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.function.Consumer;
public class TrustStoreScannerTest {
@ -42,8 +39,8 @@ public class TrustStoreScannerTest {
private static File trustStoreFile;
@BeforeClass
public static void initClass() throws GeneralSecurityException, IOException {
TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
public static void initClass() {
TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
keyStoreFile = Paths.get(tlsConfiguration.getKeystorePath()).toFile();
trustStoreFile = Paths.get(tlsConfiguration.getTruststorePath()).toFile();
}
@ -85,10 +82,4 @@ public class TrustStoreScannerTest {
Mockito.verify(sslContextFactory).reload(ArgumentMatchers.any(Consumer.class));
}
@AfterClass
public static void tearDown() throws IOException {
Files.deleteIfExists(keyStoreFile.toPath());
Files.deleteIfExists(trustStoreFile.toPath());
}
}

View File

@ -17,7 +17,7 @@
package org.apache.nifi.web.security.saml.impl;
import org.apache.commons.lang3.SystemUtils;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.security.saml.SAMLConfigurationFactory;
@ -70,9 +70,7 @@ public class TestStandardSAMLService {
final File idpMetadataFile = new File("src/test/resources/saml/sso-circle-meta.xml");
final String baseUrl = "https://localhost:8443/nifi-api";
final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
when(properties.getProperty(NiFiProperties.SECURITY_KEYSTORE)).thenReturn(tlsConfiguration.getKeystorePath());
when(properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD)).thenReturn(tlsConfiguration.getKeystorePassword());

View File

@ -23,8 +23,8 @@ import org.apache.nifi.processors.mqtt.common.MQTTQueueMessage;
import org.apache.nifi.processors.mqtt.common.MqttTestClient;
import org.apache.nifi.processors.mqtt.common.TestConsumeMqttCommon;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.security.util.TlsException;
import org.apache.nifi.ssl.SSLContextService;
@ -42,10 +42,8 @@ import org.junit.Test;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.security.GeneralSecurityException;
import java.util.concurrent.BlockingQueue;
import static org.junit.Assert.assertTrue;
@ -53,7 +51,6 @@ import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class TestConsumeMQTT extends TestConsumeMqttCommon {
private static TlsConfiguration tlsConfiguration;
@ -73,10 +70,8 @@ public class TestConsumeMQTT extends TestConsumeMqttCommon {
}
@BeforeClass
public static void setTlsConfiguration() throws IOException, GeneralSecurityException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Before

View File

@ -23,8 +23,8 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.flowfile.attributes.CoreAttributes;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.StandardTlsConfiguration;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.security.util.TlsException;
import org.apache.nifi.ssl.SSLContextService;
@ -34,7 +34,6 @@ import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.apache.nifi.web.util.ssl.SslContextUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -44,8 +43,6 @@ import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@ -130,8 +127,8 @@ public class InvokeHTTPTest {
private TestRunner runner;
@BeforeClass
public static void setStores() throws IOException, GeneralSecurityException {
generatedTlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
public static void setStores() {
generatedTlsConfiguration = new TemporaryKeyStoreBuilder().build();
truststoreTlsConfiguration = new StandardTlsConfiguration(
null,
null,
@ -142,12 +139,6 @@ public class InvokeHTTPTest {
);
}
@AfterClass
public static void deleteStores() throws IOException {
Files.deleteIfExists(Paths.get(generatedTlsConfiguration.getKeystorePath()));
Files.deleteIfExists(Paths.get(generatedTlsConfiguration.getTruststorePath()));
}
@Before
public void setRunner() {
mockWebServer = new MockWebServer();

View File

@ -44,14 +44,13 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.StandardTlsConfiguration;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.ssl.RestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
@ -62,7 +61,6 @@ import org.apache.nifi.web.util.ssl.SslContextUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
@ -113,9 +111,9 @@ public class TestListenHTTP {
private int availablePort;
@BeforeClass
public static void setUpSuite() throws GeneralSecurityException, IOException {
public static void setUpSuite() throws GeneralSecurityException {
// generate new keystore and truststore
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
serverConfiguration = new StandardTlsConfiguration(
tlsConfiguration.getKeystorePath(),
@ -170,27 +168,6 @@ public class TestListenHTTP {
);
}
@AfterClass
public static void afterClass() throws Exception {
if (tlsConfiguration != null) {
try {
if (StringUtils.isNotBlank(tlsConfiguration.getKeystorePath())) {
Files.deleteIfExists(Paths.get(tlsConfiguration.getKeystorePath()));
}
} catch (IOException e) {
throw new IOException("There was an error deleting a keystore: " + e.getMessage(), e);
}
try {
if (StringUtils.isNotBlank(tlsConfiguration.getTruststorePath())) {
Files.deleteIfExists(Paths.get(tlsConfiguration.getTruststorePath()));
}
} catch (IOException e) {
throw new IOException("There was an error deleting a truststore: " + e.getMessage(), e);
}
}
}
@Before
public void setup() throws IOException {
proc = new ListenHTTP();

View File

@ -25,7 +25,7 @@ import org.apache.nifi.event.transport.message.ByteArrayMessage;
import org.apache.nifi.event.transport.netty.ByteArrayMessageNettyEventServerFactory;
import org.apache.nifi.event.transport.netty.NettyEventServerFactory;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.util.TestRunner;
@ -114,7 +114,7 @@ public class TestPutTCP {
@Test
public void testRunSuccessSslContextService() throws Exception {
final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
final TlsConfiguration tlsConfiguration = new TemporaryKeyStoreBuilder().build();
final SSLContext sslContext = SslContextUtils.createSslContext(tlsConfiguration);
assertNotNull("SSLContext not found", sslContext);

View File

@ -17,9 +17,9 @@
package org.apache.nifi.web.util.ssl;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.security.util.StandardTlsConfiguration;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.security.util.TlsException;
@ -35,9 +35,7 @@ public class SslContextUtils {
static {
try {
TLS_CONFIGURATION = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(TLS_CONFIGURATION.getKeystorePath()).deleteOnExit();
new File(TLS_CONFIGURATION.getTruststorePath()).deleteOnExit();
TLS_CONFIGURATION = new TemporaryKeyStoreBuilder().build();
KEYSTORE_TLS_CONFIGURATION = new StandardTlsConfiguration(
TLS_CONFIGURATION.getKeystorePath(),

View File

@ -23,14 +23,13 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.util.MockProcessContext;
import org.apache.nifi.util.MockValidationContext;
@ -44,10 +43,8 @@ public class SSLContextServiceTest {
private static TlsConfiguration tlsConfiguration;
@BeforeClass
public static void setTlsConfiguration() throws GeneralSecurityException, IOException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
new File(tlsConfiguration.getKeystorePath()).deleteOnExit();
new File(tlsConfiguration.getTruststorePath()).deleteOnExit();
public static void setTlsConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Test

View File

@ -18,12 +18,11 @@ package org.apache.nifi.ssl;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.KeyStoreUtils;
import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
import org.apache.nifi.security.util.TlsConfiguration;
import org.apache.nifi.security.util.TlsPlatform;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -32,10 +31,6 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import static org.junit.Assert.assertEquals;
@ -54,14 +49,8 @@ public class StandardRestrictedSSLContextServiceTest {
private TestRunner runner;
@BeforeClass
public static void setConfiguration() throws IOException, GeneralSecurityException {
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
}
@AfterClass
public static void deleteConfiguration() throws IOException {
Files.deleteIfExists(Paths.get(tlsConfiguration.getKeystorePath()));
Files.deleteIfExists(Paths.get(tlsConfiguration.getTruststorePath()));
public static void setConfiguration() {
tlsConfiguration = new TemporaryKeyStoreBuilder().build();
}
@Before