diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2023-07-18 12:39:54 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2023-07-19 15:52:52 +0200 |
commit | 6a04405f7f7072d8aa04f486da55231580720855 (patch) | |
tree | 23a169641a8f674422a25c34489f442bf5c82b57 | |
parent | 9b3ee17b0ec8c844ace83bd7c797d6600ce0b713 (diff) |
Add handler binding for additional token auth port
7 files changed, 79 insertions, 66 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomHandlerBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomHandlerBuilder.java index ed53a1d2267..9b5a1429cb7 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomHandlerBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomHandlerBuilder.java @@ -15,7 +15,7 @@ import com.yahoo.vespa.model.container.component.UserBindingPattern; import com.yahoo.vespa.model.container.xml.BundleInstantiationSpecificationBuilder; import org.w3c.dom.Element; -import java.util.OptionalInt; +import java.util.Collection; import java.util.Set; import static com.yahoo.vespa.model.container.ApplicationContainerCluster.METRICS_V2_HANDLER_BINDING_1; @@ -38,12 +38,9 @@ public class DomHandlerBuilder extends VespaDomBuilder.DomConfigProducerBuilderB VIP_HANDLER_BINDING); private final ApplicationContainerCluster cluster; - private final OptionalInt portBindingOverride; + private final Set<Integer> portBindingOverride; - public DomHandlerBuilder(ApplicationContainerCluster cluster) { - this(cluster, OptionalInt.empty()); - } - public DomHandlerBuilder(ApplicationContainerCluster cluster, OptionalInt portBindingOverride) { + public DomHandlerBuilder(ApplicationContainerCluster cluster, Set<Integer> portBindingOverride) { this.cluster = cluster; this.portBindingOverride = portBindingOverride; } @@ -51,23 +48,24 @@ public class DomHandlerBuilder extends VespaDomBuilder.DomConfigProducerBuilderB @Override protected Handler doBuild(DeployState deployState, TreeConfigProducer<AnyConfigProducer> parent, Element handlerElement) { Handler handler = createHandler(handlerElement); - OptionalInt port = portBindingOverride.isPresent() && deployState.isHosted() && deployState.featureFlags().useRestrictedDataPlaneBindings() - ? portBindingOverride - : OptionalInt.empty(); + var ports = deployState.isHosted() && deployState.featureFlags().useRestrictedDataPlaneBindings() + ? portBindingOverride : Set.<Integer>of(); - for (Element binding : XML.getChildren(handlerElement, "binding")) - addServerBinding(handler, userBindingPattern(XML.getValue(binding), port), deployState.getDeployLogger()); + for (Element xmlBinding : XML.getChildren(handlerElement, "binding")) + for (var binding : userBindingPattern(XML.getValue(xmlBinding), ports)) + addServerBinding(handler, binding, deployState.getDeployLogger()); DomComponentBuilder.addChildren(deployState, parent, handlerElement, handler); return handler; } - private static UserBindingPattern userBindingPattern(String path, OptionalInt port) { + private static Collection<UserBindingPattern> userBindingPattern(String path, Set<Integer> portBindingOverride) { UserBindingPattern bindingPattern = UserBindingPattern.fromPattern(path); - return port.isPresent() - ? bindingPattern.withPort(port.getAsInt()) - : bindingPattern; + if (portBindingOverride.isEmpty()) return Set.of(bindingPattern); + return portBindingOverride.stream() + .map(bindingPattern::withPort) + .toList(); } Handler createHandler(Element handlerElement) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java b/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java index 8163c268d09..a5a567b18f8 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/clients/ContainerDocumentApi.java @@ -14,7 +14,8 @@ import com.yahoo.vespa.model.container.component.UserBindingPattern; import java.nio.file.Path; import java.util.Collection; import java.util.Collections; -import java.util.OptionalInt; +import java.util.List; +import java.util.Set; /** * @author Einar M R Rosenvinge @@ -28,7 +29,7 @@ public class ContainerDocumentApi { private final boolean ignoreUndefinedFields; - public ContainerDocumentApi(ContainerCluster<?> cluster, HandlerOptions handlerOptions, boolean ignoreUndefinedFields, OptionalInt portOverride) { + public ContainerDocumentApi(ContainerCluster<?> cluster, HandlerOptions handlerOptions, boolean ignoreUndefinedFields, Set<Integer> portOverride) { this.ignoreUndefinedFields = ignoreUndefinedFields; addRestApiHandler(cluster, handlerOptions, portOverride); addFeedHandler(cluster, handlerOptions, portOverride); @@ -39,7 +40,7 @@ public class ContainerDocumentApi { c.addPlatformBundle(VESPACLIENT_CONTAINER_BUNDLE); } - private static void addFeedHandler(ContainerCluster<?> cluster, HandlerOptions handlerOptions, OptionalInt portOverride) { + private static void addFeedHandler(ContainerCluster<?> cluster, HandlerOptions handlerOptions, Set<Integer> portOverride) { String bindingSuffix = ContainerCluster.RESERVED_URI_PREFIX + "/feedapi"; var executor = new Threadpool("feedapi-handler", handlerOptions.feedApiThreadpoolOptions); var handler = newVespaClientHandler("com.yahoo.vespa.http.server.FeedHandler", @@ -48,7 +49,7 @@ public class ContainerDocumentApi { } - private static void addRestApiHandler(ContainerCluster<?> cluster, HandlerOptions handlerOptions, OptionalInt portOverride) { + private static void addRestApiHandler(ContainerCluster<?> cluster, HandlerOptions handlerOptions, Set<Integer> portOverride) { var handler = newVespaClientHandler("com.yahoo.document.restapi.resource.DocumentV1ApiHandler", DOCUMENT_V1_PREFIX + "/*", handlerOptions, null, portOverride); cluster.addComponent(handler); @@ -65,34 +66,34 @@ public class ContainerDocumentApi { String bindingSuffix, HandlerOptions handlerOptions, Threadpool executor, - OptionalInt portOverride) { + Set<Integer> portOverride) { Handler handler = createHandler(componentId, executor); if (handlerOptions.bindings.isEmpty()) { - handler.addServerBindings( - bindingPattern(bindingSuffix, portOverride), - bindingPattern(bindingSuffix + '/', portOverride)); + handler.addServerBindings(bindingPattern(bindingSuffix, portOverride)); + handler.addServerBindings(bindingPattern(bindingSuffix + '/', portOverride)); } else { for (String rootBinding : handlerOptions.bindings) { String pathWithoutLeadingSlash = bindingSuffix.substring(1); - handler.addServerBindings( - userBindingPattern(rootBinding + pathWithoutLeadingSlash, portOverride), - userBindingPattern(rootBinding + pathWithoutLeadingSlash + '/', portOverride)); + handler.addServerBindings(userBindingPattern(rootBinding + pathWithoutLeadingSlash, portOverride)); + handler.addServerBindings(userBindingPattern(rootBinding + pathWithoutLeadingSlash + '/', portOverride)); } } return handler; } - private static BindingPattern bindingPattern(String path, OptionalInt port) { - return port.isPresent() - ? SystemBindingPattern.fromHttpPortAndPath(Integer.toString(port.getAsInt()), path) - : SystemBindingPattern.fromHttpPath(path); + private static List<BindingPattern> bindingPattern(String path, Set<Integer> ports) { + if (ports.isEmpty()) return List.of(SystemBindingPattern.fromHttpPath(path)); + return ports.stream() + .map(p -> (BindingPattern)SystemBindingPattern.fromHttpPortAndPath(p, path)) + .toList(); } - private static UserBindingPattern userBindingPattern(String path, OptionalInt port) { + private static List<BindingPattern> userBindingPattern(String path, Set<Integer> ports) { UserBindingPattern bindingPattern = UserBindingPattern.fromPattern(path); - return port.isPresent() - ? bindingPattern.withPort(port.getAsInt()) - : bindingPattern; + if (ports.isEmpty()) return List.of(bindingPattern); + return ports.stream() + .map(p -> (BindingPattern)bindingPattern.withPort(p)) + .toList(); } private static Handler createHandler(String className, Threadpool executor) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/component/Handler.java b/config-model/src/main/java/com/yahoo/vespa/model/container/component/Handler.java index 9f2bfe9251b..31031aa5bf2 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/component/Handler.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/component/Handler.java @@ -7,6 +7,7 @@ import com.yahoo.vespa.model.container.ContainerThreadpool; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; @@ -51,6 +52,8 @@ public class Handler extends Component<Component<?, ?>, ComponentModel> { serverBindings.addAll(Arrays.asList(bindings)); } + public void addServerBindings(Collection<BindingPattern> bps) { serverBindings.addAll(bps); } + public void removeServerBinding(BindingPattern binding) { serverBindings.remove(binding); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/component/SystemBindingPattern.java b/config-model/src/main/java/com/yahoo/vespa/model/container/component/SystemBindingPattern.java index 606557670a5..0fb3ec389e0 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/component/SystemBindingPattern.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/component/SystemBindingPattern.java @@ -15,6 +15,7 @@ public class SystemBindingPattern extends BindingPattern { public static SystemBindingPattern fromPattern(String binding) { return new SystemBindingPattern(binding);} public static SystemBindingPattern fromHttpPortAndPath(String port, String path) { return new SystemBindingPattern("http", "*", port, path); } public static SystemBindingPattern fromHttpPortAndPath(int port, String path) { return new SystemBindingPattern("http", "*", Integer.toString(port), path); } + public SystemBindingPattern withPort(int port) { return new SystemBindingPattern(scheme(), host(), Integer.toString(port), path()); } @Override public String toString() { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java b/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java index 330e1f96dc7..b05466d54ab 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/processing/ProcessingChains.java @@ -6,6 +6,8 @@ import com.yahoo.vespa.model.container.component.BindingPattern; import com.yahoo.vespa.model.container.component.SystemBindingPattern; import com.yahoo.vespa.model.container.component.chain.Chains; +import java.util.List; + /** * Root config producer for processing * @@ -13,7 +15,7 @@ import com.yahoo.vespa.model.container.component.chain.Chains; */ public class ProcessingChains extends Chains<ProcessingChain> { - public static final BindingPattern[] defaultBindings = new BindingPattern[]{SystemBindingPattern.fromHttpPath("/processing/*")}; + public static final List<BindingPattern> defaultBindings = List.of(SystemBindingPattern.fromHttpPath("/processing/*")); public ProcessingChains(TreeConfigProducer<? super Chains> parent, String subId) { 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 c97ea6671e8..d9b725bae40 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 @@ -139,9 +139,6 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { // Default path to vip status file for container in Hosted Vespa. static final String HOSTED_VESPA_STATUS_FILE = Defaults.getDefaults().underVespaHome("var/vespa/load-balancer/status.html"); - // Data plane port for hosted Vespa - public static final int HOSTED_VESPA_DATAPLANE_PORT = 4443; - //Path to vip status file for container in Hosted Vespa. Only used if set, else use HOSTED_VESPA_STATUS_FILE private static final String HOSTED_VESPA_STATUS_FILE_SETTING = "VESPA_LB_STATUS_FILE"; @@ -469,7 +466,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { private static void addCloudDataPlaneFilter(DeployState deployState, ApplicationContainerCluster cluster) { if (!deployState.isHosted() || !deployState.zone().system().isPublic()) return; - var dataplanePort = getDataplanePort(deployState); + var dataplanePort = getMtlsDataplanePort(deployState); // Setup secure filter chain var secureChain = new HttpFilterChain("cloud-data-plane-secure", HttpFilterChain.Type.SYSTEM); secureChain.addInnerComponent(new CloudDataPlaneFilter(cluster, deployState)); @@ -604,7 +601,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { String serverName = server.getComponentId().getName(); // If the deployment contains certificate/private key reference, setup TLS port - var builder = HostedSslConnectorFactory.builder(serverName, getDataplanePort(state)) + var builder = HostedSslConnectorFactory.builder(serverName, getMtlsDataplanePort(state)) .proxyProtocol(true, state.getProperties().featureFlags().enableProxyProtocolMixedMode()) .tlsCiphersOverride(state.getProperties().tlsCiphersOverride()) .endpointConnectionTtl(state.getProperties().endpointConnectionTtl()); @@ -637,7 +634,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { cluster.addSimpleComponent(DataplaneProxyService.class); var dataplaneProxy = new DataplaneProxy( - getDataplanePort(state), + getMtlsDataplanePort(state), endpointCert.certificate(), endpointCert.key()); cluster.addComponent(dataplaneProxy); @@ -810,7 +807,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { } private void addUserHandlers(DeployState deployState, ApplicationContainerCluster cluster, Element spec, ConfigModelContext context) { - OptionalInt portBindingOverride = isHostedTenantApplication(context) ? OptionalInt.of(getDataplanePort(deployState)) : OptionalInt.empty(); + var portBindingOverride = isHostedTenantApplication(context) ? getDataplanePorts(deployState) : Set.<Integer>of(); for (Element component: XML.getChildren(spec, "handler")) { cluster.addComponent( new DomHandlerBuilder(cluster, portBindingOverride).build(deployState, cluster, component)); @@ -1099,12 +1096,12 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { } private void addSearchHandler(DeployState deployState, ApplicationContainerCluster cluster, Element searchElement, ConfigModelContext context) { - BindingPattern bindingPattern = SearchHandler.DEFAULT_BINDING; + var bindingPatterns = List.<BindingPattern>of(SearchHandler.DEFAULT_BINDING); if (isHostedTenantApplication(context) && deployState.featureFlags().useRestrictedDataPlaneBindings()) { - bindingPattern = SearchHandler.bindingPattern(Optional.of(Integer.toString(getDataplanePort(deployState)))); + bindingPatterns = SearchHandler.bindingPattern(getDataplanePorts(deployState)); } SearchHandler searchHandler = new SearchHandler(cluster, - serverBindings(deployState, context, searchElement, bindingPattern), + serverBindings(deployState, context, searchElement, bindingPatterns), ContainerThreadpool.UserOptions.fromXml(searchElement).orElse(null)); cluster.addComponent(searchHandler); @@ -1112,41 +1109,43 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { searchHandler.addComponent(Component.fromClassAndBundle(SearchHandler.EXECUTION_FACTORY, PlatformBundles.SEARCH_AND_DOCPROC_BUNDLE)); } - private List<BindingPattern> serverBindings(DeployState deployState, ConfigModelContext context, Element searchElement, BindingPattern... defaultBindings) { + private List<BindingPattern> serverBindings(DeployState deployState, ConfigModelContext context, Element searchElement, Collection<BindingPattern> defaultBindings) { List<Element> bindings = XML.getChildren(searchElement, "binding"); if (bindings.isEmpty()) - return List.of(defaultBindings); + return List.copyOf(defaultBindings); return toBindingList(deployState, context, bindings); } 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(getDataplanePort(deployState)) : OptionalInt.empty(); + var portOverride = isHostedTenantApplication(context) && deployState.featureFlags().useRestrictedDataPlaneBindings() ? getDataplanePorts(deployState) : Set.<Integer>of(); for (Element element: bindingElements) { String text = element.getTextContent().trim(); if (!text.isEmpty()) - result.add(userBindingPattern(text, portOverride)); + result.addAll(userBindingPattern(text, portOverride)); } return result; } - private static UserBindingPattern userBindingPattern(String path, OptionalInt portOverride) { + private static Collection<UserBindingPattern> userBindingPattern(String path, Set<Integer> portBindingOverride) { UserBindingPattern bindingPattern = UserBindingPattern.fromPattern(path); - return portOverride.isPresent() - ? bindingPattern.withPort(portOverride.getAsInt()) - : bindingPattern; + if (portBindingOverride.isEmpty()) return Set.of(bindingPattern); + return portBindingOverride.stream() + .map(bindingPattern::withPort) + .toList(); } + private ContainerDocumentApi buildDocumentApi(DeployState deployState, ApplicationContainerCluster cluster, Element spec, ConfigModelContext context) { Element documentApiElement = XML.getChild(spec, "document-api"); if (documentApiElement == null) return null; ContainerDocumentApi.HandlerOptions documentApiOptions = DocumentApiOptionsBuilder.build(documentApiElement); Element ignoreUndefinedFields = XML.getChild(documentApiElement, "ignore-undefined-fields"); - OptionalInt portBindingOverride = deployState.featureFlags().useRestrictedDataPlaneBindings() && isHostedTenantApplication(context) - ? OptionalInt.of(getDataplanePort(deployState)) - : OptionalInt.empty(); + var portBindingOverride = deployState.featureFlags().useRestrictedDataPlaneBindings() && isHostedTenantApplication(context) + ? getDataplanePorts(deployState) + : Set.<Integer>of(); return new ContainerDocumentApi(cluster, documentApiOptions, "true".equals(XML.getValue(ignoreUndefinedFields)), portBindingOverride); } @@ -1406,8 +1405,18 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { } - private static int getDataplanePort(DeployState deployState) { - return deployState.featureFlags().enableDataplaneProxy() ? 8443 : HOSTED_VESPA_DATAPLANE_PORT; + private static Set<Integer> getDataplanePorts(DeployState ds) { + var tokenPort = getTokenDataplanePort(ds); + var mtlsPort = getMtlsDataplanePort(ds); + return tokenPort.isPresent() ? Set.of(mtlsPort, tokenPort.getAsInt()) : Set.of(mtlsPort); + } + + private static int getMtlsDataplanePort(DeployState ds) { + return ds.featureFlags().enableDataplaneProxy() ? 8443 : 4443; + } + + private static OptionalInt getTokenDataplanePort(DeployState ds) { + return ds.featureFlags().enableDataplaneProxy() ? OptionalInt.of(8444) : OptionalInt.empty(); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java index ebb22b2b73b..6cfef153fee 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/SearchHandler.java @@ -10,8 +10,8 @@ import com.yahoo.vespa.model.container.component.SystemBindingPattern; import com.yahoo.vespa.model.container.component.chain.ProcessingHandler; import com.yahoo.vespa.model.container.search.searchchain.SearchChains; +import java.util.Collection; import java.util.List; -import java.util.Optional; import static com.yahoo.container.bundle.BundleInstantiationSpecification.fromSearchAndDocproc; @@ -28,7 +28,7 @@ class SearchHandler extends ProcessingHandler<SearchChains> { static final String EXECUTION_FACTORY_CLASSNAME = EXECUTION_FACTORY.getName(); static final BundleInstantiationSpecification HANDLER_SPEC = fromSearchAndDocproc(HANDLER_CLASSNAME); - static final BindingPattern DEFAULT_BINDING = bindingPattern(Optional.empty()); + static final BindingPattern DEFAULT_BINDING = SystemBindingPattern.fromHttpPath("/search/*"); SearchHandler(ApplicationContainerCluster cluster, List<BindingPattern> bindings, @@ -37,12 +37,11 @@ class SearchHandler extends ProcessingHandler<SearchChains> { bindings.forEach(this::addServerBindings); } - static BindingPattern bindingPattern(Optional<String> port) { - String path = "/search/*"; - return port - .filter(s -> !s.isBlank()) - .map(s -> SystemBindingPattern.fromHttpPortAndPath(s, path)) - .orElseGet(() -> SystemBindingPattern.fromHttpPath(path)); + static List<BindingPattern> bindingPattern(Collection<Integer> ports) { + if (ports.isEmpty()) return List.of(DEFAULT_BINDING); + return ports.stream() + .map(s -> (BindingPattern)SystemBindingPattern.fromHttpPortAndPath(s, DEFAULT_BINDING.path())) + .toList(); } private static class Threadpool extends ContainerThreadpool { |