aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHÃ¥kon Hallingstad <hakon@oath.com>2019-02-18 19:52:05 +0100
committerGitHub <noreply@github.com>2019-02-18 19:52:05 +0100
commitc3f34b6b1de9836d6d2175757a3081ffcc29a90c (patch)
treeb8de6a559038b0438a091e32117c51472a27598e
parent10504a888b8e9affd97edd8749f87b90c23d7b9d (diff)
parenta9e317a5dd2370866bc5c519d522a824cf118c8e (diff)
Merge pull request #8543 from vespa-engine/revert-8511-bjorncs/jdisc-misc-mode-preparations
Revert "Bjorncs/jdisc mixed mode preparations"
-rw-r--r--jrt/src/com/yahoo/jrt/TlsCryptoEngine.java1
-rw-r--r--security-utils/pom.xml5
-rw-r--r--security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java66
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java150
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java90
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/KeyManagerUtils.java49
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/MutableX509KeyManager.java106
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/MutableX509TrustManager.java70
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java98
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java7
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/TrustManagerUtils.java50
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java22
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManagersFactory.java8
-rw-r--r--security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java84
-rw-r--r--security-utils/src/test/java/com/yahoo/security/tls/MutableX509KeyManagerTest.java65
-rw-r--r--security-utils/src/test/java/com/yahoo/security/tls/MutableX509TrustManagerTest.java59
16 files changed, 108 insertions, 822 deletions
diff --git a/jrt/src/com/yahoo/jrt/TlsCryptoEngine.java b/jrt/src/com/yahoo/jrt/TlsCryptoEngine.java
index 84fbb7d4f01..41302a4c725 100644
--- a/jrt/src/com/yahoo/jrt/TlsCryptoEngine.java
+++ b/jrt/src/com/yahoo/jrt/TlsCryptoEngine.java
@@ -22,6 +22,7 @@ public class TlsCryptoEngine implements CryptoEngine {
@Override
public TlsCryptoSocket createCryptoSocket(SocketChannel channel, boolean isServer) {
SSLEngine sslEngine = tlsContext.createSslEngine();
+ sslEngine.setNeedClientAuth(true);
sslEngine.setUseClientMode(!isServer);
return new TlsCryptoSocket(channel, sslEngine);
}
diff --git a/security-utils/pom.xml b/security-utils/pom.xml
index 10dec598915..0a26c73cf70 100644
--- a/security-utils/pom.xml
+++ b/security-utils/pom.xml
@@ -54,11 +54,6 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<plugins>
diff --git a/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java b/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java
index 1ef4df9c7bc..09a5a87138f 100644
--- a/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java
+++ b/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java
@@ -1,14 +1,11 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.security;
-import com.yahoo.security.tls.KeyManagerUtils;
-import com.yahoo.security.tls.TrustManagerUtils;
-
import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509ExtendedKeyManager;
-import javax.net.ssl.X509ExtendedTrustManager;
+import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
@@ -22,17 +19,14 @@ import java.util.List;
import static java.util.Collections.singletonList;
/**
- * A builder for {@link SSLContext}.
- *
* @author bjorncs
*/
public class SslContextBuilder {
- private KeyStoreSupplier trustStoreSupplier = () -> null;
- private KeyStoreSupplier keyStoreSupplier = () -> null;
+ private KeyStoreSupplier trustStoreSupplier;
+ private KeyStoreSupplier keyStoreSupplier;
private char[] keyStorePassword;
- private TrustManagerFactory trustManagerFactory = TrustManagerUtils::createDefaultX509TrustManager;
- private KeyManagerFactory keyManagerFactory = KeyManagerUtils::createDefaultX509KeyManager;
+ private TrustManagersFactory trustManagersFactory = SslContextBuilder::createDefaultTrustManagers;
public SslContextBuilder() {}
@@ -100,21 +94,18 @@ public class SslContextBuilder {
return this;
}
- public SslContextBuilder withTrustManagerFactory(TrustManagerFactory trustManagersFactory) {
- this.trustManagerFactory = trustManagersFactory;
- return this;
- }
-
- public SslContextBuilder withKeyManagerFactory(KeyManagerFactory keyManagerFactory) {
- this.keyManagerFactory = keyManagerFactory;
+ public SslContextBuilder withTrustManagerFactory(TrustManagersFactory trustManagersFactory) {
+ this.trustManagersFactory = trustManagersFactory;
return this;
}
public SSLContext build() {
try {
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
- TrustManager[] trustManagers = new TrustManager[] { trustManagerFactory.createTrustManager(trustStoreSupplier.get()) };
- KeyManager[] keyManagers = new KeyManager[] { keyManagerFactory.createKeyManager(keyStoreSupplier.get(), keyStorePassword) };
+ TrustManager[] trustManagers =
+ trustStoreSupplier != null ? createTrustManagers(trustManagersFactory, trustStoreSupplier) : null;
+ KeyManager[] keyManagers =
+ keyStoreSupplier != null ? createKeyManagers(keyStoreSupplier, keyStorePassword) : null;
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
} catch (GeneralSecurityException e) {
@@ -124,6 +115,27 @@ public class SslContextBuilder {
}
}
+ private static TrustManager[] createTrustManagers(TrustManagersFactory trustManagersFactory, KeyStoreSupplier trustStoreSupplier)
+ throws GeneralSecurityException, IOException {
+ KeyStore truststore = trustStoreSupplier.get();
+ return trustManagersFactory.createTrustManagers(truststore);
+ }
+
+ private static TrustManager[] createDefaultTrustManagers(KeyStore truststore) throws GeneralSecurityException {
+ TrustManagerFactory trustManagerFactory =
+ TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(truststore);
+ return trustManagerFactory.getTrustManagers();
+ }
+
+ private static KeyManager[] createKeyManagers(KeyStoreSupplier keyStoreSupplier, char[] password)
+ throws GeneralSecurityException, IOException {
+ KeyManagerFactory keyManagerFactory =
+ KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(keyStoreSupplier.get(), password);
+ return keyManagerFactory.getKeyManagers();
+ }
+
private static KeyStore createTrustStore(List<X509Certificate> caCertificates) {
KeyStoreBuilder trustStoreBuilder = KeyStoreBuilder.withType(KeyStoreType.JKS);
for (int i = 0; i < caCertificates.size(); i++) {
@@ -137,19 +149,11 @@ public class SslContextBuilder {
}
/**
- * A factory interface for creating {@link X509ExtendedTrustManager}.
- */
- @FunctionalInterface
- public interface TrustManagerFactory {
- X509ExtendedTrustManager createTrustManager(KeyStore truststore) throws GeneralSecurityException;
- }
-
- /**
- * A factory interface for creating {@link X509ExtendedKeyManager}.
+ * A factory interface that is similar to {@link TrustManagerFactory}, but is an interface instead of a class.
*/
@FunctionalInterface
- public interface KeyManagerFactory {
- X509ExtendedKeyManager createKeyManager(KeyStore truststore, char[] password) throws GeneralSecurityException;
+ public interface TrustManagersFactory {
+ TrustManager[] createTrustManagers(KeyStore truststore) throws GeneralSecurityException;
}
}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java b/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java
deleted file mode 100644
index 0dae185995c..00000000000
--- a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.X509CertificateUtils;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.X509ExtendedKeyManager;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.net.Socket;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.KeyStore;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.time.Duration;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * A {@link X509ExtendedKeyManager} that reloads the certificate and private key from file regularly.
- *
- * @author bjorncs
- */
-public class AutoReloadingX509KeyManager extends X509ExtendedKeyManager implements AutoCloseable {
-
- private static final Duration UPDATE_PERIOD = Duration.ofHours(1);
-
- private static final Logger log = Logger.getLogger(AutoReloadingX509KeyManager.class.getName());
-
- private final MutableX509KeyManager mutableX509KeyManager;
- private final ScheduledExecutorService scheduler;
- private final Path privateKeyFile;
- private final Path certificatesFile;
-
- private AutoReloadingX509KeyManager(Path privateKeyFile, Path certificatesFile) {
- this(privateKeyFile, certificatesFile, createDefaultScheduler());
- }
-
- AutoReloadingX509KeyManager(Path privateKeyFile, Path certificatesFile, ScheduledExecutorService scheduler) {
- this.privateKeyFile = privateKeyFile;
- this.certificatesFile = certificatesFile;
- this.scheduler = scheduler;
- this.mutableX509KeyManager = new MutableX509KeyManager(createKeystore(privateKeyFile, certificatesFile), new char[0]);
- scheduler.scheduleAtFixedRate(
- new KeyManagerReloader(), UPDATE_PERIOD.getSeconds()/*initial delay*/, UPDATE_PERIOD.getSeconds(), TimeUnit.SECONDS);
- }
-
- public static AutoReloadingX509KeyManager fromPemFiles(Path privateKeyFile, Path certificatesFile) {
- return new AutoReloadingX509KeyManager(privateKeyFile, certificatesFile);
- }
-
- private static KeyStore createKeystore(Path privateKey, Path certificateChain) {
- try {
- return KeyStoreBuilder.withType(KeyStoreType.PKCS12)
- .withKeyEntry(
- "default",
- KeyUtils.fromPemEncodedPrivateKey(Files.readString(privateKey)),
- X509CertificateUtils.certificateListFromPem(Files.readString(certificateChain)))
- .build();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static ScheduledExecutorService createDefaultScheduler() {
- return Executors.newSingleThreadScheduledExecutor(runnable -> {
- Thread thread = new Thread(runnable, "auto-reloading-x509-key-manager");
- thread.setDaemon(true);
- return thread;
- });
- }
-
- private class KeyManagerReloader implements Runnable {
- @Override
- public void run() {
- try {
- log.log(Level.FINE, () -> String.format("Reloading key and certificate chain (private-key='%s', certificates='%s')", privateKeyFile, certificatesFile));
- mutableX509KeyManager.updateKeystore(createKeystore(privateKeyFile, certificatesFile), new char[0]);
- } catch (Throwable t) {
- log.log(Level.SEVERE,
- String.format("Failed to load X509 key manager (private-key='%s', certificates='%s'): %s",
- privateKeyFile, certificatesFile, t.getMessage()),
- t);
- }
- }
- }
-
- @Override
- public void close() {
- try {
- scheduler.shutdownNow();
- scheduler.awaitTermination(5, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- //
- // Methods from X509ExtendedKeyManager
- //
-
- @Override
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return mutableX509KeyManager.getServerAliases(keyType, issuers);
- }
-
- @Override
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return mutableX509KeyManager.getClientAliases(keyType, issuers);
- }
-
- @Override
- public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
- return mutableX509KeyManager.chooseServerAlias(keyType, issuers, socket);
- }
-
- @Override
- public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
- return mutableX509KeyManager.chooseClientAlias(keyType, issuers, socket);
- }
-
- @Override
- public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
- return mutableX509KeyManager.chooseEngineServerAlias(keyType, issuers, engine);
- }
-
- @Override
- public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
- return mutableX509KeyManager.chooseEngineClientAlias(keyType, issuers, engine);
- }
-
- @Override
- public X509Certificate[] getCertificateChain(String alias) {
- return mutableX509KeyManager.getCertificateChain(alias);
- }
-
- @Override
- public PrivateKey getPrivateKey(String alias) {
- return mutableX509KeyManager.getPrivateKey(alias);
- }
-
-}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java
index c9c326df9ed..2befd50332a 100644
--- a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java
+++ b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java
@@ -7,7 +7,7 @@ import com.yahoo.security.tls.policy.AuthorizedPeers;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
+import java.nio.file.Path;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Arrays;
@@ -38,8 +38,7 @@ public class DefaultTlsContext implements TlsContext {
private static final Logger log = Logger.getLogger(DefaultTlsContext.class.getName());
private final SSLContext sslContext;
- private final String[] validCiphers;
- private final String[] validProtocols;
+ private final List<String> acceptedCiphers;
public DefaultTlsContext(List<X509Certificate> certificates,
PrivateKey privateKey,
@@ -47,77 +46,49 @@ public class DefaultTlsContext implements TlsContext {
AuthorizedPeers authorizedPeers,
AuthorizationMode mode,
List<String> acceptedCiphers) {
- this(createSslContext(certificates, privateKey, caCertificates, authorizedPeers, mode),
- acceptedCiphers);
+ this.sslContext = createSslContext(certificates, privateKey, caCertificates, authorizedPeers, mode);
+ this.acceptedCiphers = acceptedCiphers;
}
-
- public DefaultTlsContext(SSLContext sslContext, List<String> acceptedCiphers) {
- this.sslContext = sslContext;
- this.validCiphers = getAllowedCiphers(sslContext, acceptedCiphers);
- this.validProtocols = getAllowedProtocols(sslContext);
+ public DefaultTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) {
+ TransportSecurityOptions options = TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile);
+ this.sslContext = createSslContext(options, mode);
+ this.acceptedCiphers = options.getAcceptedCiphers();
}
+ @Override
+ public SSLEngine createSslEngine() {
+ SSLEngine sslEngine = sslContext.createSSLEngine();
+ restrictSetOfEnabledCiphers(sslEngine, acceptedCiphers);
+ restrictTlsProtocols(sslEngine);
+ return sslEngine;
+ }
- private static String[] getAllowedCiphers(SSLContext sslContext, List<String> acceptedCiphers) {
- String[] supportedCipherSuites = sslContext.getSupportedSSLParameters().getCipherSuites();
- String[] validCipherSuites = Arrays.stream(supportedCipherSuites)
+ private static void restrictSetOfEnabledCiphers(SSLEngine sslEngine, List<String> acceptedCiphers) {
+ String[] validCipherSuites = Arrays.stream(sslEngine.getSupportedCipherSuites())
.filter(suite -> ALLOWED_CIPHER_SUITES.contains(suite) && (acceptedCiphers.isEmpty() || acceptedCiphers.contains(suite)))
.toArray(String[]::new);
if (validCipherSuites.length == 0) {
throw new IllegalStateException(
String.format("None of the allowed cipher suites are supported " +
"(allowed-cipher-suites=%s, supported-cipher-suites=%s, accepted-cipher-suites=%s)",
- ALLOWED_CIPHER_SUITES, List.of(supportedCipherSuites), acceptedCiphers));
+ ALLOWED_CIPHER_SUITES, List.of(sslEngine.getSupportedCipherSuites()), acceptedCiphers));
}
- log.log(Level.FINE, () -> String.format("Allowed cipher suites that are supported: %s", List.of(validCipherSuites)));
- return validCipherSuites;
+ log.log(Level.FINE, () -> String.format("Allowed cipher suites that are supported: %s", Arrays.toString(validCipherSuites)));
+ sslEngine.setEnabledCipherSuites(validCipherSuites);
}
- private static String[] getAllowedProtocols(SSLContext sslContext) {
- String[] supportedProtocols = sslContext.getSupportedSSLParameters().getProtocols();
- String[] validProtocols = Arrays.stream(supportedProtocols)
+ private static void restrictTlsProtocols(SSLEngine sslEngine) {
+ String[] validProtocols = Arrays.stream(sslEngine.getSupportedProtocols())
.filter(ALLOWED_PROTOCOLS::contains)
.toArray(String[]::new);
if (validProtocols.length == 0) {
throw new IllegalArgumentException(
String.format("None of the allowed protocols are supported (allowed-protocols=%s, supported-protocols=%s)",
- ALLOWED_PROTOCOLS, List.of(supportedProtocols)));
+ ALLOWED_PROTOCOLS, Arrays.toString(sslEngine.getSupportedProtocols())));
}
- log.log(Level.FINE, () -> String.format("Allowed protocols that are supported: %s", List.of(validProtocols)));
- return validProtocols;
- }
-
- @Override
- public SSLContext context() {
- return sslContext;
- }
-
- @Override
- public SSLParameters parameters() {
- return createSslParameters();
- }
-
- @Override
- public SSLEngine createSslEngine() {
- SSLEngine sslEngine = sslContext.createSSLEngine();
- sslEngine.setSSLParameters(createSslParameters());
- return sslEngine;
- }
-
- @Override
- public SSLEngine createSslEngine(String peerHost, int peerPort) {
- SSLEngine sslEngine = sslContext.createSSLEngine(peerHost, peerPort);
- sslEngine.setSSLParameters(createSslParameters());
- return sslEngine;
- }
-
- private SSLParameters createSslParameters() {
- SSLParameters newParameters = sslContext.getDefaultSSLParameters();
- newParameters.setCipherSuites(validCiphers);
- newParameters.setProtocols(validProtocols);
- newParameters.setNeedClientAuth(true);
- return newParameters;
+ log.log(Level.FINE, () -> String.format("Allowed protocols that are supported: %s", Arrays.toString(validProtocols)));
+ sslEngine.setEnabledProtocols(validProtocols);
}
private static SSLContext createSslContext(List<X509Certificate> certificates,
@@ -138,5 +109,16 @@ public class DefaultTlsContext implements TlsContext {
return builder.build();
}
+ private static SSLContext createSslContext(TransportSecurityOptions options, AuthorizationMode mode) {
+ SslContextBuilder builder = new SslContextBuilder();
+ options.getCertificatesFile()
+ .ifPresent(certificates -> builder.withKeyStore(options.getPrivateKeyFile().get(), certificates));
+ options.getCaCertificatesFile().ifPresent(builder::withTrustStore);
+ if (mode != AuthorizationMode.DISABLE) {
+ options.getAuthorizedPeers().ifPresent(
+ authorizedPeers -> builder.withTrustManagerFactory(new PeerAuthorizerTrustManagersFactory(authorizedPeers, mode)));
+ }
+ return builder.build();
+ }
}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/KeyManagerUtils.java b/security-utils/src/main/java/com/yahoo/security/tls/KeyManagerUtils.java
deleted file mode 100644
index 2e48de3c01f..00000000000
--- a/security-utils/src/main/java/com/yahoo/security/tls/KeyManagerUtils.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.X509ExtendedKeyManager;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utility methods for constructing {@link X509ExtendedKeyManager}.
- *
- * @author bjorncs
- */
-public class KeyManagerUtils {
-
- public static X509ExtendedKeyManager createDefaultX509KeyManager(KeyStore keystore, char[] password) {
- try {
- KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- keyManagerFactory.init(keystore, password);
- KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
- return Arrays.stream(keyManagers)
- .filter(manager -> manager instanceof X509ExtendedKeyManager)
- .map(X509ExtendedKeyManager.class::cast)
- .findFirst()
- .orElseThrow(() -> new RuntimeException("No X509ExtendedKeyManager in " + List.of(keyManagers)));
- } catch (GeneralSecurityException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static X509ExtendedKeyManager createDefaultX509KeyManager(PrivateKey privateKey, List<X509Certificate> certificateChain) {
- KeyStore keystore = KeyStoreBuilder.withType(KeyStoreType.PKCS12)
- .withKeyEntry("default", privateKey, certificateChain)
- .build();
- return createDefaultX509KeyManager(keystore, new char[0]);
- }
-
- public static X509ExtendedKeyManager createDefaultX509KeyManager() {
- return createDefaultX509KeyManager(null, new char[0]);
- }
-}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509KeyManager.java b/security-utils/src/main/java/com/yahoo/security/tls/MutableX509KeyManager.java
deleted file mode 100644
index e5e56f7a181..00000000000
--- a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509KeyManager.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.X509ExtendedKeyManager;
-import java.net.Socket;
-import java.security.KeyStore;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.util.WeakHashMap;
-
-/**
- * A {@link X509ExtendedKeyManager} which can be updated with new certificate chain and private key while in use.
- *
- * The implementations assumes that aliases are retrieved from the same thread as the certificate chain and private key.
- * This is case for OpenJDK 11.
- *
- * @author bjorncs
- */
-public class MutableX509KeyManager extends X509ExtendedKeyManager {
-
- // Not using ThreadLocal as we want the x509 key manager instances to be collected
- // when either the thread dies or the MutableX509KeyManager instance is collected (latter not the case for ThreadLocal).
- private final WeakHashMap<Thread, X509ExtendedKeyManager> threadLocalManager = new WeakHashMap<>();
- private volatile X509ExtendedKeyManager currentManager;
-
- public MutableX509KeyManager(KeyStore keystore, char[] password) {
- this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(keystore, password);
- }
-
- public MutableX509KeyManager() {
- this.currentManager = KeyManagerUtils.createDefaultX509KeyManager();
- }
-
- public void updateKeystore(KeyStore keystore, char[] password) {
- this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(keystore, password);
- }
-
- public void useDefaultKeystore() {
- this.currentManager = KeyManagerUtils.createDefaultX509KeyManager();
- }
-
- @Override
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return updateAndGetThreadLocalManager()
- .getServerAliases(keyType, issuers);
- }
-
- @Override
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return updateAndGetThreadLocalManager()
- .getClientAliases(keyType, issuers);
- }
-
- @Override
- public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
- return updateAndGetThreadLocalManager()
- .chooseServerAlias(keyType, issuers, socket);
- }
-
- @Override
- public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
- return updateAndGetThreadLocalManager()
- .chooseClientAlias(keyType, issuers, socket);
- }
-
- @Override
- public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
- return updateAndGetThreadLocalManager()
- .chooseEngineServerAlias(keyType, issuers, engine);
- }
-
- @Override
- public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
- return updateAndGetThreadLocalManager()
- .chooseEngineClientAlias(keyType, issuers, engine);
- }
-
- private X509ExtendedKeyManager updateAndGetThreadLocalManager() {
- X509ExtendedKeyManager currentManager = this.currentManager;
- threadLocalManager.put(Thread.currentThread(), currentManager);
- return currentManager;
- }
-
- @Override
- public X509Certificate[] getCertificateChain(String alias) {
- return getThreadLocalManager()
- .getCertificateChain(alias);
- }
-
- @Override
- public PrivateKey getPrivateKey(String alias) {
- return getThreadLocalManager()
- .getPrivateKey(alias);
- }
-
- private X509ExtendedKeyManager getThreadLocalManager() {
- X509ExtendedKeyManager manager = threadLocalManager.get(Thread.currentThread());
- if (manager == null) {
- throw new IllegalStateException("Methods to retrieve valid aliases has not been called previously from this thread");
- }
- return manager;
- }
-
-}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509TrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/MutableX509TrustManager.java
deleted file mode 100644
index ed424480d26..00000000000
--- a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509TrustManager.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.X509ExtendedTrustManager;
-import java.net.Socket;
-import java.security.KeyStore;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-/**
- * A {@link X509ExtendedTrustManager} which can be updated with new CA certificates while in use.
- *
- * @author bjorncs
- */
-public class MutableX509TrustManager extends X509ExtendedTrustManager {
-
- private volatile X509ExtendedTrustManager currentManager;
-
- public MutableX509TrustManager(KeyStore truststore) {
- this.currentManager = TrustManagerUtils.createDefaultX509TrustManager(truststore);
- }
-
- public MutableX509TrustManager() {
- this.currentManager = TrustManagerUtils.createDefaultX509TrustManager();
- }
-
- public void updateTruststore(KeyStore truststore) {
- this.currentManager = TrustManagerUtils.createDefaultX509TrustManager(truststore);
- }
-
- public void useDefaultTruststore() {
- this.currentManager = TrustManagerUtils.createDefaultX509TrustManager();
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- currentManager.checkClientTrusted(chain, authType);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- currentManager.checkServerTrusted(chain, authType);
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
- currentManager.checkClientTrusted(chain, authType, socket);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
- currentManager.checkServerTrusted(chain, authType, socket);
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine) throws CertificateException {
- currentManager.checkClientTrusted(chain, authType, sslEngine);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine) throws CertificateException {
- currentManager.checkServerTrusted(chain, authType, sslEngine);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return currentManager.getAcceptedIssuers();
- }
-}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java
index b57105f54f9..5add13e067d 100644
--- a/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java
+++ b/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java
@@ -1,28 +1,13 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.security.tls;
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SslContextBuilder;
-import com.yahoo.security.X509CertificateUtils;
-import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager;
-
-import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.X509ExtendedTrustManager;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.security.KeyStore;
-import java.security.cert.X509Certificate;
import java.time.Duration;
-import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -38,9 +23,8 @@ public class ReloadingTlsContext implements TlsContext {
private static final Logger log = Logger.getLogger(ReloadingTlsContext.class.getName());
private final Path tlsOptionsConfigFile;
- private final TlsContext tlsContext;
- private final MutableX509TrustManager trustManager = new MutableX509TrustManager();
- private final MutableX509KeyManager keyManager = new MutableX509KeyManager();
+ private final AuthorizationMode mode;
+ private final AtomicReference<TlsContext> currentTlsContext;
private final ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor(runnable -> {
Thread thread = new Thread(runnable, "tls-context-reloader");
@@ -50,77 +34,19 @@ public class ReloadingTlsContext implements TlsContext {
public ReloadingTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) {
this.tlsOptionsConfigFile = tlsOptionsConfigFile;
- TransportSecurityOptions options = TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile);
- reloadCryptoMaterial(options, trustManager, keyManager);
- this.tlsContext = createDefaultTlsContext(options, mode, trustManager, keyManager);
- this.scheduler.scheduleAtFixedRate(new CryptoMaterialReloader(),
+ this.mode = mode;
+ this.currentTlsContext = new AtomicReference<>(new DefaultTlsContext(tlsOptionsConfigFile, mode));
+ this.scheduler.scheduleAtFixedRate(new SslContextReloader(),
UPDATE_PERIOD.getSeconds()/*initial delay*/,
UPDATE_PERIOD.getSeconds(),
TimeUnit.SECONDS);
}
- private static void reloadCryptoMaterial(TransportSecurityOptions options,
- MutableX509TrustManager trustManager,
- MutableX509KeyManager keyManager) {
- if (options.getCaCertificatesFile().isPresent()) {
- trustManager.updateTruststore(loadTruststore(options.getCaCertificatesFile().get()));
- } else {
- trustManager.useDefaultTruststore();
- }
-
- if (options.getPrivateKeyFile().isPresent() && options.getCertificatesFile().isPresent()) {
- keyManager.updateKeystore(loadKeystore(options.getPrivateKeyFile().get(), options.getCertificatesFile().get()), new char[0]);
- } else {
- keyManager.useDefaultKeystore();
- }
- }
-
- private static KeyStore loadTruststore(Path caCertificateFile) {
- try {
- List<X509Certificate> caCertificates = X509CertificateUtils.certificateListFromPem(Files.readString(caCertificateFile));
- KeyStoreBuilder trustStoreBuilder = KeyStoreBuilder.withType(KeyStoreType.PKCS12);
- for (int i = 0; i < caCertificates.size(); i++) {
- trustStoreBuilder.withCertificateEntry("cert-" + i, caCertificates.get(i));
- }
- return trustStoreBuilder.build();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static KeyStore loadKeystore(Path privateKeyFile, Path certificatesFile) {
- try {
- return KeyStoreBuilder.withType(KeyStoreType.PKCS12)
- .withKeyEntry(
- "default",
- KeyUtils.fromPemEncodedPrivateKey(Files.readString(privateKeyFile)),
- X509CertificateUtils.certificateListFromPem(Files.readString(certificatesFile)))
- .build();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static DefaultTlsContext createDefaultTlsContext(TransportSecurityOptions options,
- AuthorizationMode mode,
- MutableX509TrustManager mutableTrustManager,
- MutableX509KeyManager mutableKeyManager) {
- SSLContext sslContext = new SslContextBuilder()
- .withKeyManagerFactory((ignoredKeystore, ignoredPassword) -> mutableKeyManager)
- .withTrustManagerFactory(
- ignoredTruststore -> options.getAuthorizedPeers()
- .map(authorizedPeers -> (X509ExtendedTrustManager) new PeerAuthorizerTrustManager(authorizedPeers, mode, mutableTrustManager))
- .orElse(mutableTrustManager))
- .build();
- return new DefaultTlsContext(sslContext, options.getAcceptedCiphers());
+ @Override
+ public SSLEngine createSslEngine() {
+ return currentTlsContext.get().createSslEngine();
}
- // Wrapped methods from TlsContext
- @Override public SSLContext context() { return tlsContext.context(); }
- @Override public SSLParameters parameters() { return tlsContext.parameters(); }
- @Override public SSLEngine createSslEngine() { return tlsContext.createSslEngine(); }
- @Override public SSLEngine createSslEngine(String peerHost, int peerPort) { return tlsContext.createSslEngine(peerHost, peerPort); }
-
@Override
public void close() {
try {
@@ -131,13 +57,13 @@ public class ReloadingTlsContext implements TlsContext {
}
}
- private class CryptoMaterialReloader implements Runnable {
+ private class SslContextReloader implements Runnable {
@Override
public void run() {
try {
- reloadCryptoMaterial(TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile), trustManager, keyManager);
+ currentTlsContext.set(new DefaultTlsContext(tlsOptionsConfigFile, mode));
} catch (Throwable t) {
- log.log(Level.SEVERE, String.format("Failed to reload crypto material (path='%s'): %s", tlsOptionsConfigFile, t.getMessage()), t);
+ log.log(Level.SEVERE, String.format("Failed to load SSLContext (path='%s'): %s", tlsOptionsConfigFile, t.getMessage()), t);
}
}
}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java
index b315dd00b31..58687a0ba8f 100644
--- a/security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java
+++ b/security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java
@@ -3,7 +3,6 @@ package com.yahoo.security.tls;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
/**
* A simplified version of {@link SSLContext} modelled as an interface.
@@ -12,14 +11,8 @@ import javax.net.ssl.SSLParameters;
*/
public interface TlsContext extends AutoCloseable {
- SSLContext context();
-
- SSLParameters parameters();
-
SSLEngine createSslEngine();
- SSLEngine createSslEngine(String peerHost, int peerPort);
-
@Override default void close() {}
}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TrustManagerUtils.java b/security-utils/src/main/java/com/yahoo/security/tls/TrustManagerUtils.java
deleted file mode 100644
index f114b672ed8..00000000000
--- a/security-utils/src/main/java/com/yahoo/security/tls/TrustManagerUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedTrustManager;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utility methods for constructing {@link X509ExtendedTrustManager}.
- *
- * @author bjorncs
- */
-public class TrustManagerUtils {
-
- public static X509ExtendedTrustManager createDefaultX509TrustManager(KeyStore truststore) {
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(truststore);
- TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
- return Arrays.stream(trustManagers)
- .filter(manager -> manager instanceof X509ExtendedTrustManager)
- .map(X509ExtendedTrustManager.class::cast)
- .findFirst()
- .orElseThrow(() -> new RuntimeException("No X509ExtendedTrustManager in " + List.of(trustManagers)));
- } catch (GeneralSecurityException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static X509ExtendedTrustManager createDefaultX509TrustManager(List<X509Certificate> certificates) {
- KeyStoreBuilder truststoreBuilder = KeyStoreBuilder.withType(KeyStoreType.PKCS12);
- for (int i = 0; i < certificates.size(); i++) {
- truststoreBuilder.withCertificateEntry("cert-" + i, certificates.get(i));
- }
- KeyStore truststore = truststoreBuilder.build();
- return createDefaultX509TrustManager(truststore);
- }
-
- public static X509ExtendedTrustManager createDefaultX509TrustManager() {
- return createDefaultX509TrustManager((KeyStore) null);
- }
-}
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java
index eee2e502183..80acc940a99 100644
--- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java
+++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java
@@ -3,12 +3,14 @@ package com.yahoo.security.tls.authz;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.security.tls.AuthorizationMode;
-import com.yahoo.security.tls.TrustManagerUtils;
import com.yahoo.security.tls.policy.AuthorizedPeers;
import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedTrustManager;
import java.net.Socket;
+import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
@@ -37,8 +39,22 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager {
this.defaultTrustManager = defaultTrustManager;
}
- public PeerAuthorizerTrustManager(AuthorizedPeers authorizedPeers, AuthorizationMode mode, KeyStore truststore) {
- this(authorizedPeers, mode, TrustManagerUtils.createDefaultX509TrustManager(truststore));
+ public static TrustManager[] wrapTrustManagersFromKeystore(AuthorizedPeers authorizedPeers, AuthorizationMode mode, KeyStore keystore) throws GeneralSecurityException {
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init(keystore);
+ return wrapTrustManagers(authorizedPeers, mode, factory.getTrustManagers());
+ }
+
+ public static TrustManager[] wrapTrustManagers(AuthorizedPeers authorizedPeers, AuthorizationMode mode, TrustManager[] managers) {
+ TrustManager[] wrappedManagers = new TrustManager[managers.length];
+ for (int i = 0; i < managers.length; i++) {
+ if (managers[i] instanceof X509ExtendedTrustManager) {
+ wrappedManagers[i] = new PeerAuthorizerTrustManager(authorizedPeers, mode, (X509ExtendedTrustManager) managers[i]);
+ } else {
+ wrappedManagers[i] = managers[i];
+ }
+ }
+ return wrappedManagers;
}
@Override
diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManagersFactory.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManagersFactory.java
index 6ec8450c035..c0a3b4e41a5 100644
--- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManagersFactory.java
+++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManagersFactory.java
@@ -5,12 +5,14 @@ import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.tls.AuthorizationMode;
import com.yahoo.security.tls.policy.AuthorizedPeers;
+import javax.net.ssl.TrustManager;
+import java.security.GeneralSecurityException;
import java.security.KeyStore;
/**
* @author bjorncs
*/
-public class PeerAuthorizerTrustManagersFactory implements SslContextBuilder.TrustManagerFactory {
+public class PeerAuthorizerTrustManagersFactory implements SslContextBuilder.TrustManagersFactory {
private final AuthorizedPeers authorizedPeers;
private AuthorizationMode mode;
@@ -20,7 +22,7 @@ public class PeerAuthorizerTrustManagersFactory implements SslContextBuilder.Tru
}
@Override
- public PeerAuthorizerTrustManager createTrustManager(KeyStore truststore) {
- return new PeerAuthorizerTrustManager(authorizedPeers, mode, truststore);
+ public TrustManager[] createTrustManagers(KeyStore truststore) throws GeneralSecurityException {
+ return PeerAuthorizerTrustManager.wrapTrustManagersFromKeystore(authorizedPeers, mode, truststore);
}
}
diff --git a/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java
deleted file mode 100644
index 139d5313074..00000000000
--- a/security-utils/src/test/java/com/yahoo/security/tls/AutoReloadingX509KeyManagerTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyAlgorithm;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SignatureAlgorithm;
-import com.yahoo.security.X509CertificateBuilder;
-import com.yahoo.security.X509CertificateUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-
-import javax.security.auth.x500.X500Principal;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.KeyPair;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.time.Instant;
-import java.util.concurrent.ScheduledExecutorService;
-
-import static java.time.temporal.ChronoUnit.DAYS;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.verify;
-
-/**
- * @author bjorncs
- */
-public class AutoReloadingX509KeyManagerTest {
- private static final X500Principal SUBJECT = new X500Principal("CN=dummy");
-
- @Rule
- public TemporaryFolder tempDirectory = new TemporaryFolder();
-
- @Test
- public void crypto_material_is_reloaded_when_scheduler_task_is_executed() throws IOException {
- KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC);
- Path privateKeyFile = tempDirectory.newFile().toPath();
- Files.writeString(privateKeyFile, KeyUtils.toPem(keyPair.getPrivate()));
-
- Path certificateFile = tempDirectory.newFile().toPath();
- BigInteger serialNumberInitialCertificate = BigInteger.ONE;
- X509Certificate initialCertificate = generateCertificate(keyPair, serialNumberInitialCertificate);
- Files.writeString(certificateFile, X509CertificateUtils.toPem(initialCertificate));
-
- ScheduledExecutorService scheduler = Mockito.mock(ScheduledExecutorService.class);
- ArgumentCaptor<Runnable> updaterTaskCaptor = ArgumentCaptor.forClass(Runnable.class);
-
- AutoReloadingX509KeyManager keyManager = new AutoReloadingX509KeyManager(privateKeyFile, certificateFile, scheduler);
- verify(scheduler).scheduleAtFixedRate(updaterTaskCaptor.capture(), anyLong(), anyLong(), any());
-
- String[] initialAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT});
- X509Certificate[] certChain = keyManager.getCertificateChain(initialAliases[0]);
- assertThat(certChain).hasSize(1);
- assertThat(certChain[0].getSerialNumber()).isEqualTo(serialNumberInitialCertificate);
-
- BigInteger serialNumberUpdatedCertificate = BigInteger.TWO;
- X509Certificate updatedCertificate = generateCertificate(keyPair, serialNumberUpdatedCertificate);
- Files.writeString(certificateFile, X509CertificateUtils.toPem(updatedCertificate));
-
- updaterTaskCaptor.getValue().run(); // run update task in ReloadingX509KeyManager
-
- String[] updatedAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT});
- X509Certificate[] updatedCertChain = keyManager.getCertificateChain(updatedAliases[0]);
- assertThat(updatedCertChain).hasSize(1);
- assertThat(updatedCertChain[0].getSerialNumber()).isEqualTo(serialNumberUpdatedCertificate);
- }
-
- private static X509Certificate generateCertificate(KeyPair keyPair, BigInteger serialNumber) {
- return X509CertificateBuilder.fromKeypair(keyPair,
- SUBJECT,
- Instant.EPOCH,
- Instant.EPOCH.plus(1, DAYS),
- SignatureAlgorithm.SHA256_WITH_ECDSA,
- serialNumber)
- .build();
- }
-} \ No newline at end of file
diff --git a/security-utils/src/test/java/com/yahoo/security/tls/MutableX509KeyManagerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/MutableX509KeyManagerTest.java
deleted file mode 100644
index 30e54d3c09d..00000000000
--- a/security-utils/src/test/java/com/yahoo/security/tls/MutableX509KeyManagerTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyAlgorithm;
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SignatureAlgorithm;
-import com.yahoo.security.X509CertificateBuilder;
-import org.junit.Test;
-
-import javax.security.auth.x500.X500Principal;
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.KeyStore;
-import java.security.Principal;
-import java.security.cert.X509Certificate;
-import java.time.Instant;
-
-import static java.time.temporal.ChronoUnit.DAYS;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author bjorncs
- */
-public class MutableX509KeyManagerTest {
-
- private static final X500Principal SUBJECT = new X500Principal("CN=dummy");
-
- @Test
- public void key_manager_can_be_updated_with_new_certificate() {
- KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC);
-
- BigInteger serialNumberInitialCertificate = BigInteger.ONE;
- KeyStore initialKeystore = generateKeystore(keyPair, serialNumberInitialCertificate);
-
- MutableX509KeyManager keyManager = new MutableX509KeyManager(initialKeystore, new char[0]);
-
- String[] initialAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT});
- assertThat(initialAliases).hasSize(1);
- X509Certificate[] certChain = keyManager.getCertificateChain(initialAliases[0]);
- assertThat(certChain).hasSize(1);
- assertThat(certChain[0].getSerialNumber()).isEqualTo(serialNumberInitialCertificate);
-
- BigInteger serialNumberUpdatedCertificate = BigInteger.TWO;
- KeyStore updatedKeystore = generateKeystore(keyPair, serialNumberUpdatedCertificate);
- keyManager.updateKeystore(updatedKeystore, new char[0]);
-
- String[] updatedAliases = keyManager.getClientAliases(keyPair.getPublic().getAlgorithm(), new Principal[]{SUBJECT});
- assertThat(updatedAliases).hasSize(1);
- X509Certificate[] updatedCertChain = keyManager.getCertificateChain(updatedAliases[0]);
- assertThat(updatedCertChain).hasSize(1);
- assertThat(updatedCertChain[0].getSerialNumber()).isEqualTo(serialNumberUpdatedCertificate);
- }
-
- private static KeyStore generateKeystore(KeyPair keyPair, BigInteger serialNumber) {
- X509Certificate certificate = X509CertificateBuilder.fromKeypair(
- keyPair, SUBJECT, Instant.EPOCH, Instant.EPOCH.plus(1, DAYS), SignatureAlgorithm.SHA256_WITH_ECDSA, serialNumber)
- .build();
- return KeyStoreBuilder.withType(KeyStoreType.PKCS12)
- .withKeyEntry("default", keyPair.getPrivate(), certificate)
- .build();
- }
-
-} \ No newline at end of file
diff --git a/security-utils/src/test/java/com/yahoo/security/tls/MutableX509TrustManagerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/MutableX509TrustManagerTest.java
deleted file mode 100644
index 4c4ea332818..00000000000
--- a/security-utils/src/test/java/com/yahoo/security/tls/MutableX509TrustManagerTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.security.tls;
-
-import com.yahoo.security.KeyAlgorithm;
-import com.yahoo.security.KeyStoreBuilder;
-import com.yahoo.security.KeyStoreType;
-import com.yahoo.security.KeyUtils;
-import com.yahoo.security.SignatureAlgorithm;
-import com.yahoo.security.X509CertificateBuilder;
-import org.junit.Test;
-
-import javax.security.auth.x500.X500Principal;
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.KeyStore;
-import java.security.cert.X509Certificate;
-import java.time.Instant;
-
-import static java.time.temporal.ChronoUnit.DAYS;
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * @author bjorncs
- */
-public class MutableX509TrustManagerTest {
-
- @Test
- public void key_manager_can_be_updated_with_new_certificate() {
- KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.EC);
-
- X509Certificate initialCertificate = generateCertificate(new X500Principal("CN=issuer1"), keyPair);
- KeyStore initialTruststore = generateTruststore(initialCertificate);
-
- MutableX509TrustManager trustManager = new MutableX509TrustManager(initialTruststore);
-
- X509Certificate[] initialAcceptedIssuers = trustManager.getAcceptedIssuers();
- assertThat(initialAcceptedIssuers).containsExactly(initialCertificate);
-
- X509Certificate updatedCertificate = generateCertificate(new X500Principal("CN=issuer2"), keyPair);
- KeyStore updatedTruststore = generateTruststore(updatedCertificate);
- trustManager.updateTruststore(updatedTruststore);
-
- X509Certificate[] updatedAcceptedIssuers = trustManager.getAcceptedIssuers();
- assertThat(updatedAcceptedIssuers).containsExactly(updatedCertificate);
- }
-
- private static X509Certificate generateCertificate(X500Principal issuer, KeyPair keyPair) {
- return X509CertificateBuilder.fromKeypair(
- keyPair, issuer, Instant.EPOCH, Instant.EPOCH.plus(1, DAYS), SignatureAlgorithm.SHA256_WITH_ECDSA, BigInteger.ONE)
- .build();
- }
-
- private static KeyStore generateTruststore(X509Certificate certificate) {
- return KeyStoreBuilder.withType(KeyStoreType.PKCS12)
- .withCertificateEntry("default", certificate)
- .build();
- }
-
-} \ No newline at end of file