From 9b3ee17b0ec8c844ace83bd7c797d6600ce0b713 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 19 Jul 2023 14:42:19 +0200 Subject: Proper modelling of client auth setting --- .../container/http/ssl/HostedSslConnectorFactory.java | 15 ++++++++------- .../vespa/model/container/xml/ContainerModelBuilder.java | 16 ++++++++++------ 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'config-model/src/main/java/com/yahoo') 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 365d7cd1a34..2b13cd21e99 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 @@ -17,7 +17,7 @@ import java.util.List; */ public class HostedSslConnectorFactory extends ConnectorFactory { - boolean requireTlsClientAuthDuringTlsHandshake; + private final SslClientAuth clientAuth; private final List tlsCiphersOverride; private final boolean proxyProtocolEnabled; private final boolean proxyProtocolMixedMode; @@ -27,7 +27,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory { private HostedSslConnectorFactory(Builder builder) { super(new ConnectorFactory.Builder("tls"+builder.port, builder.port).sslProvider(createSslProvider(builder))); - this.requireTlsClientAuthDuringTlsHandshake = builder.requireTlsClientAuthDuringTlsHandshake; + this.clientAuth = builder.clientAuth; this.tlsCiphersOverride = List.copyOf(builder.tlsCiphersOverride); this.proxyProtocolEnabled = builder.proxyProtocolEnabled; this.proxyProtocolMixedMode = builder.proxyProtocolMixedMode; @@ -36,17 +36,17 @@ public class HostedSslConnectorFactory extends ConnectorFactory { private static SslProvider createSslProvider(Builder builder) { if (builder.endpointCertificate == null) return new DefaultSslProvider(builder.name); - var clientAuthentication = builder.requireTlsClientAuthDuringTlsHandshake + var sslClientAuth = builder.clientAuth == SslClientAuth.NEED ? ConnectorConfig.Ssl.ClientAuth.Enum.NEED_AUTH : ConnectorConfig.Ssl.ClientAuth.Enum.WANT_AUTH; return new CloudSslProvider( builder.name, builder.endpointCertificate.key(), builder.endpointCertificate.certificate(), - builder.tlsCaCertificatesPath, builder.tlsCaCertificatesPem, clientAuthentication, builder.tokenEndpoint); + builder.tlsCaCertificatesPath, builder.tlsCaCertificatesPem, sslClientAuth, builder.tokenEndpoint); } @Override public void getConfig(ConnectorConfig.Builder connectorBuilder) { super.getConfig(connectorBuilder); - if (! requireTlsClientAuthDuringTlsHandshake) { + if (clientAuth == SslClientAuth.WANT_WITH_ENFORCER) { connectorBuilder.tlsClientAuthEnforcer( new ConnectorConfig.TlsClientAuthEnforcer.Builder() .pathWhitelist(List.of("/status.html")).enable(true)); @@ -65,10 +65,11 @@ public class HostedSslConnectorFactory extends ConnectorFactory { .maxConnectionLife(endpointConnectionTtl != null ? endpointConnectionTtl.toSeconds() : 0); } + public enum SslClientAuth { WANT, NEED, WANT_WITH_ENFORCER } public static class Builder { final String name; final int port; - boolean requireTlsClientAuthDuringTlsHandshake; + SslClientAuth clientAuth; List tlsCiphersOverride; boolean proxyProtocolEnabled; boolean proxyProtocolMixedMode; @@ -79,7 +80,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory { boolean tokenEndpoint; private Builder(String name, int port) { this.name = name; this.port = port; } - public Builder requireTlsClientAuthDuringTlsHandshake(boolean enable) {this.requireTlsClientAuthDuringTlsHandshake = enable; return this; } + public Builder clientAuth(SslClientAuth auth) { clientAuth = auth; return this; } public Builder endpointConnectionTtl(Duration ttl) { endpointConnectionTtl = ttl; return this; } public Builder tlsCiphersOverride(Collection ciphers) { tlsCiphersOverride = List.copyOf(ciphers); return this; } public Builder proxyProtocol(boolean enabled, boolean mixedMode) { proxyProtocolEnabled = enabled; proxyProtocolMixedMode = mixedMode; return this; } 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 f9cf2579774..c97ea6671e8 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 @@ -94,6 +94,7 @@ import com.yahoo.vespa.model.container.http.Http; import com.yahoo.vespa.model.container.http.HttpFilterChain; import com.yahoo.vespa.model.container.http.JettyHttpServer; import com.yahoo.vespa.model.container.http.ssl.HostedSslConnectorFactory; +import com.yahoo.vespa.model.container.http.ssl.HostedSslConnectorFactory.SslClientAuth; import com.yahoo.vespa.model.container.http.xml.HttpBuilder; import com.yahoo.vespa.model.container.processing.ProcessingChains; import com.yahoo.vespa.model.container.search.ContainerSearch; @@ -616,15 +617,16 @@ public class ContainerModelBuilder extends ConfigModelBuilder { if (clientCertificates.isEmpty()) throw new IllegalArgumentException("Client certificate authority security/clients.pem is missing - " + "see: https://cloud.vespa.ai/en/security/guide#data-plane"); - builder.tlsCaCertificatesPem(X509CertificateUtils.toPem(clientCertificates)); + builder.tlsCaCertificatesPem(X509CertificateUtils.toPem(clientCertificates)) + .clientAuth(SslClientAuth.WANT_WITH_ENFORCER); } else { builder.tlsCaCertificatesPath("/opt/yahoo/share/ssl/certs/athenz_certificate_bundle.pem"); + var needAuth = cluster.getHttp().getAccessControl() + .map(accessControl -> accessControl.clientAuthentication) + .map(clientAuth -> clientAuth == AccessControl.ClientAuthentication.need) + .orElse(false); + builder.clientAuth(needAuth ? SslClientAuth.NEED : SslClientAuth.WANT); } - builder.requireTlsClientAuthDuringTlsHandshake( - cluster.getHttp().getAccessControl() - .map(accessControl -> accessControl.clientAuthentication) - .map(clientAuth -> clientAuth == AccessControl.ClientAuthentication.need) - .orElse(false)); boolean enableTokenSupport = state.featureFlags().enableDataplaneProxy() && cluster.getClients().stream().anyMatch(c -> !c.tokens().isEmpty()); @@ -641,6 +643,8 @@ public class ContainerModelBuilder extends ConfigModelBuilder { cluster.addComponent(dataplaneProxy); builder.tokenEndpoint(true); } + } else { + builder.clientAuth(SslClientAuth.WANT_WITH_ENFORCER); } var connectorFactory = builder.build(); cluster.getHttp().getAccessControl().ifPresent(accessControl -> accessControl.configureHostedConnector(connectorFactory)); -- cgit v1.2.3