summaryrefslogtreecommitdiffstats
path: root/config-model/src/main
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2020-08-19 11:57:46 +0200
committerGitHub <noreply@github.com>2020-08-19 11:57:46 +0200
commit320e626d482968bd0853e2841e5435530a3da174 (patch)
tree2ff9567eaa5ee1c15705245008b5342653bd3f7f /config-model/src/main
parent4fa221b7c20f492de0433b9b812f1cc509a18d97 (diff)
Revert "Bjorncs/improve athenz access control"
Diffstat (limited to 'config-model/src/main')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/component/SystemBindingPattern.java1
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java109
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/FilterBinding.java29
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java6
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java9
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java17
6 files changed, 75 insertions, 96 deletions
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 3ae531539ef..559651b3b4f 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
@@ -13,7 +13,6 @@ public class SystemBindingPattern extends BindingPattern {
public static SystemBindingPattern fromHttpPath(String path) { return new SystemBindingPattern("http", "*", null, path);}
public static SystemBindingPattern fromPattern(String binding) { return new SystemBindingPattern(binding);}
- public static SystemBindingPattern fromHttpPortAndPath(String port, String path) { return new SystemBindingPattern("http", "*", port, path); }
@Override
public String toString() {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java
index e96951dc83a..87c6d41c80d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/AccessControl.java
@@ -8,15 +8,17 @@ import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.container.component.BindingPattern;
import com.yahoo.vespa.model.container.component.FileStatusHandlerComponent;
import com.yahoo.vespa.model.container.component.Handler;
+import com.yahoo.vespa.model.container.component.Servlet;
import com.yahoo.vespa.model.container.component.SystemBindingPattern;
-import com.yahoo.vespa.model.container.component.chain.Chain;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Helper class for http access control.
@@ -24,15 +26,11 @@ import java.util.Set;
* @author gjoranv
* @author bjorncs
*/
-public class AccessControl {
+public final class AccessControl {
public static final ComponentId ACCESS_CONTROL_CHAIN_ID = ComponentId.fromString("access-control-chain");
- public static final ComponentId ACCESS_CONTROL_EXCLUDED_CHAIN_ID = ComponentId.fromString("access-control-excluded-chain");
- private static final int HOSTED_CONTAINER_PORT = 4443;
-
- // Handlers that are excluded from access control
- private static final List<String> EXCLUDED_HANDLERS = List.of(
+ public static final List<String> UNPROTECTED_HANDLERS = List.of(
FileStatusHandlerComponent.CLASS,
ContainerCluster.APPLICATION_STATUS_HANDLER_CLASS,
ContainerCluster.BINDINGS_OVERVIEW_HANDLER_CLASS,
@@ -42,12 +40,13 @@ public class AccessControl {
ApplicationContainerCluster.PROMETHEUS_V1_HANDLER_CLASS
);
- public static class Builder {
- private final String domain;
+ public static final class Builder {
+ private String domain;
private boolean readEnabled = false;
private boolean writeEnabled = true;
private final Set<BindingPattern> excludeBindings = new LinkedHashSet<>();
private Collection<Handler<?>> handlers = Collections.emptyList();
+ private Collection<Servlet> servlets = Collections.emptyList();
public Builder(String domain) {
this.domain = domain;
@@ -58,8 +57,8 @@ public class AccessControl {
return this;
}
- public Builder writeEnabled(boolean writeEnabled) {
- this.writeEnabled = writeEnabled;
+ public Builder writeEnabled(boolean writeEnalbed) {
+ this.writeEnabled = writeEnalbed;
return this;
}
@@ -70,11 +69,13 @@ public class AccessControl {
public Builder setHandlers(ApplicationContainerCluster cluster) {
this.handlers = cluster.getHandlers();
+ this.servlets = cluster.getAllServlets();
return this;
}
public AccessControl build() {
- return new AccessControl(domain, writeEnabled, readEnabled, excludeBindings, handlers);
+ return new AccessControl(domain, writeEnabled, readEnabled,
+ excludeBindings, servlets, handlers);
}
}
@@ -83,83 +84,69 @@ public class AccessControl {
public final boolean writeEnabled;
private final Set<BindingPattern> excludedBindings;
private final Collection<Handler<?>> handlers;
+ private final Collection<Servlet> servlets;
private AccessControl(String domain,
boolean writeEnabled,
boolean readEnabled,
Set<BindingPattern> excludedBindings,
+ Collection<Servlet> servlets,
Collection<Handler<?>> handlers) {
this.domain = domain;
this.readEnabled = readEnabled;
this.writeEnabled = writeEnabled;
this.excludedBindings = Collections.unmodifiableSet(excludedBindings);
this.handlers = handlers;
+ this.servlets = servlets;
}
- public void configureHttpFilterChains(Http http) {
- http.setAccessControl(this);
- addAccessControlFilterChain(http);
- addAccessControlExcludedChain(http);
- removeDuplicateBindingsFromAccessControlChain(http);
+ public List<FilterBinding> getBindings() {
+ return Stream.concat(getHandlerBindings(), getServletBindings())
+ .collect(Collectors.toCollection(ArrayList::new));
}
public static boolean hasHandlerThatNeedsProtection(ApplicationContainerCluster cluster) {
- return cluster.getHandlers().stream()
- .anyMatch(handler -> ! isExcludedHandler(handler) && hasNonMbusBinding(handler));
+ return cluster.getHandlers().stream().anyMatch(AccessControl::handlerNeedsProtection);
}
- private void addAccessControlFilterChain(Http http) {
- http.getFilterChains().add(createChain(ACCESS_CONTROL_CHAIN_ID));
- http.getBindings().addAll(List.of(createAccessControlBinding("/"), createAccessControlBinding("/*")));
+ private Stream<FilterBinding> getHandlerBindings() {
+ return handlers.stream()
+ .filter(this::shouldHandlerBeProtected)
+ .flatMap(handler -> handler.getServerBindings().stream())
+ .map(binding -> accessControlBinding(binding));
}
- private void addAccessControlExcludedChain(Http http) {
- http.getFilterChains().add(createChain(ACCESS_CONTROL_EXCLUDED_CHAIN_ID));
- for (BindingPattern excludedBinding : excludedBindings) {
- http.getBindings().add(createAccessControlExcludedBinding(excludedBinding));
- }
- for (Handler<?> handler : handlers) {
- if (isExcludedHandler(handler)) {
- for (BindingPattern binding : handler.getServerBindings()) {
- http.getBindings().add(createAccessControlExcludedBinding(binding));
- }
- }
- }
+ private Stream<FilterBinding> getServletBindings() {
+ return servlets.stream()
+ .filter(this::shouldServletBeProtected)
+ .flatMap(AccessControl::servletBindings)
+ .map(binding -> accessControlBinding(binding));
}
- // Remove bindings from access control chain that have binding pattern as a different filter chain
- private void removeDuplicateBindingsFromAccessControlChain(Http http) {
- Set<FilterBinding> duplicateBindings = new HashSet<>();
- for (FilterBinding binding : http.getBindings()) {
- if (binding.chainId().toId().equals(ACCESS_CONTROL_CHAIN_ID)) {
- for (FilterBinding otherBinding : http.getBindings()) {
- if (!binding.chainId().equals(otherBinding.chainId())
- && binding.binding().equals(otherBinding.binding())) {
- duplicateBindings.add(binding);
- }
- }
- }
- }
- duplicateBindings.forEach(http.getBindings()::remove);
+ private boolean shouldHandlerBeProtected(Handler<?> handler) {
+ return ! isBuiltinGetOnly(handler)
+ && handler.getServerBindings().stream().noneMatch(excludedBindings::contains);
}
- private static FilterBinding createAccessControlBinding(String path) {
- return FilterBinding.create(
- new ComponentSpecification(ACCESS_CONTROL_CHAIN_ID.stringValue()),
- SystemBindingPattern.fromHttpPortAndPath(Integer.toString(HOSTED_CONTAINER_PORT), path));
+ private static boolean isBuiltinGetOnly(Handler<?> handler) {
+ return UNPROTECTED_HANDLERS.contains(handler.getClassId().getName());
}
- private static FilterBinding createAccessControlExcludedBinding(BindingPattern excludedBinding) {
- BindingPattern rewrittenBinding = SystemBindingPattern.fromHttpPortAndPath(
- Integer.toString(HOSTED_CONTAINER_PORT), excludedBinding.path()); // only keep path from excluded binding
- return FilterBinding.create(
- new ComponentSpecification(ACCESS_CONTROL_EXCLUDED_CHAIN_ID.stringValue()),
- rewrittenBinding);
+ private boolean shouldServletBeProtected(Servlet servlet) {
+ return servletBindings(servlet).noneMatch(excludedBindings::contains);
}
- private static Chain<Filter> createChain(ComponentId id) { return new Chain<>(FilterChains.emptyChainSpec(id)); }
+ private static FilterBinding accessControlBinding(BindingPattern binding) {
+ return FilterBinding.create(new ComponentSpecification(ACCESS_CONTROL_CHAIN_ID.stringValue()), binding);
+ }
+
+ private static Stream<BindingPattern> servletBindings(Servlet servlet) {
+ return Stream.of(SystemBindingPattern.fromHttpPath("/" + servlet.bindingPath));
+ }
- private static boolean isExcludedHandler(Handler<?> handler) { return EXCLUDED_HANDLERS.contains(handler.getClassId().getName()); }
+ private static boolean handlerNeedsProtection(Handler<?> handler) {
+ return ! isBuiltinGetOnly(handler) && hasNonMbusBinding(handler);
+ }
private static boolean hasNonMbusBinding(Handler<?> handler) {
return handler.getServerBindings().stream().anyMatch(binding -> ! binding.scheme().equals("mbus"));
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/FilterBinding.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/FilterBinding.java
index 1ca54769683..8ae06b7cebd 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/FilterBinding.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/FilterBinding.java
@@ -4,44 +4,29 @@ package com.yahoo.vespa.model.container.http;
import com.yahoo.component.ComponentSpecification;
import com.yahoo.vespa.model.container.component.BindingPattern;
-import java.util.Objects;
-
/**
* @author bjorncs
*/
public class FilterBinding {
- private final ComponentSpecification chainId;
+ private final ComponentSpecification filterId;
private final BindingPattern binding;
- private FilterBinding(ComponentSpecification chainId, BindingPattern binding) {
- this.chainId = chainId;
+ private FilterBinding(ComponentSpecification filterId, BindingPattern binding) {
+ this.filterId = filterId;
this.binding = binding;
}
- public static FilterBinding create(ComponentSpecification chainId, BindingPattern binding) {
- return new FilterBinding(chainId, binding);
+ public static FilterBinding create(ComponentSpecification filterId, BindingPattern binding) {
+ return new FilterBinding(filterId, binding);
}
- public ComponentSpecification chainId() {
- return chainId;
+ public ComponentSpecification filterId() {
+ return filterId;
}
public BindingPattern binding() {
return binding;
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- FilterBinding that = (FilterBinding) o;
- return Objects.equals(chainId, that.chainId) &&
- Objects.equals(binding, that.binding);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(chainId, binding);
- }
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java
index f58f5faa382..3155669527a 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/Http.java
@@ -76,7 +76,7 @@ public class Http extends AbstractConfigProducer<AbstractConfigProducer<?>> impl
public void getConfig(ServerConfig.Builder builder) {
for (FilterBinding binding : bindings) {
builder.filter(new ServerConfig.Filter.Builder()
- .id(binding.chainId().stringValue())
+ .id(binding.filterId().stringValue())
.binding(binding.binding().patternString()));
}
}
@@ -92,8 +92,8 @@ public class Http extends AbstractConfigProducer<AbstractConfigProducer<?>> impl
ComponentRegistry<Chain<Filter>> chains = filterChains.allChains();
for (FilterBinding binding: bindings) {
- if (filters.getComponent(binding.chainId()) == null && chains.getComponent(binding.chainId()) == null)
- throw new RuntimeException("Can't find filter " + binding.chainId() + " for binding " + binding.binding());
+ if (filters.getComponent(binding.filterId()) == null && chains.getComponent(binding.filterId()) == null)
+ throw new RuntimeException("Can't find filter " + binding.filterId() + " for binding " + binding.binding());
}
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java
index c86d8b206d5..9d5fead7dfb 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/xml/HttpBuilder.java
@@ -14,6 +14,7 @@ import com.yahoo.vespa.model.builder.xml.dom.VespaDomBuilder;
import com.yahoo.vespa.model.container.ApplicationContainerCluster;
import com.yahoo.vespa.model.container.Container;
import com.yahoo.vespa.model.container.component.UserBindingPattern;
+import com.yahoo.vespa.model.container.component.chain.Chain;
import com.yahoo.vespa.model.container.http.AccessControl;
import com.yahoo.vespa.model.container.http.FilterBinding;
import com.yahoo.vespa.model.container.http.FilterChains;
@@ -25,6 +26,8 @@ import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
+import static com.yahoo.vespa.model.container.http.AccessControl.ACCESS_CONTROL_CHAIN_ID;
+
/**
* @author Tony Vaagenes
* @author gjoranv
@@ -45,6 +48,8 @@ public class HttpBuilder extends VespaDomBuilder.DomConfigProducerBuilder<Http>
Element accessControlElem = XML.getChild(filteringElem, "access-control");
if (accessControlElem != null) {
accessControl = buildAccessControl(deployState, ancestor, accessControlElem);
+ bindings.addAll(accessControl.getBindings());
+ filterChains.add(new Chain<>(FilterChains.emptyChainSpec(ACCESS_CONTROL_CHAIN_ID)));
}
} else {
filterChains = new FilterChainsBuilder().newChainsInstance(ancestor);
@@ -52,10 +57,8 @@ public class HttpBuilder extends VespaDomBuilder.DomConfigProducerBuilder<Http>
Http http = new Http(filterChains);
http.getBindings().addAll(bindings);
+ http.setAccessControl(accessControl);
http.setHttpServer(new JettyHttpServerBuilder().build(deployState, ancestor, spec));
- if (accessControl != null) {
- accessControl.configureHttpFilterChains(http);
- }
return http;
}
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 51583588201..d11e0f9a891 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
@@ -61,6 +61,7 @@ import com.yahoo.vespa.model.container.component.FileStatusHandlerComponent;
import com.yahoo.vespa.model.container.component.Handler;
import com.yahoo.vespa.model.container.component.SystemBindingPattern;
import com.yahoo.vespa.model.container.component.UserBindingPattern;
+import com.yahoo.vespa.model.container.component.chain.Chain;
import com.yahoo.vespa.model.container.component.chain.ProcessingHandler;
import com.yahoo.vespa.model.container.docproc.ContainerDocproc;
import com.yahoo.vespa.model.container.docproc.DocprocChains;
@@ -93,6 +94,7 @@ import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import static com.yahoo.vespa.model.container.http.AccessControl.ACCESS_CONTROL_CHAIN_ID;
import static java.util.logging.Level.WARNING;
/**
@@ -369,12 +371,15 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
if (http.getAccessControl().isPresent()) return; // access control added explicitly
AthenzDomain tenantDomain = deployState.getProperties().athenzDomain().orElse(null);
if (tenantDomain == null) return; // tenant domain not present, cannot add access control. this should eventually be a failure.
- new AccessControl.Builder(tenantDomain.value())
- .setHandlers(cluster)
- .readEnabled(false)
- .writeEnabled(false)
- .build()
- .configureHttpFilterChains(http);
+ AccessControl accessControl =
+ new AccessControl.Builder(tenantDomain.value())
+ .setHandlers(cluster)
+ .readEnabled(false)
+ .writeEnabled(false)
+ .build();
+ http.getFilterChains().add(new Chain<>(FilterChains.emptyChainSpec(ACCESS_CONTROL_CHAIN_ID)));
+ http.setAccessControl(accessControl);
+ http.getBindings().addAll(accessControl.getBindings());
}
private Http buildHttp(DeployState deployState, ApplicationContainerCluster cluster, Element httpElement) {