From 96c2e442cbb798f0c85990d3f0c760c60ee9a5b3 Mon Sep 17 00:00:00 2001 From: Morten Tokle Date: Thu, 15 Apr 2021 11:58:21 +0200 Subject: Custom acl mapping --- container-core/abi-spec.json | 108 ++++++++++++++++++++- .../java/com/yahoo/container/jdisc/AclMapping.java | 14 +++ .../yahoo/container/jdisc/DefaultAclMapping.java | 31 ++++++ .../yahoo/container/jdisc/RequestHandlerSpec.java | 46 +++++++++ .../container/jdisc/RequestHandlerWithSpec.java | 21 ++++ .../com/yahoo/container/jdisc/RequestView.java | 18 ++++ .../container/jdisc/ThreadedRequestHandler.java | 2 +- .../yahoo/jdisc/http/filter/DiscFilterRequest.java | 14 +++ .../http/server/jetty/FilteringRequestHandler.java | 7 ++ 9 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java create mode 100644 container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java create mode 100644 container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerSpec.java create mode 100644 container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerWithSpec.java create mode 100644 container-core/src/main/java/com/yahoo/container/jdisc/RequestView.java (limited to 'container-core') diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json index c133c9cc158..22fb744ad70 100644 --- a/container-core/abi-spec.json +++ b/container-core/abi-spec.json @@ -478,6 +478,38 @@ "public static final java.lang.String FULL_COVERAGE" ] }, + "com.yahoo.container.jdisc.AclMapping$Action": { + "superClass": "java.lang.Enum", + "interfaces": [], + "attributes": [ + "public", + "final", + "enum" + ], + "methods": [ + "public static com.yahoo.container.jdisc.AclMapping$Action[] values()", + "public static com.yahoo.container.jdisc.AclMapping$Action valueOf(java.lang.String)" + ], + "fields": [ + "public static final enum com.yahoo.container.jdisc.AclMapping$Action create", + "public static final enum com.yahoo.container.jdisc.AclMapping$Action read", + "public static final enum com.yahoo.container.jdisc.AclMapping$Action update", + "public static final enum com.yahoo.container.jdisc.AclMapping$Action delete" + ] + }, + "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 +547,20 @@ ], "fields": [] }, + "com.yahoo.container.jdisc.DefaultAclMapping": { + "superClass": "java.lang.Object", + "interfaces": [ + "com.yahoo.container.jdisc.AclMapping" + ], + "attributes": [ + "public" + ], + "methods": [ + "public void ()", + "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": [], @@ -689,6 +735,34 @@ ], "fields": [] }, + "com.yahoo.container.jdisc.RequestHandlerSpec$Builder": { + "superClass": "java.lang.Object", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void ()", + "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 +808,35 @@ ], "fields": [] }, + "com.yahoo.container.jdisc.RequestHandlerWithSpec": { + "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.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": [ @@ -775,7 +878,9 @@ }, "com.yahoo.container.jdisc.ThreadedRequestHandler": { "superClass": "com.yahoo.jdisc.handler.AbstractRequestHandler", - "interfaces": [], + "interfaces": [ + "com.yahoo.container.jdisc.RequestHandlerWithSpec" + ], "attributes": [ "public", "abstract" @@ -2019,6 +2124,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..8c7701a7534 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/jdisc/AclMapping.java @@ -0,0 +1,14 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +package com.yahoo.container.jdisc; + +/** + * Mapping from request to action + * + * @author mortent + */ +public interface AclMapping { + enum Action {create, read, update, delete}; + + 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..0a996cb5967 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/jdisc/DefaultAclMapping.java @@ -0,0 +1,31 @@ +// 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: + return Action.create; + case DELETE: + return Action.delete; + case PUT: + case PATCH: + case CONNECT: + case TRACE: + return Action.update; + default: + throw new IllegalArgumentException("Illegal request method: " + requestMeta.method()); + } + } +} 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/RequestHandlerWithSpec.java b/container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerWithSpec.java new file mode 100644 index 00000000000..89107195671 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/jdisc/RequestHandlerWithSpec.java @@ -0,0 +1,21 @@ +// 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 request handler specification. + * + * @author mortent + */ +public interface RequestHandlerWithSpec extends RequestHandler { + + /** + * + * @return handler specification + */ + default RequestHandlerSpec requestHandlerSpec() { + return RequestHandlerSpec.DEFAULT_INSTANCE; + } +} 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/ThreadedRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedRequestHandler.java index 446ee90c205..0b05f58f75e 100644 --- a/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedRequestHandler.java +++ b/container-core/src/main/java/com/yahoo/container/jdisc/ThreadedRequestHandler.java @@ -35,7 +35,7 @@ import java.util.logging.Logger; * * @author Simon Thoresen Hult */ -public abstract class ThreadedRequestHandler extends AbstractRequestHandler { +public abstract class ThreadedRequestHandler extends AbstractRequestHandler implements RequestHandlerWithSpec { private static final Logger log = Logger.getLogger(ThreadedRequestHandler.class.getName()); private static final Duration TIMEOUT = Duration.ofSeconds(Integer.parseInt(System.getProperty("ThreadedRequestHandler.timeout", "300"))); 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 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..0d94701f794 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.RequestHandlerWithSpec; 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 RequestHandlerWithSpec) { + RequestHandlerSpec requestHandlerSpec = ((RequestHandlerWithSpec) resolvedRequestHandler).requestHandlerSpec(); + request.context().put(RequestHandlerSpec.ATTRIBUTE_NAME, requestHandlerSpec); + } + RequestHandler requestHandler = new ReferenceCountingRequestHandler(resolvedRequestHandler); ResponseHandler responseHandler; -- cgit v1.2.3