summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2021-06-23 09:00:26 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2021-06-23 09:00:26 +0200
commit107dc321de5172aebfbb63a16f0aff28c0f26747 (patch)
treed233860af233eb6c92aa525a8ca6961048a56d4f
parent79831782255e2b362c9d650ec5c7c8398b2a4eff (diff)
Add feature flag for overriding TLS ciphers
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java32
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java10
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java5
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java7
5 files changed, 42 insertions, 14 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
index 81ee0a4c4c3..07785eb3391 100644
--- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
+++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java
@@ -141,6 +141,8 @@ public interface ModelContext {
default boolean allowDisableMtls() { return true; }
default List<X509Certificate> operatorCertificates() { return List.of(); }
+
+ default List<String> tlsCiphersOverride() { return List.of(); }
}
@Retention(RetentionPolicy.RUNTIME)
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
index 766aa46fc01..89f200698fa 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
@@ -8,6 +8,7 @@ import com.yahoo.security.tls.TlsContext;
import com.yahoo.vespa.model.container.http.ConnectorFactory;
import java.time.Duration;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -24,39 +25,43 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
private final boolean enforceClientAuth;
private final boolean enforceHandshakeClientAuth;
+ private final Collection<String> tlsCiphersOverride;
/**
* Create connector factory that uses a certificate provided by the config-model / configserver and default hosted Vespa truststore.
*/
public static HostedSslConnectorFactory withProvidedCertificate(
- String serverName, EndpointCertificateSecrets endpointCertificateSecrets, boolean enforceHandshakeClientAuth) {
+ String serverName, EndpointCertificateSecrets endpointCertificateSecrets, boolean enforceHandshakeClientAuth,
+ Collection<String> tlsCiphersOverride) {
ConfiguredDirectSslProvider sslProvider = createConfiguredDirectSslProvider(
serverName, endpointCertificateSecrets, DEFAULT_HOSTED_TRUSTSTORE, /*tlsCaCertificates*/null, enforceHandshakeClientAuth);
- return new HostedSslConnectorFactory(sslProvider, false, enforceHandshakeClientAuth);
+ return new HostedSslConnectorFactory(sslProvider, false, enforceHandshakeClientAuth, tlsCiphersOverride);
}
/**
* Create connector factory that uses a certificate provided by the config-model / configserver and a truststore configured by the application.
*/
public static HostedSslConnectorFactory withProvidedCertificateAndTruststore(
- String serverName, EndpointCertificateSecrets endpointCertificateSecrets, String tlsCaCertificates) {
+ String serverName, EndpointCertificateSecrets endpointCertificateSecrets, String tlsCaCertificates,
+ Collection<String> tlsCiphersOverride) {
ConfiguredDirectSslProvider sslProvider = createConfiguredDirectSslProvider(
serverName, endpointCertificateSecrets, /*tlsCaCertificatesPath*/null, tlsCaCertificates, false);
- return new HostedSslConnectorFactory(sslProvider, true, false);
+ return new HostedSslConnectorFactory(sslProvider, true, false, tlsCiphersOverride);
}
/**
* Create connector factory that uses the default certificate and truststore provided by Vespa (through Vespa-global TLS configuration).
*/
- public static HostedSslConnectorFactory withDefaultCertificateAndTruststore(String serverName) {
- return new HostedSslConnectorFactory(new DefaultSslProvider(serverName), true, false);
+ public static HostedSslConnectorFactory withDefaultCertificateAndTruststore(String serverName, Collection<String> tlsCiphersOverride) {
+ return new HostedSslConnectorFactory(new DefaultSslProvider(serverName), true, false, tlsCiphersOverride);
}
private HostedSslConnectorFactory(SslProvider sslProvider, boolean enforceClientAuth,
- boolean enforceHandshakeClientAuth) {
+ boolean enforceHandshakeClientAuth, Collection<String> tlsCiphersOverride) {
super(new Builder("tls4443", 4443).sslProvider(sslProvider));
this.enforceClientAuth = enforceClientAuth;
this.enforceHandshakeClientAuth = enforceHandshakeClientAuth;
+ this.tlsCiphersOverride = tlsCiphersOverride;
}
private static ConfiguredDirectSslProvider createConfiguredDirectSslProvider(
@@ -83,10 +88,15 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
// Disables TLSv1.3 as it causes some browsers to prompt user for client certificate (when connector has 'want' auth)
connectorBuilder.ssl.enabledProtocols(List.of("TLSv1.2"));
- // Add TLS_RSA_WITH_AES_256_GCM_SHA384 cipher to list of defalt allowed ciphers
- Set<String> ciphers = new HashSet<>(TlsContext.ALLOWED_CIPHER_SUITES);
- ciphers.add("TLS_RSA_WITH_AES_256_GCM_SHA384");
- connectorBuilder.ssl.enabledCipherSuites(Set.copyOf(ciphers));
+ if (!tlsCiphersOverride.isEmpty()) {
+ connectorBuilder.ssl.enabledCipherSuites(tlsCiphersOverride);
+ } else {
+ // Add TLS_RSA_WITH_AES_256_GCM_SHA384 cipher to list of default allowed ciphers
+ // TODO Remove TLS_RSA_WITH_AES_256_GCM_SHA384 as it's weak and incompatible with HTTP/2
+ Set<String> ciphers = new HashSet<>(TlsContext.ALLOWED_CIPHER_SUITES);
+ ciphers.add("TLS_RSA_WITH_AES_256_GCM_SHA384");
+ connectorBuilder.ssl.enabledCipherSuites(Set.copyOf(ciphers));
+ }
connectorBuilder
.proxyProtocol(new ConnectorConfig.ProxyProtocol.Builder().enabled(true).mixedMode(true))
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index 08ccfe33cd5..3ca67a16b66 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -92,6 +92,7 @@ import org.w3c.dom.Node;
import java.net.URI;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -434,6 +435,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
// If the deployment contains certificate/private key reference, setup TLS port
HostedSslConnectorFactory connectorFactory;
boolean enableHttp2 = deployState.featureFlags().enableJdiscHttp2();
+ Collection<String> tlsCiphersOverride = deployState.getProperties().tlsCiphersOverride();
if (deployState.endpointCertificateSecrets().isPresent()) {
boolean authorizeClient = deployState.zone().system().isPublic();
if (authorizeClient && deployState.tlsClientAuthority().isEmpty()) {
@@ -447,10 +449,12 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
.orElse(false);
connectorFactory = authorizeClient
- ? HostedSslConnectorFactory.withProvidedCertificateAndTruststore(serverName, endpointCertificateSecrets, getTlsClientAuthorities(deployState))
- : HostedSslConnectorFactory.withProvidedCertificate(serverName, endpointCertificateSecrets, enforceHandshakeClientAuth);
+ ? HostedSslConnectorFactory.withProvidedCertificateAndTruststore(
+ serverName, endpointCertificateSecrets, getTlsClientAuthorities(deployState), tlsCiphersOverride)
+ : HostedSslConnectorFactory.withProvidedCertificate(
+ serverName, endpointCertificateSecrets, enforceHandshakeClientAuth, tlsCiphersOverride);
} else {
- connectorFactory = HostedSslConnectorFactory.withDefaultCertificateAndTruststore(serverName);
+ connectorFactory = HostedSslConnectorFactory.withDefaultCertificateAndTruststore(serverName, tlsCiphersOverride);
}
cluster.getHttp().getAccessControl().ifPresent(accessControl -> accessControl.configureHostedConnector(connectorFactory));
server.addConnector(connectorFactory);
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
index 94cfba12453..4fa221f3910 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java
@@ -298,6 +298,7 @@ public class ModelContextImpl implements ModelContext {
private final StringFlag jvmGCOptionsFlag;
private final boolean allowDisableMtls;
private final List<X509Certificate> operatorCertificates;
+ private final List<String> tlsCiphersOverride;
public Properties(ApplicationId applicationId,
ConfigserverConfig configserverConfig,
@@ -336,6 +337,8 @@ public class ModelContextImpl implements ModelContext {
this.allowDisableMtls = PermanentFlags.ALLOW_DISABLE_MTLS.bindTo(flagSource)
.with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
this.operatorCertificates = operatorCertificates;
+ this.tlsCiphersOverride = PermanentFlags.TLS_CIPHERS_OVERRIDE.bindTo(flagSource)
+ .with(FetchVector.Dimension.APPLICATION_ID, applicationId.serializedForm()).value();
}
@Override public ModelContext.FeatureFlags featureFlags() { return featureFlags; }
@@ -409,6 +412,8 @@ public class ModelContextImpl implements ModelContext {
return operatorCertificates;
}
+ @Override public List<String> tlsCiphersOverride() { return tlsCiphersOverride; }
+
public String flagValueForClusterType(StringFlag flag, Optional<ClusterSpec.Type> clusterType) {
return clusterType.map(type -> flag.with(CLUSTER_TYPE, type.name()))
.orElse(flag)
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
index 1b7f0c034a3..511f45a91ab 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
@@ -170,6 +170,13 @@ public class PermanentFlags {
TENANT_ID
);
+ public static final UnboundListFlag<String> TLS_CIPHERS_OVERRIDE = defineListFlag(
+ "tls-ciphers-override", List.of(), String.class,
+ "Override TLS ciphers enabled for port 4443 on hosted application containers",
+ "Takes effect on redeployment",
+ APPLICATION_ID
+ );
+
private PermanentFlags() {}
private static UnboundBooleanFlag defineFeatureFlag(