summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOla Aunronning <olaa@yahooinc.com>2023-05-19 11:06:30 +0200
committerOla Aunronning <olaa@yahooinc.com>2023-05-19 11:06:30 +0200
commita89a6d9269fcdb23d907c92bb348c7a3655f9cae (patch)
tree93a6989e096e06aec3adb94df577c7f8f4b9f2eb
parent2853860a3c0b8884668b4d76ad90db50228b52cd (diff)
Add dataplane proxy in config model
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/DataplaneProxy.java52
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java47
-rw-r--r--configdefinitions/src/vespa/CMakeLists.txt2
-rw-r--r--configdefinitions/src/vespa/dataplane-proxy.def4
4 files changed, 97 insertions, 8 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/DataplaneProxy.java b/config-model/src/main/java/com/yahoo/vespa/model/container/DataplaneProxy.java
new file mode 100644
index 00000000000..a4fc7a59d5a
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/DataplaneProxy.java
@@ -0,0 +1,52 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.container;
+
+import com.yahoo.cloud.config.DataplaneProxyConfig;
+import com.yahoo.config.model.producer.TreeConfigProducer;
+import com.yahoo.vespa.model.AbstractService;
+import com.yahoo.vespa.model.PortAllocBridge;
+
+import java.util.Optional;
+
+public class DataplaneProxy extends AbstractService implements DataplaneProxyConfig.Producer {
+
+ private final Integer port;
+
+ public DataplaneProxy(TreeConfigProducer<? super DataplaneProxy> parent, Integer port) {
+ super(parent, "dataplane-proxy");
+ this.port = port;
+ setProp("clustertype", "hosts");
+ setProp("clustername", "admin");
+ }
+
+
+ // Does not need any ports.
+ @Override
+ public void allocatePorts(int start, PortAllocBridge from) { }
+
+ /**
+ *
+ * @return The number of ports reserved
+ */
+ public int getPortCount() { return 0; }
+
+ /**
+ * @return The command used to start
+ */
+ @Override
+ public Optional<String> getStartupCommand() { return Optional.of("exec $ROOT/bin/vespa-dataplane-proxy-start -c " + getConfigId()); }
+
+ @Override
+ public void getConfig(DataplaneProxyConfig.Builder builder) {
+ builder.port(port);
+ }
+
+ @Override
+ public Optional<String> getPreShutdownCommand() {
+ var builder = new DataplaneProxyConfig.Builder();
+ getConfig(builder);
+ String cmd = "$ROOT/bin/vespa-dataplane-proxy-start -S -c " + getConfigId();
+ return Optional.of(cmd);
+ }
+
+}
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 3cb0731c43a..c8bd661a00b 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
@@ -67,6 +67,7 @@ import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.container.ContainerModel;
import com.yahoo.vespa.model.container.ContainerModelEvaluation;
import com.yahoo.vespa.model.container.ContainerThreadpool;
+import com.yahoo.vespa.model.container.DataplaneProxy;
import com.yahoo.vespa.model.container.IdentityProvider;
import com.yahoo.vespa.model.container.PlatformBundles;
import com.yahoo.vespa.model.container.SecretStore;
@@ -459,19 +460,21 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
addDefaultConnectorHostedFilterBinding(cluster);
addAdditionalHostedConnector(deployState, cluster);
addCloudDataPlaneFilter(deployState, cluster);
+ addDataplaneProxy(deployState, cluster);
}
}
private static void addCloudDataPlaneFilter(DeployState deployState, ApplicationContainerCluster cluster) {
if (!deployState.isHosted() || !deployState.zone().system().isPublic()) return;
+ var dataplanePort = getDataplanePort(deployState);
// Setup secure filter chain
var secureChain = new HttpFilterChain("cloud-data-plane-secure", HttpFilterChain.Type.SYSTEM);
secureChain.addInnerComponent(new CloudDataPlaneFilter(cluster, cluster.clientsLegacyMode()));
cluster.getHttp().getFilterChains().add(secureChain);
// Set cloud data plane filter as default request filter chain for data plane connector
cluster.getHttp().getHttpServer().orElseThrow().getConnectorFactories().stream()
- .filter(c -> c.getListenPort() == HOSTED_VESPA_DATAPLANE_PORT).findAny().orElseThrow()
+ .filter(c -> c.getListenPort() == dataplanePort).findAny().orElseThrow()
.setDefaultRequestFilterChain(secureChain.getComponentId());
// Setup insecure filter chain
@@ -494,6 +497,28 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
}
+ private void addDataplaneProxy(DeployState deployState, ApplicationContainerCluster cluster) {
+ if (!deployState.featureFlags().enableDataplaneProxy())
+ return;
+
+ var tokenChain = new HttpFilterChain("cloud-data-plane-token", HttpFilterChain.Type.SYSTEM);
+ tokenChain.addInnerComponent(new Filter(
+ new ChainedComponentModel(
+ new BundleInstantiationSpecification(
+ new ComponentSpecification("com.yahoo.jdisc.http.filter.security.misc.BlockingRequestFilter"),
+ null, new ComponentSpecification("jdisc-security-filters")),
+ Dependencies.emptyDependencies())));
+
+ cluster.getHttp().getFilterChains().add(tokenChain);
+
+ cluster.getContainers().forEach(container -> {
+ var hostResource = container.getHostResource();
+ var dataplaneProxy = new DataplaneProxy(hostResource.getHost(), getDataplanePort(deployState));
+ dataplaneProxy.setHostResource(hostResource);
+ dataplaneProxy.initService(deployState);
+ });
+ }
+
protected void addClients(DeployState deployState, Element spec, ApplicationContainerCluster cluster) {
if (!deployState.isHosted() || !deployState.zone().system().isPublic()) return;
@@ -566,6 +591,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
Collection<String> tlsCiphersOverride = deployState.getProperties().tlsCiphersOverride();
boolean proxyProtocolMixedMode = deployState.getProperties().featureFlags().enableProxyProtocolMixedMode();
Duration endpointConnectionTtl = deployState.getProperties().endpointConnectionTtl();
+ var port = getDataplanePort(deployState);
if (deployState.endpointCertificateSecrets().isPresent()) {
boolean authorizeClient = deployState.zone().system().isPublic();
List<X509Certificate> clientCertificates = getClientCertificates(cluster);
@@ -583,13 +609,13 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
connectorFactory = authorizeClient
? HostedSslConnectorFactory.withProvidedCertificateAndTruststore(
serverName, endpointCertificateSecrets, X509CertificateUtils.toPem(clientCertificates),
- tlsCiphersOverride, proxyProtocolMixedMode, HOSTED_VESPA_DATAPLANE_PORT, endpointConnectionTtl)
+ tlsCiphersOverride, proxyProtocolMixedMode, port, endpointConnectionTtl)
: HostedSslConnectorFactory.withProvidedCertificate(
serverName, endpointCertificateSecrets, enforceHandshakeClientAuth, tlsCiphersOverride,
- proxyProtocolMixedMode, HOSTED_VESPA_DATAPLANE_PORT, endpointConnectionTtl);
+ proxyProtocolMixedMode, port, endpointConnectionTtl);
} else {
connectorFactory = HostedSslConnectorFactory.withDefaultCertificateAndTruststore(
- serverName, tlsCiphersOverride, proxyProtocolMixedMode, HOSTED_VESPA_DATAPLANE_PORT,
+ serverName, tlsCiphersOverride, proxyProtocolMixedMode, port,
endpointConnectionTtl);
}
cluster.getHttp().getAccessControl().ifPresent(accessControl -> accessControl.configureHostedConnector(connectorFactory));
@@ -755,7 +781,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
}
private void addUserHandlers(DeployState deployState, ApplicationContainerCluster cluster, Element spec, ConfigModelContext context) {
- OptionalInt portBindingOverride = isHostedTenantApplication(context) ? OptionalInt.of(HOSTED_VESPA_DATAPLANE_PORT) : OptionalInt.empty();
+ OptionalInt portBindingOverride = isHostedTenantApplication(context) ? OptionalInt.of(getDataplanePort(deployState)) : OptionalInt.empty();
for (Element component: XML.getChildren(spec, "handler")) {
cluster.addComponent(
new DomHandlerBuilder(cluster, portBindingOverride).build(deployState, cluster, component));
@@ -1047,7 +1073,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
private void addSearchHandler(DeployState deployState, ApplicationContainerCluster cluster, Element searchElement, ConfigModelContext context) {
BindingPattern bindingPattern = SearchHandler.DEFAULT_BINDING;
if (isHostedTenantApplication(context) && deployState.featureFlags().useRestrictedDataPlaneBindings()) {
- bindingPattern = SearchHandler.bindingPattern(Optional.of(Integer.toString(HOSTED_VESPA_DATAPLANE_PORT)));
+ bindingPattern = SearchHandler.bindingPattern(Optional.of(Integer.toString(getDataplanePort(deployState))));
}
SearchHandler searchHandler = new SearchHandler(cluster,
serverBindings(deployState, context, searchElement, bindingPattern),
@@ -1068,7 +1094,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
private List<BindingPattern> toBindingList(DeployState deployState, ConfigModelContext context, List<Element> bindingElements) {
List<BindingPattern> result = new ArrayList<>();
- OptionalInt portOverride = isHostedTenantApplication(context) && deployState.featureFlags().useRestrictedDataPlaneBindings() ? OptionalInt.of(HOSTED_VESPA_DATAPLANE_PORT) : OptionalInt.empty();
+ OptionalInt portOverride = isHostedTenantApplication(context) && deployState.featureFlags().useRestrictedDataPlaneBindings() ? OptionalInt.of(getDataplanePort(deployState)) : OptionalInt.empty();
for (Element element: bindingElements) {
String text = element.getTextContent().trim();
if (!text.isEmpty())
@@ -1091,7 +1117,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
ContainerDocumentApi.HandlerOptions documentApiOptions = DocumentApiOptionsBuilder.build(documentApiElement);
Element ignoreUndefinedFields = XML.getChild(documentApiElement, "ignore-undefined-fields");
OptionalInt portBindingOverride = deployState.featureFlags().useRestrictedDataPlaneBindings() && isHostedTenantApplication(context)
- ? OptionalInt.of(HOSTED_VESPA_DATAPLANE_PORT)
+ ? OptionalInt.of(getDataplanePort(deployState))
: OptionalInt.empty();
return new ContainerDocumentApi(cluster, documentApiOptions,
"true".equals(XML.getValue(ignoreUndefinedFields)), portBindingOverride);
@@ -1354,4 +1380,9 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
}
+ private static int getDataplanePort(DeployState deployState) {
+ // TODO: Determine port
+ return deployState.featureFlags().enableDataplaneProxy() ? 9999 : HOSTED_VESPA_DATAPLANE_PORT;
+ }
+
}
diff --git a/configdefinitions/src/vespa/CMakeLists.txt b/configdefinitions/src/vespa/CMakeLists.txt
index 95e9a31cb73..6a737e6f57d 100644
--- a/configdefinitions/src/vespa/CMakeLists.txt
+++ b/configdefinitions/src/vespa/CMakeLists.txt
@@ -83,3 +83,5 @@ install_config_definition(onnx-models.def vespa.config.search.core.onnx-models.d
vespa_generate_config(configdefinitions proton.def)
install_config_definition(proton.def vespa.config.search.core.proton.def)
vespa_generate_config(configdefinitions hwinfo.def)
+vespa_generate_config(configdefinitions dataplane-proxy.def)
+install_config_definition(dataplane-proxy.def cloud.config.dataplane-proxy.def) \ No newline at end of file
diff --git a/configdefinitions/src/vespa/dataplane-proxy.def b/configdefinitions/src/vespa/dataplane-proxy.def
new file mode 100644
index 00000000000..bef2c8457f7
--- /dev/null
+++ b/configdefinitions/src/vespa/dataplane-proxy.def
@@ -0,0 +1,4 @@
+# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+namespace=cloud.config
+
+port int \ No newline at end of file