diff options
Diffstat (limited to 'security-utils/src/main/java/com')
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java | 15 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java | 4 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java (renamed from security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java) | 17 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java | 47 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/PeerAuthentication.java | 9 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/TlsContext.java | 14 | ||||
-rw-r--r-- | security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java | 2 |
7 files changed, 78 insertions, 30 deletions
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 0ef179f775e..4f8919cdd5e 100644 --- a/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java +++ b/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java @@ -33,6 +33,7 @@ public class SslContextBuilder { private char[] keyStorePassword; private TrustManagerFactory trustManagerFactory = TrustManagerUtils::createDefaultX509TrustManager; private KeyManagerFactory keyManagerFactory = KeyManagerUtils::createDefaultX509KeyManager; + private X509ExtendedKeyManager keyManager; public SslContextBuilder() {} @@ -110,11 +111,23 @@ public class SslContextBuilder { return this; } + /** + * Note: Callee is responsible for configuring the key manager. + * Any keystore configured by {@link #withKeyStore(KeyStore, char[])} or the other overloads will be ignored. + */ + public SslContextBuilder withKeyManager(X509ExtendedKeyManager keyManager) { + this.keyManager = keyManager; + 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) }; + X509ExtendedKeyManager keyManager = this.keyManager != null + ? this.keyManager + : keyManagerFactory.createKeyManager(keyStoreSupplier.get(), keyStorePassword); + KeyManager[] keyManagers = new KeyManager[] {keyManager}; sslContext.init(keyManagers, trustManagers, null); return sslContext; } catch (GeneralSecurityException e) { 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 index 0dae185995c..faf6ecb4348 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/AutoReloadingX509KeyManager.java @@ -31,6 +31,8 @@ import java.util.logging.Logger; */ 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()); @@ -61,7 +63,7 @@ public class AutoReloadingX509KeyManager extends X509ExtendedKeyManager implemen try { return KeyStoreBuilder.withType(KeyStoreType.PKCS12) .withKeyEntry( - "default", + CERTIFICATE_ALIAS, KeyUtils.fromPemEncodedPrivateKey(Files.readString(privateKey)), X509CertificateUtils.certificateListFromPem(Files.readString(certificateChain))) .build(); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java index 16f66f91da6..3b9158cf9b1 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java @@ -20,6 +20,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyStore; import java.time.Duration; +import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -29,20 +31,21 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * A {@link TlsContext} that regularly reloads the credentials referred to from the transport security options file. + * A {@link TlsContext} that uses the tls configuration specified in the transport security options file. + * The credentials are regularly reloaded to support short-lived certificates. * * @author bjorncs */ -public class ReloadingTlsContext implements TlsContext { +public class ConfigFileBasedTlsContext implements TlsContext { private static final Duration UPDATE_PERIOD = Duration.ofHours(1); - private static final Logger log = Logger.getLogger(ReloadingTlsContext.class.getName()); + private static final Logger log = Logger.getLogger(ConfigFileBasedTlsContext.class.getName()); private final TlsContext tlsContext; private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ReloaderThreadFactory()); - public ReloadingTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) { + public ConfigFileBasedTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) { TransportSecurityOptions options = TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile); MutableX509TrustManager trustManager = new MutableX509TrustManager(); MutableX509KeyManager keyManager = new MutableX509KeyManager(); @@ -99,13 +102,15 @@ public class ReloadingTlsContext implements TlsContext { MutableX509TrustManager mutableTrustManager, MutableX509KeyManager mutableKeyManager) { SSLContext sslContext = new SslContextBuilder() - .withKeyManagerFactory((ignoredKeystore, ignoredPassword) -> mutableKeyManager) + .withKeyManager(mutableKeyManager) .withTrustManagerFactory( ignoredTruststore -> options.getAuthorizedPeers() .map(authorizedPeers -> (X509ExtendedTrustManager) new PeerAuthorizerTrustManager(authorizedPeers, mode, mutableTrustManager)) .orElseGet(() -> new PeerAuthorizerTrustManager(new AuthorizedPeers(Set.of()), AuthorizationMode.DISABLE, mutableTrustManager))) .build(); - return new DefaultTlsContext(sslContext, options.getAcceptedCiphers()); + List<String> acceptedCiphers = options.getAcceptedCiphers(); + Set<String> ciphers = acceptedCiphers.isEmpty() ? TlsContext.ALLOWED_CIPHER_SUITES : new HashSet<>(acceptedCiphers); + return new DefaultTlsContext(sslContext, ciphers, PeerAuthentication.NEED); } // Wrapped methods from TlsContext 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 e74ad49b2f5..572461c6cdd 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 @@ -23,47 +23,41 @@ import java.util.logging.Logger; */ public class DefaultTlsContext implements TlsContext { - public static final List<String> ALLOWED_CIPHER_SUITES = Arrays.asList( - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_AES_128_GCM_SHA256", // TLSv1.3 - "TLS_AES_256_GCM_SHA384", // TLSv1.3 - "TLS_CHACHA20_POLY1305_SHA256"); // TLSv1.3 - - public static final List<String> ALLOWED_PROTOCOLS = List.of("TLSv1.2"); // TODO Enable TLSv1.3 - private static final Logger log = Logger.getLogger(DefaultTlsContext.class.getName()); private final SSLContext sslContext; private final String[] validCiphers; private final String[] validProtocols; + private final PeerAuthentication peerAuthentication; public DefaultTlsContext(List<X509Certificate> certificates, PrivateKey privateKey, List<X509Certificate> caCertificates, AuthorizedPeers authorizedPeers, AuthorizationMode mode, - List<String> acceptedCiphers) { - this(createSslContext(certificates, privateKey, caCertificates, authorizedPeers, mode), - acceptedCiphers); + PeerAuthentication peerAuthentication) { + this(createSslContext(certificates, privateKey, caCertificates, authorizedPeers, mode), peerAuthentication); + } + + public DefaultTlsContext(SSLContext sslContext, PeerAuthentication peerAuthentication) { + this(sslContext, TlsContext.ALLOWED_CIPHER_SUITES, peerAuthentication); } + public DefaultTlsContext(SSLContext sslContext) { + this(sslContext, TlsContext.ALLOWED_CIPHER_SUITES, PeerAuthentication.NEED); + } - public DefaultTlsContext(SSLContext sslContext, List<String> acceptedCiphers) { + DefaultTlsContext(SSLContext sslContext, Set<String> acceptedCiphers, PeerAuthentication peerAuthentication) { this.sslContext = sslContext; + this.peerAuthentication = peerAuthentication; this.validCiphers = getAllowedCiphers(sslContext, acceptedCiphers); this.validProtocols = getAllowedProtocols(sslContext); } - - private static String[] getAllowedCiphers(SSLContext sslContext, List<String> acceptedCiphers) { + private static String[] getAllowedCiphers(SSLContext sslContext, Set<String> acceptedCiphers) { String[] supportedCipherSuites = sslContext.getSupportedSSLParameters().getCipherSuites(); String[] validCipherSuites = Arrays.stream(supportedCipherSuites) - .filter(suite -> ALLOWED_CIPHER_SUITES.contains(suite) && (acceptedCiphers.isEmpty() || acceptedCiphers.contains(suite))) + .filter(suite -> ALLOWED_CIPHER_SUITES.contains(suite) && acceptedCiphers.contains(suite)) .toArray(String[]::new); if (validCipherSuites.length == 0) { throw new IllegalStateException( @@ -117,7 +111,18 @@ public class DefaultTlsContext implements TlsContext { SSLParameters newParameters = sslContext.getDefaultSSLParameters(); newParameters.setCipherSuites(validCiphers); newParameters.setProtocols(validProtocols); - newParameters.setNeedClientAuth(true); + switch (peerAuthentication) { + case WANT: + newParameters.setWantClientAuth(true); + break; + case NEED: + newParameters.setNeedClientAuth(true); + break; + case DISABLED: + break; + default: + throw new UnsupportedOperationException("Unknown peer authentication: " + peerAuthentication); + } return newParameters; } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthentication.java b/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthentication.java new file mode 100644 index 00000000000..9aa7b642b4a --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/tls/PeerAuthentication.java @@ -0,0 +1,9 @@ +// 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; + +/** + * @author bjorncs + */ +public enum PeerAuthentication { + WANT, NEED, DISABLED +} 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..ea26be0ef4f 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 @@ -4,6 +4,7 @@ package com.yahoo.security.tls; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; +import java.util.Set; /** * A simplified version of {@link SSLContext} modelled as an interface. @@ -12,6 +13,19 @@ import javax.net.ssl.SSLParameters; */ public interface TlsContext extends AutoCloseable { + Set<String> ALLOWED_CIPHER_SUITES = Set.of( + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_AES_128_GCM_SHA256", // TLSv1.3 + "TLS_AES_256_GCM_SHA384", // TLSv1.3 + "TLS_CHACHA20_POLY1305_SHA256"); // TLSv1.3 + + Set<String> ALLOWED_PROTOCOLS = Set.of("TLSv1.2"); // TODO Enable TLSv1.3 + SSLContext context(); SSLParameters parameters(); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java index a4e508e0d2a..f28cad2a071 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java @@ -66,7 +66,7 @@ public class TransportSecurityUtils { public static Optional<TlsContext> createTlsContext() { return getConfigFile() - .map(configFile -> new ReloadingTlsContext(configFile, getInsecureAuthorizationMode())); + .map(configFile -> new ConfigFileBasedTlsContext(configFile, getInsecureAuthorizationMode())); } private static Optional<String> getEnvironmentVariable(Map<String, String> environmentVariables, String variableName) { |