diff options
author | Bjørn Christian Seime <bjorn.christian@seime.no> | 2018-12-06 13:24:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-06 13:24:11 +0100 |
commit | 4b02253d4db532ba6ae93afbd9b236991e60f7f3 (patch) | |
tree | 6116e9e22566e269c6c5d64a07dea8863748f2cf | |
parent | 51d5defd8116fadb68b1a3f9367cdb5c2cb6d845 (diff) | |
parent | e1fba95a8a69d532db2ce4db753a60512c24a98e (diff) |
Merge pull request #7875 from vespa-engine/bjorncs/tls-certificate-validation
Bjorncs/tls certificate validation
11 files changed, 271 insertions, 122 deletions
diff --git a/jrt/src/com/yahoo/jrt/CryptoEngine.java b/jrt/src/com/yahoo/jrt/CryptoEngine.java index e620c8cbd34..cc59c29bc3b 100644 --- a/jrt/src/com/yahoo/jrt/CryptoEngine.java +++ b/jrt/src/com/yahoo/jrt/CryptoEngine.java @@ -2,11 +2,11 @@ package com.yahoo.jrt; -import com.yahoo.security.tls.ConfigFileManagedTlsContext; +import com.yahoo.security.tls.AuthorizationMode; +import com.yahoo.security.tls.MixedMode; +import com.yahoo.security.tls.ReloadingTlsContext; import com.yahoo.security.tls.TlsContext; import com.yahoo.security.tls.TransportSecurityUtils; -import com.yahoo.security.tls.TransportSecurityUtils.MixedMode; -import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager.Mode; import java.nio.channels.SocketChannel; @@ -23,7 +23,8 @@ public interface CryptoEngine extends AutoCloseable { if (!TransportSecurityUtils.isTransportSecurityEnabled()) { return new NullCryptoEngine(); } - TlsContext tlsContext = new ConfigFileManagedTlsContext(TransportSecurityUtils.getConfigFile().get(), Mode.DRY_RUN); + AuthorizationMode mode = TransportSecurityUtils.getInsecureAuthorizationMode().orElse(AuthorizationMode.ENFORCE); + TlsContext tlsContext = new ReloadingTlsContext(TransportSecurityUtils.getConfigFile().get(), mode); TlsCryptoEngine tlsCryptoEngine = new TlsCryptoEngine(tlsContext); if (!TransportSecurityUtils.isInsecureMixedModeEnabled()) { return tlsCryptoEngine; diff --git a/jrt/tests/com/yahoo/jrt/CryptoUtils.java b/jrt/tests/com/yahoo/jrt/CryptoUtils.java index 92c7825f1d5..1c2280567cb 100644 --- a/jrt/tests/com/yahoo/jrt/CryptoUtils.java +++ b/jrt/tests/com/yahoo/jrt/CryptoUtils.java @@ -1,13 +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.jrt; -import com.yahoo.security.KeyStoreBuilder; import com.yahoo.security.KeyUtils; -import com.yahoo.security.SslContextBuilder; import com.yahoo.security.X509CertificateBuilder; +import com.yahoo.security.tls.AuthorizationMode; +import com.yahoo.security.tls.DefaultTlsContext; import com.yahoo.security.tls.TlsContext; -import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager.Mode; -import com.yahoo.security.tls.authz.PeerAuthorizerTrustManagersFactory; import com.yahoo.security.tls.policy.AuthorizedPeers; import com.yahoo.security.tls.policy.HostGlobPattern; import com.yahoo.security.tls.policy.PeerPolicy; @@ -15,16 +13,12 @@ import com.yahoo.security.tls.policy.RequiredPeerCredential; import com.yahoo.security.tls.policy.RequiredPeerCredential.Field; import com.yahoo.security.tls.policy.Role; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; import javax.security.auth.x500.X500Principal; import java.security.KeyPair; -import java.security.KeyStore; import java.security.cert.X509Certificate; import java.time.Instant; import static com.yahoo.security.KeyAlgorithm.RSA; -import static com.yahoo.security.KeyStoreType.PKCS12; import static com.yahoo.security.SignatureAlgorithm.SHA256_WITH_RSA; import static com.yahoo.security.X509CertificateBuilder.generateRandomSerialNumber; import static java.time.Instant.EPOCH; @@ -35,57 +29,27 @@ import static java.util.Collections.singletonList; /** * @author bjorncs */ +// TODO Use EC. Java/JSSE is currently unable to find compatible ciphers when using elliptic curve crypto from BouncyCastle class CryptoUtils { - static final SSLContext testSslContext = createTestSslContext(); - static TlsContext createTestTlsContext() { - return new StaticTlsContext(testSslContext); - } - - // TODO Fix TlsCryptoEngine bug to allow use of EC/ECDSA crypto - static SSLContext createTestSslContext() { - KeyPair keyPair = KeyUtils.generateKeypair(RSA); + static final KeyPair keyPair = KeyUtils.generateKeypair(RSA); - X509Certificate certificate = X509CertificateBuilder - .fromKeypair(keyPair, new X500Principal("CN=dummy"), EPOCH, Instant.now().plus(1, DAYS), SHA256_WITH_RSA, generateRandomSerialNumber()) - .build(); + static final X509Certificate certificate = X509CertificateBuilder + .fromKeypair(keyPair, new X500Principal("CN=dummy"), EPOCH, Instant.now().plus(1, DAYS), SHA256_WITH_RSA, generateRandomSerialNumber()) + .build(); - KeyStore trustStore = KeyStoreBuilder.withType(PKCS12) - .withCertificateEntry("self-signed", certificate) - .build(); - - - return new SslContextBuilder() - .withTrustStore(trustStore) - .withKeyStore(keyPair.getPrivate(), certificate) - .withTrustManagerFactory(new PeerAuthorizerTrustManagersFactory(createAuthorizedPeers(), Mode.ENFORCE)) - .build(); - } + static final AuthorizedPeers authorizedPeers = new AuthorizedPeers( + singleton( + new PeerPolicy( + "dummy-policy", + singleton( + new Role("dummy-role")), + singletonList( + new RequiredPeerCredential( + Field.CN, new HostGlobPattern("dummy")))))); - private static AuthorizedPeers createAuthorizedPeers() { - return new AuthorizedPeers( - singleton( - new PeerPolicy( - "dummy-policy", - singleton( - new Role("dummy-role")), - singletonList( - new RequiredPeerCredential( - Field.CN, new HostGlobPattern("dummy")))))); + static TlsContext createTestTlsContext() { + return new DefaultTlsContext(singletonList(certificate), keyPair.getPrivate(), singletonList(certificate), authorizedPeers, AuthorizationMode.ENFORCE); } - private static class StaticTlsContext implements TlsContext { - - final SSLContext sslContext; - - StaticTlsContext(SSLContext sslContext) { - this.sslContext = sslContext; - } - - @Override - public SSLEngine createSslEngine() { - return sslContext.createSSLEngine(); - } - - } } 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 17d425578ee..09a5a87138f 100644 --- a/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java +++ b/security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java @@ -59,8 +59,12 @@ public class SslContextBuilder { } public SslContextBuilder withKeyStore(PrivateKey privateKey, X509Certificate certificate) { + return withKeyStore(privateKey, singletonList(certificate)); + } + + public SslContextBuilder withKeyStore(PrivateKey privateKey, List<X509Certificate> certificates) { char[] pwd = new char[0]; - this.keyStoreSupplier = () -> KeyStoreBuilder.withType(KeyStoreType.JKS).withKeyEntry("default", privateKey, certificate).build(); + this.keyStoreSupplier = () -> KeyStoreBuilder.withType(KeyStoreType.JKS).withKeyEntry("default", privateKey, certificates).build(); this.keyStorePassword = pwd; return this; } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/AuthorizationMode.java b/security-utils/src/main/java/com/yahoo/security/tls/AuthorizationMode.java new file mode 100644 index 00000000000..141214dc478 --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/tls/AuthorizationMode.java @@ -0,0 +1,30 @@ +// 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 java.util.Arrays; + +/** + * @author bjorncs + */ +public enum AuthorizationMode { + DISABLE("disable"), + LOG_ONLY("log-only"), + ENFORCE("enforce"); + + final String configValue; + + AuthorizationMode(String configValue) { + this.configValue = configValue; + } + + public String configValue() { + return configValue; + } + + static AuthorizationMode fromConfigValue(String configValue) { + return Arrays.stream(values()) + .filter(v -> v.configValue.equals(configValue)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown value: " + configValue)); + } +} 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 new file mode 100644 index 00000000000..f2ae1dd0d38 --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java @@ -0,0 +1,98 @@ +// 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.SslContextBuilder; +import com.yahoo.security.tls.authz.PeerAuthorizerTrustManagersFactory; +import com.yahoo.security.tls.policy.AuthorizedPeers; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import java.nio.file.Path; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A static {@link TlsContext} + * + * @author bjorncs + */ +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"); + + private static final Logger log = Logger.getLogger(DefaultTlsContext.class.getName()); + + private final SSLContext sslContext; + + public DefaultTlsContext(List<X509Certificate> certificates, + PrivateKey privateKey, + List<X509Certificate> caCertificates, + AuthorizedPeers authorizedPeers, + AuthorizationMode mode) { + this.sslContext = createSslContext(certificates, privateKey, caCertificates, authorizedPeers, mode); + } + + public DefaultTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) { + this.sslContext = createSslContext(tlsOptionsConfigFile, mode); + } + + @Override + public SSLEngine createSslEngine() { + SSLEngine sslEngine = sslContext.createSSLEngine(); + restrictSetOfEnabledCiphers(sslEngine); + return sslEngine; + } + + private static void restrictSetOfEnabledCiphers(SSLEngine sslEngine) { + String[] validCipherSuites = Arrays.stream(sslEngine.getSupportedCipherSuites()) + .filter(ALLOWED_CIPHER_SUITES::contains) + .toArray(String[]::new); + if (validCipherSuites.length == 0) { + throw new IllegalStateException("None of the allowed cipher suites are supported"); + } + log.log(Level.FINE, () -> String.format("Allowed cipher suites that are supported: %s", Arrays.toString(validCipherSuites))); + sslEngine.setEnabledCipherSuites(validCipherSuites); + } + + private static SSLContext createSslContext(List<X509Certificate> certificates, + PrivateKey privateKey, + List<X509Certificate> caCertificates, + AuthorizedPeers authorizedPeers, + AuthorizationMode mode) { + SslContextBuilder builder = new SslContextBuilder(); + if (!certificates.isEmpty()) { + builder.withKeyStore(privateKey, certificates); + } + if (!caCertificates.isEmpty()) { + builder.withTrustStore(caCertificates); + } + if (authorizedPeers != null) { + builder.withTrustManagerFactory(new PeerAuthorizerTrustManagersFactory(authorizedPeers, mode)); + } + return builder.build(); + } + + private static SSLContext createSslContext(Path tlsOptionsConfigFile, AuthorizationMode mode) { + TransportSecurityOptions options = TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile); + 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/MixedMode.java b/security-utils/src/main/java/com/yahoo/security/tls/MixedMode.java new file mode 100644 index 00000000000..1365a81cf10 --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/tls/MixedMode.java @@ -0,0 +1,29 @@ +// 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 java.util.Arrays; + +/** + * @author bjorncs + */ +public enum MixedMode { + PLAINTEXT_CLIENT_MIXED_SERVER("plaintext_client_mixed_server"), + TLS_CLIENT_MIXED_SERVER("tls_client_mixed_server"); + + final String configValue; + + MixedMode(String configValue) { + this.configValue = configValue; + } + + public String configValue() { + return configValue; + } + + static MixedMode fromConfigValue(String configValue) { + return Arrays.stream(values()) + .filter(v -> v.configValue.equals(configValue)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown value: " + configValue)); + } +} diff --git a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileManagedTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java index 7c487388e2f..5add13e067d 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileManagedTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java @@ -1,11 +1,6 @@ // 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.SslContextBuilder; -import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager; -import com.yahoo.security.tls.authz.PeerAuthorizerTrustManagersFactory; - -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import java.nio.file.Path; import java.time.Duration; @@ -21,15 +16,15 @@ import java.util.logging.Logger; * * @author bjorncs */ -public class ConfigFileManagedTlsContext implements TlsContext { +public class ReloadingTlsContext implements TlsContext { private static final Duration UPDATE_PERIOD = Duration.ofHours(1); - private static final Logger log = Logger.getLogger(ConfigFileManagedTlsContext.class.getName()); + private static final Logger log = Logger.getLogger(ReloadingTlsContext.class.getName()); private final Path tlsOptionsConfigFile; - private final PeerAuthorizerTrustManager.Mode mode; - private final AtomicReference<SSLContext> currentSslContext; + private final AuthorizationMode mode; + private final AtomicReference<TlsContext> currentTlsContext; private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> { Thread thread = new Thread(runnable, "tls-context-reloader"); @@ -37,30 +32,19 @@ public class ConfigFileManagedTlsContext implements TlsContext { return thread; }); - - public ConfigFileManagedTlsContext(Path tlsOptionsConfigFile, PeerAuthorizerTrustManager.Mode mode) { + public ReloadingTlsContext(Path tlsOptionsConfigFile, AuthorizationMode mode) { this.tlsOptionsConfigFile = tlsOptionsConfigFile; this.mode = mode; - this.currentSslContext = new AtomicReference<>(createSslContext(tlsOptionsConfigFile, mode)); + this.currentTlsContext = new AtomicReference<>(new DefaultTlsContext(tlsOptionsConfigFile, mode)); this.scheduler.scheduleAtFixedRate(new SslContextReloader(), UPDATE_PERIOD.getSeconds()/*initial delay*/, UPDATE_PERIOD.getSeconds(), TimeUnit.SECONDS); } + @Override public SSLEngine createSslEngine() { - return currentSslContext.get().createSSLEngine(); - } - - private static SSLContext createSslContext(Path tlsOptionsConfigFile, PeerAuthorizerTrustManager.Mode mode) { - TransportSecurityOptions options = TransportSecurityOptions.fromJsonFile(tlsOptionsConfigFile); - SslContextBuilder builder = new SslContextBuilder(); - options.getCertificatesFile() - .ifPresent(certificates -> builder.withKeyStore(options.getPrivateKeyFile().get(), certificates)); - options.getCaCertificatesFile().ifPresent(builder::withTrustStore); - options.getAuthorizedPeers().ifPresent( - authorizedPeers -> builder.withTrustManagerFactory(new PeerAuthorizerTrustManagersFactory(authorizedPeers, mode))); - return builder.build(); + return currentTlsContext.get().createSslEngine(); } @Override @@ -77,7 +61,7 @@ public class ConfigFileManagedTlsContext implements TlsContext { @Override public void run() { try { - currentSslContext.set(createSslContext(tlsOptionsConfigFile, mode)); + currentTlsContext.set(new DefaultTlsContext(tlsOptionsConfigFile, mode)); } catch (Throwable 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/TransportSecurityUtils.java b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java index adae2e82873..f07924f3ce9 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 @@ -3,7 +3,6 @@ package com.yahoo.security.tls; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; import java.util.Optional; /** @@ -15,28 +14,7 @@ public class TransportSecurityUtils { public static final String CONFIG_FILE_ENVIRONMENT_VARIABLE = "VESPA_TLS_CONFIG_FILE"; public static final String INSECURE_MIXED_MODE_ENVIRONMENT_VARIABLE = "VESPA_TLS_INSECURE_MIXED_MODE"; - - public enum MixedMode { - PLAINTEXT_CLIENT_MIXED_SERVER("plaintext_client_mixed_server"), - TLS_CLIENT_MIXED_SERVER("tls_client_mixed_server"); - - final String configValue; - - MixedMode(String configValue) { - this.configValue = configValue; - } - - public String configValue() { - return configValue; - } - - static MixedMode fromConfigValue(String configValue) { - return Arrays.stream(values()) - .filter(v -> v.configValue.equals(configValue)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Unknown value: " + configValue)); - } - } + public static final String INSECURE_AUTHORIZATION_MODE_ENVIRONMENT_VARIABLE = "VESPA_TLS_INSECURE_AUTHORIZATION_MODE"; private TransportSecurityUtils() {} @@ -54,6 +32,12 @@ public class TransportSecurityUtils { .map(MixedMode::fromConfigValue); } + public static Optional<AuthorizationMode> getInsecureAuthorizationMode() { + if (!isInsecureMixedModeEnabled()) return Optional.empty(); + return getEnvironmentVariable(INSECURE_AUTHORIZATION_MODE_ENVIRONMENT_VARIABLE) + .map(AuthorizationMode::fromConfigValue); + } + public static Optional<Path> getConfigFile() { return getEnvironmentVariable(CONFIG_FILE_ENVIRONMENT_VARIABLE).map(Paths::get); } 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 aca4f86b639..05524cdffea 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 @@ -2,6 +2,7 @@ package com.yahoo.security.tls.authz; import com.yahoo.security.X509CertificateUtils; +import com.yahoo.security.tls.AuthorizationMode; import com.yahoo.security.tls.policy.AuthorizedPeers; import javax.net.ssl.SSLEngine; @@ -27,25 +28,23 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { private static final Logger log = Logger.getLogger(PeerAuthorizerTrustManager.class.getName()); - public enum Mode { DRY_RUN, ENFORCE } - private final PeerAuthorizer authorizer; private final X509ExtendedTrustManager defaultTrustManager; - private final Mode mode; + private final AuthorizationMode mode; - public PeerAuthorizerTrustManager(AuthorizedPeers authorizedPeers, Mode mode, X509ExtendedTrustManager defaultTrustManager) { + public PeerAuthorizerTrustManager(AuthorizedPeers authorizedPeers, AuthorizationMode mode, X509ExtendedTrustManager defaultTrustManager) { this.authorizer = new PeerAuthorizer(authorizedPeers); this.mode = mode; this.defaultTrustManager = defaultTrustManager; } - public static TrustManager[] wrapTrustManagersFromKeystore(AuthorizedPeers authorizedPeers, Mode mode, KeyStore keystore) throws GeneralSecurityException { + 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, Mode mode, TrustManager[] managers) { + 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) { @@ -99,6 +98,8 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { } private void authorizePeer(X509Certificate certificate, String authType, boolean isVerifyingClient, SSLEngine sslEngine) throws CertificateException { + if (mode == AuthorizationMode.DISABLE) return; + log.fine(() -> "Verifying certificate: " + createInfoString(certificate, authType, isVerifyingClient)); AuthorizationResult result = authorizer.authorizePeer(certificate); if (sslEngine != null) { // getHandshakeSession() will never return null in this context @@ -109,13 +110,8 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { } else { String errorMessage = "Authorization failed: " + createInfoString(certificate, authType, isVerifyingClient); log.warning(errorMessage); - switch (mode) { - case ENFORCE: - throw new CertificateException(errorMessage); - case DRY_RUN: - break; - default: - throw new UnsupportedOperationException(); + if (mode == AuthorizationMode.ENFORCE) { + throw new CertificateException(errorMessage); } } } 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 0bb99aea886..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 @@ -2,6 +2,7 @@ package com.yahoo.security.tls.authz; import com.yahoo.security.SslContextBuilder; +import com.yahoo.security.tls.AuthorizationMode; import com.yahoo.security.tls.policy.AuthorizedPeers; import javax.net.ssl.TrustManager; @@ -13,9 +14,9 @@ import java.security.KeyStore; */ public class PeerAuthorizerTrustManagersFactory implements SslContextBuilder.TrustManagersFactory { private final AuthorizedPeers authorizedPeers; - private PeerAuthorizerTrustManager.Mode mode; + private AuthorizationMode mode; - public PeerAuthorizerTrustManagersFactory(AuthorizedPeers authorizedPeers, PeerAuthorizerTrustManager.Mode mode) { + public PeerAuthorizerTrustManagersFactory(AuthorizedPeers authorizedPeers, AuthorizationMode mode) { this.authorizedPeers = authorizedPeers; this.mode = mode; } diff --git a/security-utils/src/test/java/com/yahoo/security/tls/DefaultTlsContextTest.java b/security-utils/src/test/java/com/yahoo/security/tls/DefaultTlsContextTest.java new file mode 100644 index 00000000000..608ddcd2c1d --- /dev/null +++ b/security-utils/src/test/java/com/yahoo/security/tls/DefaultTlsContextTest.java @@ -0,0 +1,58 @@ +// 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.KeyUtils; +import com.yahoo.security.X509CertificateBuilder; +import com.yahoo.security.tls.policy.AuthorizedPeers; +import com.yahoo.security.tls.policy.HostGlobPattern; +import com.yahoo.security.tls.policy.PeerPolicy; +import com.yahoo.security.tls.policy.RequiredPeerCredential; +import com.yahoo.security.tls.policy.Role; +import org.junit.Test; + +import javax.net.ssl.SSLEngine; +import javax.security.auth.x500.X500Principal; +import java.security.KeyPair; +import java.security.cert.X509Certificate; +import java.time.Instant; + +import static com.yahoo.security.KeyAlgorithm.RSA; +import static com.yahoo.security.SignatureAlgorithm.SHA256_WITH_RSA; +import static com.yahoo.security.X509CertificateBuilder.generateRandomSerialNumber; +import static java.time.Instant.EPOCH; +import static java.time.temporal.ChronoUnit.DAYS; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author bjorncs + */ +public class DefaultTlsContextTest { + + @Test + public void can_create_sslcontext_from_credentials() { + KeyPair keyPair = KeyUtils.generateKeypair(RSA); + + X509Certificate certificate = X509CertificateBuilder + .fromKeypair(keyPair, new X500Principal("CN=dummy"), EPOCH, Instant.now().plus(1, DAYS), SHA256_WITH_RSA, generateRandomSerialNumber()) + .build(); + + AuthorizedPeers authorizedPeers = new AuthorizedPeers( + singleton( + new PeerPolicy( + "dummy-policy", + singleton(new Role("dummy-role")), + singletonList(new RequiredPeerCredential(RequiredPeerCredential.Field.CN, new HostGlobPattern("dummy")))))); + + DefaultTlsContext tlsContext = + new DefaultTlsContext(singletonList(certificate), keyPair.getPrivate(), singletonList(certificate), authorizedPeers, AuthorizationMode.ENFORCE); + + SSLEngine sslEngine = tlsContext.createSslEngine(); + assertThat(sslEngine).isNotNull(); + String[] enabledCiphers = sslEngine.getEnabledCipherSuites(); + assertThat(enabledCiphers).isNotEmpty(); + assertThat(enabledCiphers).isSubsetOf(DefaultTlsContext.ALLOWED_CIPHER_SUITES.toArray(new String[0])); + } + +}
\ No newline at end of file |