summaryrefslogtreecommitdiffstats
path: root/container-core
diff options
context:
space:
mode:
authorMorten Tokle <mortent@verizonmedia.com>2021-04-16 14:23:33 +0200
committerGitHub <noreply@github.com>2021-04-16 14:23:33 +0200
commitb5ef9172e7ba9a4dc4429918e1ae2fc26444ce33 (patch)
tree16d88702fe9fde02d5005cbd1f0ce8ecce5d18e8 /container-core
parent95162715532714931a379f35f29fba6836e57daa (diff)
parent852ae37871cc7db3447dbfc8ddea5157b6a81d4d (diff)
Merge pull request #17440 from vespa-engine/mortent/custom-acl-mapping
Custom acl mapping
Diffstat (limited to 'container-core')
-rw-r--r--container-core/abi-spec.json107
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java50
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java29
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/HttpRequestHandler.java20
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerSpec.java46
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/RequestView.java18
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java2
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java14
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java7
9 files changed, 291 insertions, 2 deletions
diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json
index 970f7d19eb5..43e0cab967e 100644
--- a/container-core/abi-spec.json
+++ b/container-core/abi-spec.json
@@ -478,6 +478,37 @@
"public static final java.lang.String FULL_COVERAGE"
]
},
+ "com.yahoo.container.jdisc.AclMapping$Action": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public"
+ ],
+ "methods": [
+ "public static com.yahoo.container.jdisc.AclMapping$Action custom(java.lang.String)",
+ "public java.lang.String name()",
+ "public boolean equals(java.lang.Object)",
+ "public int hashCode()",
+ "public java.lang.String toString()"
+ ],
+ "fields": [
+ "public static final com.yahoo.container.jdisc.AclMapping$Action READ",
+ "public static final com.yahoo.container.jdisc.AclMapping$Action WRITE"
+ ]
+ },
+ "com.yahoo.container.jdisc.AclMapping": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public",
+ "interface",
+ "abstract"
+ ],
+ "methods": [
+ "public abstract com.yahoo.container.jdisc.AclMapping$Action get(com.yahoo.container.jdisc.RequestView)"
+ ],
+ "fields": []
+ },
"com.yahoo.container.jdisc.AsyncHttpResponse": {
"superClass": "com.yahoo.container.jdisc.HttpResponse",
"interfaces": [],
@@ -515,6 +546,20 @@
],
"fields": []
},
+ "com.yahoo.container.jdisc.DefaultAclMapping": {
+ "superClass": "java.lang.Object",
+ "interfaces": [
+ "com.yahoo.container.jdisc.AclMapping"
+ ],
+ "attributes": [
+ "public"
+ ],
+ "methods": [
+ "public void <init>()",
+ "public com.yahoo.container.jdisc.AclMapping$Action get(com.yahoo.container.jdisc.RequestView)"
+ ],
+ "fields": []
+ },
"com.yahoo.container.jdisc.EmptyResponse": {
"superClass": "com.yahoo.container.jdisc.HttpResponse",
"interfaces": [],
@@ -596,6 +641,21 @@
],
"fields": []
},
+ "com.yahoo.container.jdisc.HttpRequestHandler": {
+ "superClass": "java.lang.Object",
+ "interfaces": [
+ "com.yahoo.jdisc.handler.RequestHandler"
+ ],
+ "attributes": [
+ "public",
+ "interface",
+ "abstract"
+ ],
+ "methods": [
+ "public com.yahoo.container.jdisc.RequestHandlerSpec requestHandlerSpec()"
+ ],
+ "fields": []
+ },
"com.yahoo.container.jdisc.HttpResponse": {
"superClass": "java.lang.Object",
"interfaces": [],
@@ -689,6 +749,34 @@
],
"fields": []
},
+ "com.yahoo.container.jdisc.RequestHandlerSpec$Builder": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public"
+ ],
+ "methods": [
+ "public void <init>()",
+ "public com.yahoo.container.jdisc.RequestHandlerSpec$Builder withAclMapping(com.yahoo.container.jdisc.AclMapping)",
+ "public com.yahoo.container.jdisc.RequestHandlerSpec build()"
+ ],
+ "fields": []
+ },
+ "com.yahoo.container.jdisc.RequestHandlerSpec": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public"
+ ],
+ "methods": [
+ "public com.yahoo.container.jdisc.AclMapping aclMapping()",
+ "public static com.yahoo.container.jdisc.RequestHandlerSpec$Builder builder()"
+ ],
+ "fields": [
+ "public static final java.lang.String ATTRIBUTE_NAME",
+ "public static final com.yahoo.container.jdisc.RequestHandlerSpec DEFAULT_INSTANCE"
+ ]
+ },
"com.yahoo.container.jdisc.RequestHandlerTestDriver$MockResponseHandler": {
"superClass": "java.lang.Object",
"interfaces": [
@@ -734,6 +822,20 @@
],
"fields": []
},
+ "com.yahoo.container.jdisc.RequestView": {
+ "superClass": "java.lang.Object",
+ "interfaces": [],
+ "attributes": [
+ "public",
+ "interface",
+ "abstract"
+ ],
+ "methods": [
+ "public abstract com.yahoo.jdisc.http.HttpRequest$Method method()",
+ "public abstract java.net.URI uri()"
+ ],
+ "fields": []
+ },
"com.yahoo.container.jdisc.ThreadedHttpRequestHandler$LazyContentChannel": {
"superClass": "java.lang.Object",
"interfaces": [
@@ -752,7 +854,9 @@
},
"com.yahoo.container.jdisc.ThreadedHttpRequestHandler": {
"superClass": "com.yahoo.container.jdisc.ThreadedRequestHandler",
- "interfaces": [],
+ "interfaces": [
+ "com.yahoo.container.jdisc.HttpRequestHandler"
+ ],
"attributes": [
"public",
"abstract"
@@ -2019,6 +2123,7 @@
"public abstract void setHeaders(java.lang.String, java.lang.String)",
"public abstract void setHeaders(java.lang.String, java.util.List)",
"public int getIntHeader(java.lang.String)",
+ "public com.yahoo.container.jdisc.RequestView asRequestView()",
"public java.util.List getCookies()",
"public void setCookies(java.util.List)",
"public long getConnectedAt(java.util.concurrent.TimeUnit)",
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java b/container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java
new file mode 100644
index 00000000000..e7c3d71ba44
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java
@@ -0,0 +1,50 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.container.jdisc;
+
+import java.util.Objects;
+
+/**
+ * Mapping from request to action
+ *
+ * @author mortent
+ */
+public interface AclMapping {
+ class Action {
+ public static final Action READ = new Action("read");
+ public static final Action WRITE = new Action("write");
+ private final String name;
+ public static Action custom(String name) {
+ return new Action(name);
+ }
+ private Action(String name) {
+ if(Objects.requireNonNull(name).isBlank()) {
+ throw new IllegalArgumentException("Name cannot be blank");
+ }
+ this.name = Objects.requireNonNull(name);
+ }
+ public String name() { return name; }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Action action = (Action) o;
+ return Objects.equals(name, action.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public String toString() {
+ return "Action{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+ }
+
+ Action get(RequestView requestView);
+}
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java b/container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java
new file mode 100644
index 00000000000..93639029128
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java
@@ -0,0 +1,29 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.container.jdisc;
+
+/**
+ * Default ACL mapping
+ * @author mortent
+ */
+public class DefaultAclMapping implements AclMapping {
+
+ @Override
+ public Action get(RequestView requestMeta) {
+ switch (requestMeta.method()) {
+ case GET:
+ case HEAD:
+ case OPTIONS:
+ return Action.READ;
+ case POST:
+ case DELETE:
+ case PUT:
+ case PATCH:
+ case CONNECT:
+ case TRACE:
+ return Action.WRITE;
+ default:
+ throw new IllegalArgumentException("Illegal request method: " + requestMeta.method());
+ }
+ }
+}
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/HttpRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/HttpRequestHandler.java
new file mode 100644
index 00000000000..f322c9c5b6f
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/HttpRequestHandler.java
@@ -0,0 +1,20 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.container.jdisc;
+
+import com.yahoo.jdisc.handler.RequestHandler;
+
+/**
+ * Extends a request handler with a http specific
+ *
+ * @author mortent
+ */
+public interface HttpRequestHandler extends RequestHandler {
+
+ /**
+ * @return handler specification
+ */
+ default RequestHandlerSpec requestHandlerSpec() {
+ return RequestHandlerSpec.DEFAULT_INSTANCE;
+ }
+}
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerSpec.java b/container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerSpec.java
new file mode 100644
index 00000000000..91fac9ac448
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerSpec.java
@@ -0,0 +1,46 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.container.jdisc;
+
+import java.util.Objects;
+
+/**
+ * A specification provided by a request handler.
+ * Available through request context attribute
+ *
+ * @author mortent
+ */
+public class RequestHandlerSpec {
+
+ public static final String ATTRIBUTE_NAME = RequestHandlerSpec.class.getName();
+ public static final RequestHandlerSpec DEFAULT_INSTANCE = RequestHandlerSpec.builder().build();
+
+ private final AclMapping aclMapping;
+
+ private RequestHandlerSpec(AclMapping aclMapping) {
+ this.aclMapping = aclMapping;
+ }
+
+ public AclMapping aclMapping() {
+ return aclMapping;
+ }
+
+ public static Builder builder(){
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private AclMapping aclMapping = new DefaultAclMapping();
+
+ public Builder withAclMapping(AclMapping aclMapping) {
+ this.aclMapping = Objects.requireNonNull(aclMapping);
+ return this;
+ }
+
+ public RequestHandlerSpec build() {
+ return new RequestHandlerSpec(aclMapping);
+ }
+ }
+}
+
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/RequestView.java b/container-core/src/main/java/com/yahoo/container/jdisc/RequestView.java
new file mode 100644
index 00000000000..51a5fdc8959
--- /dev/null
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/RequestView.java
@@ -0,0 +1,18 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.container.jdisc;
+
+import com.yahoo.jdisc.http.HttpRequest;
+
+import java.net.URI;
+
+/**
+ * Read-only view of the request
+ *
+ * @author mortent
+ */
+public interface RequestView {
+ HttpRequest.Method method();
+
+ URI uri();
+}
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
index 5b8fe907293..be708f2fc94 100644
--- a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedHttpRequestHandler.java
@@ -32,7 +32,7 @@ import java.util.logging.Logger;
* @author Steinar Knutsen
* @author bratseth
*/
-public abstract class ThreadedHttpRequestHandler extends ThreadedRequestHandler {
+public abstract class ThreadedHttpRequestHandler extends ThreadedRequestHandler implements HttpRequestHandler {
public static final String CONTENT_TYPE = "Content-Type";
private static final String RENDERING_ERRORS = "rendering_errors";
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java b/container-core/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java
index f7ab399574c..72068bd2dd5 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/filter/DiscFilterRequest.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.filter;
+import com.yahoo.container.jdisc.RequestView;
import com.yahoo.jdisc.HeaderFields;
import com.yahoo.jdisc.http.Cookie;
import com.yahoo.jdisc.http.HttpHeaders;
@@ -254,6 +255,19 @@ public abstract class DiscFilterRequest {
}
}
+ public RequestView asRequestView() {
+ return new RequestView() {
+ @Override
+ public HttpRequest.Method method() {
+ return HttpRequest.Method.valueOf(getMethod());
+ }
+
+ @Override
+ public URI uri() {
+ return getUri();
+ }
+ };
+ }
public List<Cookie> getCookies() {
return parent.decodeCookieHeader();
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java
index a487b63ef10..27d122bcaa2 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/FilteringRequestHandler.java
@@ -2,6 +2,8 @@
package com.yahoo.jdisc.http.server.jetty;
import com.google.common.base.Preconditions;
+import com.yahoo.container.jdisc.RequestHandlerSpec;
+import com.yahoo.container.jdisc.HttpRequestHandler;
import com.yahoo.jdisc.Request;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.handler.AbstractRequestHandler;
@@ -65,6 +67,11 @@ class FilteringRequestHandler extends AbstractRequestHandler {
throw new BindingNotFoundException(request.getUri());
}
+ if (resolvedRequestHandler instanceof HttpRequestHandler) {
+ RequestHandlerSpec requestHandlerSpec = ((HttpRequestHandler) resolvedRequestHandler).requestHandlerSpec();
+ request.context().put(RequestHandlerSpec.ATTRIBUTE_NAME, requestHandlerSpec);
+ }
+
RequestHandler requestHandler = new ReferenceCountingRequestHandler(resolvedRequestHandler);
ResponseHandler responseHandler;