diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-07-19 17:35:12 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-07-20 13:56:33 +0200 |
commit | 6276364ef4e626d8eb65ddb0d9e39c7bb114cc0c (patch) | |
tree | 6efb48632c7f8786c7ca71727ffef18f5b8eb2ea /security-utils/src/main/java/com/yahoo/security/tls | |
parent | 91b46555d137dcdf73a534ba5fa10e07510eb0f9 (diff) |
Move generic crypto helpers from 'c.y.s.tls' to 'c.y.s'
Diffstat (limited to 'security-utils/src/main/java/com/yahoo/security/tls')
8 files changed, 3 insertions, 482 deletions
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 259d4b50d3f..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright Yahoo. 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 com.yahoo.security.X509CertificateWithKey; - -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.charset.StandardCharsets; -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.Arrays; -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 { - - public static final String CERTIFICATE_ALIAS = "default"; - - 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); - } - - public X509CertificateWithKey getCurrentCertificateWithKey() { - X509ExtendedKeyManager manager = mutableX509KeyManager.currentManager(); - X509Certificate[] certificateChain = manager.getCertificateChain(CERTIFICATE_ALIAS); - PrivateKey privateKey = manager.getPrivateKey(CERTIFICATE_ALIAS); - return new X509CertificateWithKey(Arrays.asList(certificateChain), privateKey); - } - - private static KeyStore createKeystore(Path privateKey, Path certificateChain) { - try { - return KeyStoreBuilder.withType(KeyStoreType.PKCS12) - .withKeyEntry( - CERTIFICATE_ALIAS, - KeyUtils.fromPemEncodedPrivateKey(new String(Files.readAllBytes(privateKey), StandardCharsets.UTF_8)), - X509CertificateUtils.certificateListFromPem(new String(Files.readAllBytes(certificateChain), StandardCharsets.UTF_8))) - .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/ConfigFileBasedTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java index d89e4631103..69635b92e74 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java @@ -4,6 +4,8 @@ package com.yahoo.security.tls; import com.yahoo.security.KeyStoreBuilder; import com.yahoo.security.KeyStoreType; import com.yahoo.security.KeyUtils; +import com.yahoo.security.MutableX509KeyManager; +import com.yahoo.security.MutableX509TrustManager; import com.yahoo.security.SslContextBuilder; import com.yahoo.security.X509CertificateUtils; 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 c9216d7273c..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/KeyManagerUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Yahoo. 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 " + Arrays.asList(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 6d784efc3e8..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509KeyManager.java +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright Yahoo. 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 { - - private final Object monitor = new Object(); - // Not using ThreadLocal as we want the thread local x509 key manager instances to be garbage 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 X509ExtendedKeyManager currentManager; - - public MutableX509KeyManager(KeyStore keystore, char[] password) { - synchronized (monitor) { - this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(keystore, password); - } - } - - public MutableX509KeyManager() { - synchronized (monitor) { - this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(); - } - } - - public void updateKeystore(KeyStore keystore, char[] password) { - synchronized (monitor) { - this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(keystore, password); - } - } - - public void useDefaultKeystore() { - synchronized (monitor) { - this.currentManager = KeyManagerUtils.createDefaultX509KeyManager(); - } - } - - public X509ExtendedKeyManager currentManager() { - synchronized (monitor) { - return currentManager; - } - } - - @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() { - synchronized (monitor) { - X509ExtendedKeyManager currentManager = this.currentManager; - threadLocalManager.put(Thread.currentThread(), currentManager); - return currentManager; - } - } - - @Override - public X509Certificate[] getCertificateChain(String alias) { - if (alias == null) return null; // this method can be called with 'null' alias prior to any alias getter methods. - return getThreadLocalManager() - .getCertificateChain(alias); - } - - @Override - public PrivateKey getPrivateKey(String alias) { - if (alias == null) return null; // this method can be called with 'null' alias prior to any alias getter methods. - return getThreadLocalManager() - .getPrivateKey(alias); - } - - private X509ExtendedKeyManager getThreadLocalManager() { - synchronized (monitor) { - 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 6db43ef94a9..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/MutableX509TrustManager.java +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright Yahoo. 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/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthorizerTrustManager.java index 8e7dd039081..089023e55f1 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthorizerTrustManager.java @@ -1,6 +1,7 @@ // Copyright Yahoo. 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.TrustManagerUtils; import com.yahoo.security.X509CertificateUtils; import javax.net.ssl.SSLEngine; diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TrustAllX509TrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/TrustAllX509TrustManager.java deleted file mode 100644 index b0303620cf7..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/TrustAllX509TrustManager.java +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright Yahoo. 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.cert.X509Certificate; - -/** - * A {@link X509ExtendedTrustManager} that accepts all server certificates. - * - * @author bjorncs - */ -public class TrustAllX509TrustManager extends X509ExtendedTrustManager { - @Override public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) { failWhenUsedOnServer(); } - @Override public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { failWhenUsedOnServer(); } - @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { failWhenUsedOnServer(); } - - @Override public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) {} - @Override public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {} - @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} - @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } - - private static void failWhenUsedOnServer() { - throw new IllegalStateException("TrustAllX509TrustManager cannot be used on server, only client"); - } -} 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 4172e337789..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/TrustManagerUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright Yahoo. 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 " + Arrays.asList(trustManagers))); - } catch (GeneralSecurityException e) { - throw new RuntimeException(e); - } - } - - public static X509ExtendedTrustManager createDefaultX509TrustManager(List<X509Certificate> certificates) { - return createDefaultX509TrustManager( - KeyStoreBuilder.withType(KeyStoreType.PKCS12) - .withCertificateEntries("cert", certificates) - .build()); - } - - public static X509ExtendedTrustManager createDefaultX509TrustManager() { - return createDefaultX509TrustManager((KeyStore) null); - } -} |