aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2018-12-06 13:24:11 +0100
committerGitHub <noreply@github.com>2018-12-06 13:24:11 +0100
commit4b02253d4db532ba6ae93afbd9b236991e60f7f3 (patch)
tree6116e9e22566e269c6c5d64a07dea8863748f2cf
parent51d5defd8116fadb68b1a3f9367cdb5c2cb6d845 (diff)
parente1fba95a8a69d532db2ce4db753a60512c24a98e (diff)
Merge pull request #7875 from vespa-engine/bjorncs/tls-certificate-validation
Bjorncs/tls certificate validation
-rw-r--r--jrt/src/com/yahoo/jrt/CryptoEngine.java9
-rw-r--r--jrt/tests/com/yahoo/jrt/CryptoUtils.java72
-rw-r--r--security-utils/src/main/java/com/yahoo/security/SslContextBuilder.java6
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/AuthorizationMode.java30
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java98
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/MixedMode.java29
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/ReloadingTlsContext.java (renamed from security-utils/src/main/java/com/yahoo/security/tls/ConfigFileManagedTlsContext.java)34
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityUtils.java30
-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.java5
-rw-r--r--security-utils/src/test/java/com/yahoo/security/tls/DefaultTlsContextTest.java58
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