summaryrefslogtreecommitdiffstats
path: root/jrt
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2022-07-20 16:01:16 +0200
committerGitHub <noreply@github.com>2022-07-20 16:01:16 +0200
commit37b82350dd673de1d7375c01838123bf0b1e1a91 (patch)
treed57a651f4c11589a5acefd26f70b612766857f3f /jrt
parent02c4a8fff7668971d0b82581081c1ea9466d5fc8 (diff)
parent4dcb1c83c96b51ec9a1770c269e75a94debebb9d (diff)
Merge pull request #23528 from vespa-engine/bjorncs/capabilities
Bjorncs/capabilities [run-systemtest]
Diffstat (limited to 'jrt')
-rw-r--r--jrt/src/com/yahoo/jrt/Connection.java17
-rw-r--r--jrt/src/com/yahoo/jrt/CryptoSocket.java12
-rw-r--r--jrt/src/com/yahoo/jrt/ErrorCode.java3
-rw-r--r--jrt/src/com/yahoo/jrt/InvocationServer.java6
-rw-r--r--jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java7
-rw-r--r--jrt/src/com/yahoo/jrt/Method.java6
-rw-r--r--jrt/src/com/yahoo/jrt/RequestAccessFilter.java17
-rw-r--r--jrt/src/com/yahoo/jrt/RequireCapabilitiesFilter.java54
-rw-r--r--jrt/src/com/yahoo/jrt/Target.java12
-rw-r--r--jrt/src/com/yahoo/jrt/TlsCryptoSocket.java12
-rw-r--r--jrt/tests/com/yahoo/jrt/CryptoUtils.java8
-rw-r--r--jrt/tests/com/yahoo/jrt/EchoTest.java7
-rw-r--r--jrt/tests/com/yahoo/jrt/InvokeAsyncTest.java22
-rw-r--r--jrt/tests/com/yahoo/jrt/InvokeErrorTest.java59
-rw-r--r--jrt/tests/com/yahoo/jrt/InvokeSyncTest.java19
-rw-r--r--jrt/tests/com/yahoo/jrt/SimpleRequestAccessFilter.java9
16 files changed, 212 insertions, 58 deletions
diff --git a/jrt/src/com/yahoo/jrt/Connection.java b/jrt/src/com/yahoo/jrt/Connection.java
index 644e2ef4ff3..1e4092efb75 100644
--- a/jrt/src/com/yahoo/jrt/Connection.java
+++ b/jrt/src/com/yahoo/jrt/Connection.java
@@ -1,9 +1,10 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
+import com.yahoo.security.tls.ConnectionAuthContext;
import java.io.IOException;
+import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
@@ -11,7 +12,6 @@ import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -438,9 +438,16 @@ class Connection extends Target {
}
@Override
- public Optional<ConnectionAuthContext> getConnectionAuthContext() {
- return Optional.ofNullable(socket)
- .flatMap(CryptoSocket::getConnectionAuthContext);
+ public ConnectionAuthContext connectionAuthContext() {
+ if (socket == null) throw new IllegalStateException("Not connected");
+ return socket.connectionAuthContext();
+ }
+
+ @Override
+ public Spec peerSpec() {
+ if (socket == null) throw new IllegalStateException("Not connected");
+ InetSocketAddress addr = (InetSocketAddress) socket.channel().socket().getRemoteSocketAddress();
+ return new Spec(addr.getHostString(), addr.getPort());
}
public boolean isClient() {
diff --git a/jrt/src/com/yahoo/jrt/CryptoSocket.java b/jrt/src/com/yahoo/jrt/CryptoSocket.java
index aac91362405..e30579d2bdc 100644
--- a/jrt/src/com/yahoo/jrt/CryptoSocket.java
+++ b/jrt/src/com/yahoo/jrt/CryptoSocket.java
@@ -2,12 +2,11 @@
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
+import com.yahoo.security.tls.ConnectionAuthContext;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
-import java.util.Optional;
/**
@@ -104,11 +103,6 @@ public interface CryptoSocket {
**/
public void dropEmptyBuffers();
- /**
- * Returns the auth context for the current connection (given handshake completed),
- * or empty if the current connection is not secure.
- */
- default public Optional<ConnectionAuthContext> getConnectionAuthContext() {
- return Optional.empty();
- }
+ /** Returns the auth context for the current connection (given handshake completed) */
+ default ConnectionAuthContext connectionAuthContext() { return ConnectionAuthContext.defaultAllCapabilities(); }
}
diff --git a/jrt/src/com/yahoo/jrt/ErrorCode.java b/jrt/src/com/yahoo/jrt/ErrorCode.java
index beaabcea316..8e129cfef98 100644
--- a/jrt/src/com/yahoo/jrt/ErrorCode.java
+++ b/jrt/src/com/yahoo/jrt/ErrorCode.java
@@ -49,4 +49,7 @@ public class ErrorCode
/** Method failed (111) **/
public static final int METHOD_FAILED = 111;
+
+ /** Permission denied (112) **/
+ public static final int PERMISSION_DENIED = 112;
}
diff --git a/jrt/src/com/yahoo/jrt/InvocationServer.java b/jrt/src/com/yahoo/jrt/InvocationServer.java
index 9df92eb20a6..7704c0019ed 100644
--- a/jrt/src/com/yahoo/jrt/InvocationServer.java
+++ b/jrt/src/com/yahoo/jrt/InvocationServer.java
@@ -31,7 +31,11 @@ class InvocationServer {
public void invoke() {
if (method != null) {
if (method.checkParameters(request)) {
- method.invoke(request);
+ if (method.requestAccessFilter().allow(request)) {
+ method.invoke(request);
+ } else {
+ request.setError(ErrorCode.PERMISSION_DENIED, "Permission denied");
+ }
} else {
request.setError(ErrorCode.WRONG_PARAMS, "Parameters in " + request + " does not match " + method);
}
diff --git a/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java
index 42442289cd1..ab9d78d2676 100644
--- a/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java
+++ b/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java
@@ -1,12 +1,11 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
+import com.yahoo.security.tls.ConnectionAuthContext;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
-import java.util.Optional;
/**
* A crypto socket for the server side of a connection that
@@ -132,7 +131,5 @@ public class MaybeTlsCryptoSocket implements CryptoSocket {
@Override public int write(ByteBuffer src) throws IOException { return socket.write(src); }
@Override public FlushResult flush() throws IOException { return socket.flush(); }
@Override public void dropEmptyBuffers() { socket.dropEmptyBuffers(); }
- @Override public Optional<ConnectionAuthContext> getConnectionAuthContext() {
- return Optional.ofNullable(socket).flatMap(CryptoSocket::getConnectionAuthContext);
- }
+ @Override public ConnectionAuthContext connectionAuthContext() { return socket.connectionAuthContext(); }
}
diff --git a/jrt/src/com/yahoo/jrt/Method.java b/jrt/src/com/yahoo/jrt/Method.java
index 4fc9f0714da..89c66747e0b 100644
--- a/jrt/src/com/yahoo/jrt/Method.java
+++ b/jrt/src/com/yahoo/jrt/Method.java
@@ -40,6 +40,8 @@ public class Method {
private String[] returnName;
private String[] returnDesc;
+ private RequestAccessFilter filter = RequestAccessFilter.ALLOW_ALL;
+
private static final String undocumented = "???";
@@ -147,6 +149,10 @@ public class Method {
return this;
}
+ public Method requestAccessFilter(RequestAccessFilter filter) { this.filter = filter; return this; }
+
+ public RequestAccessFilter requestAccessFilter() { return filter; }
+
/**
* Obtain the name of a parameter
*
diff --git a/jrt/src/com/yahoo/jrt/RequestAccessFilter.java b/jrt/src/com/yahoo/jrt/RequestAccessFilter.java
new file mode 100644
index 00000000000..6701436d6ce
--- /dev/null
+++ b/jrt/src/com/yahoo/jrt/RequestAccessFilter.java
@@ -0,0 +1,17 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jrt;
+
+/**
+ * Request access filter is invoked before any call to {@link Method#invoke(Request)}.
+ * If {@link #allow(Request)} returns false, the method is not invoked, and the request is failed with error
+ * {@link ErrorCode#PERMISSION_DENIED}.
+ *
+ * @author bjorncs
+ */
+public interface RequestAccessFilter {
+
+ RequestAccessFilter ALLOW_ALL = __ -> true;
+
+ boolean allow(Request r);
+
+}
diff --git a/jrt/src/com/yahoo/jrt/RequireCapabilitiesFilter.java b/jrt/src/com/yahoo/jrt/RequireCapabilitiesFilter.java
new file mode 100644
index 00000000000..bb2eafcf711
--- /dev/null
+++ b/jrt/src/com/yahoo/jrt/RequireCapabilitiesFilter.java
@@ -0,0 +1,54 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jrt;
+
+import com.yahoo.security.tls.Capability;
+import com.yahoo.security.tls.CapabilityMode;
+import com.yahoo.security.tls.CapabilitySet;
+import com.yahoo.security.tls.ConnectionAuthContext;
+import com.yahoo.security.tls.TransportSecurityUtils;
+
+import java.util.logging.Logger;
+
+import static com.yahoo.security.tls.CapabilityMode.DISABLE;
+import static com.yahoo.security.tls.CapabilityMode.LOG_ONLY;
+
+/**
+ * @author bjorncs
+ */
+public class RequireCapabilitiesFilter implements RequestAccessFilter {
+
+ private static final Logger log = Logger.getLogger(RequireCapabilitiesFilter.class.getName());
+ private static final CapabilityMode MODE = TransportSecurityUtils.getCapabilityMode();
+
+ private final CapabilitySet requiredCapabilities;
+
+ public RequireCapabilitiesFilter(CapabilitySet requiredCapabilities) {
+ this.requiredCapabilities = requiredCapabilities;
+ }
+
+ public RequireCapabilitiesFilter(Capability... requiredCapabilities) {
+ this(CapabilitySet.from(requiredCapabilities));
+ }
+
+ @Override
+ public boolean allow(Request r) {
+ if (MODE == DISABLE) return true;
+ ConnectionAuthContext ctx = r.target().connectionAuthContext();
+ CapabilitySet peerCapabilities = ctx.capabilities();
+ boolean authorized = peerCapabilities.has(requiredCapabilities);
+ if (!authorized) {
+ String msg = "%sPermission denied for RPC method '%s'. Peer at %s with %s. Call requires %s, but peer has %s"
+ .formatted(MODE == LOG_ONLY ? "Dry-run: " : "", r.methodName(), r.target().peerSpec(), ctx.peerCertificateString().orElseThrow(),
+ requiredCapabilities.toNames(), peerCapabilities.toNames());
+ if (MODE == LOG_ONLY) {
+ log.info(msg);
+ return true;
+ } else {
+ log.warning(msg);
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/jrt/src/com/yahoo/jrt/Target.java b/jrt/src/com/yahoo/jrt/Target.java
index 239a71f53b3..0e8c27deac5 100644
--- a/jrt/src/com/yahoo/jrt/Target.java
+++ b/jrt/src/com/yahoo/jrt/Target.java
@@ -1,9 +1,7 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
-
-import java.util.Optional;
+import com.yahoo.security.tls.ConnectionAuthContext;
/**
* A Target represents a connection endpoint with RPC
@@ -71,9 +69,13 @@ public abstract class Target {
public Exception getConnectionLostReason() { return null; }
/**
- * Returns the connection auth context associated with this target, or empty if no connection or is insecure.
+ * Returns the connection auth context associated with this target.
*/
- public abstract Optional<ConnectionAuthContext> getConnectionAuthContext();
+ public abstract ConnectionAuthContext connectionAuthContext();
+
+
+ /** @return address spec of socket peer */
+ public abstract Spec peerSpec();
/**
* Check if this target represents the client side of a
diff --git a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java
index ecd76e1eb17..13274dc3ba5 100644
--- a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java
+++ b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java
@@ -1,8 +1,8 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
-import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager;
+import com.yahoo.security.tls.ConnectionAuthContext;
+import com.yahoo.security.tls.PeerAuthorizerTrustManager;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
@@ -14,7 +14,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SocketChannel;
-import java.util.Optional;
+import java.util.Objects;
import java.util.logging.Logger;
import static javax.net.ssl.SSLEngineResult.Status;
@@ -219,9 +219,9 @@ public class TlsCryptoSocket implements CryptoSocket {
}
@Override
- public Optional<ConnectionAuthContext> getConnectionAuthContext() {
- if (handshakeState != HandshakeState.COMPLETED) return Optional.empty();
- return Optional.ofNullable(authContext);
+ public ConnectionAuthContext connectionAuthContext() {
+ if (handshakeState != HandshakeState.COMPLETED) throw new IllegalStateException("Handshake not complete");
+ return Objects.requireNonNull(authContext);
}
private boolean handshakeWrap() throws IOException {
diff --git a/jrt/tests/com/yahoo/jrt/CryptoUtils.java b/jrt/tests/com/yahoo/jrt/CryptoUtils.java
index d5ce32ee5ee..cef138ffba1 100644
--- a/jrt/tests/com/yahoo/jrt/CryptoUtils.java
+++ b/jrt/tests/com/yahoo/jrt/CryptoUtils.java
@@ -4,14 +4,14 @@ package com.yahoo.jrt;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.tls.AuthorizationMode;
+import com.yahoo.security.tls.AuthorizedPeers;
import com.yahoo.security.tls.DefaultTlsContext;
import com.yahoo.security.tls.HostnameVerification;
import com.yahoo.security.tls.PeerAuthentication;
+import com.yahoo.security.tls.PeerPolicy;
+import com.yahoo.security.tls.RequiredPeerCredential;
+import com.yahoo.security.tls.RequiredPeerCredential.Field;
import com.yahoo.security.tls.TlsContext;
-import com.yahoo.security.tls.policy.AuthorizedPeers;
-import com.yahoo.security.tls.policy.PeerPolicy;
-import com.yahoo.security.tls.policy.RequiredPeerCredential;
-import com.yahoo.security.tls.policy.RequiredPeerCredential.Field;
import javax.security.auth.x500.X500Principal;
import java.security.KeyPair;
diff --git a/jrt/tests/com/yahoo/jrt/EchoTest.java b/jrt/tests/com/yahoo/jrt/EchoTest.java
index e6243eaf4da..47c6e806635 100644
--- a/jrt/tests/com/yahoo/jrt/EchoTest.java
+++ b/jrt/tests/com/yahoo/jrt/EchoTest.java
@@ -2,7 +2,7 @@
package com.yahoo.jrt;
-import com.yahoo.security.tls.authz.ConnectionAuthContext;
+import com.yahoo.security.tls.ConnectionAuthContext;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
@@ -16,7 +16,6 @@ import java.util.List;
import static com.yahoo.jrt.CryptoUtils.createTestTlsContext;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
@@ -147,7 +146,7 @@ public class EchoTest {
for (int i = 0; i < p.size(); i++) {
r.add(p.get(i));
}
- connAuthCtx = req.target().getConnectionAuthContext().orElse(null);
+ connAuthCtx = req.target().connectionAuthContext();
}
@org.junit.Test
@@ -168,8 +167,6 @@ public class EchoTest {
if (connAuthCtxAssertion != null) {
assertNotNull(connAuthCtx);
connAuthCtxAssertion.assertConnectionAuthContext(connAuthCtx);
- } else {
- assertNull(connAuthCtx);
}
}
}
diff --git a/jrt/tests/com/yahoo/jrt/InvokeAsyncTest.java b/jrt/tests/com/yahoo/jrt/InvokeAsyncTest.java
index 5e9f426bb17..436b650198e 100644
--- a/jrt/tests/com/yahoo/jrt/InvokeAsyncTest.java
+++ b/jrt/tests/com/yahoo/jrt/InvokeAsyncTest.java
@@ -16,6 +16,7 @@ public class InvokeAsyncTest {
Supervisor client;
Target target;
Test.Barrier barrier;
+ SimpleRequestAccessFilter filter;
@Before
public void setUp() throws ListenFailedException {
@@ -23,11 +24,13 @@ public class InvokeAsyncTest {
client = new Supervisor(new Transport());
acceptor = server.listen(new Spec(0));
target = client.connect(new Spec("localhost", acceptor.port()));
+ filter = new SimpleRequestAccessFilter();
server.addMethod(new Method("concat", "ss", "s", this::rpc_concat)
.methodDesc("Concatenate 2 strings")
.paramDesc(0, "str1", "a string")
.paramDesc(1, "str2", "another string")
- .returnDesc(0, "ret", "str1 followed by str2"));
+ .returnDesc(0, "ret", "str1 followed by str2")
+ .requestAccessFilter(filter));
barrier = new Test.Barrier();
}
@@ -65,4 +68,21 @@ public class InvokeAsyncTest {
assertEquals("abcdef", req.returnValues().get(0).asString());
}
+ @org.junit.Test
+ public void testFilterIsInvoked() {
+ Request req = new Request("concat");
+ req.parameters().add(new StringValue("abc"));
+ req.parameters().add(new StringValue("def"));
+ assertFalse(filter.invoked);
+ Test.Waiter w = new Test.Waiter();
+ target.invokeAsync(req, 10, w);
+ assertFalse(w.isDone());
+ barrier.breakIt();
+ w.waitDone();
+ assertTrue(w.isDone());
+ assertFalse(req.isError());
+ assertEquals("abcdef", req.returnValues().get(0).asString());
+ assertTrue(filter.invoked);
+ }
+
}
diff --git a/jrt/tests/com/yahoo/jrt/InvokeErrorTest.java b/jrt/tests/com/yahoo/jrt/InvokeErrorTest.java
index a9a0b18b5a1..3b58ba2f42e 100644
--- a/jrt/tests/com/yahoo/jrt/InvokeErrorTest.java
+++ b/jrt/tests/com/yahoo/jrt/InvokeErrorTest.java
@@ -6,6 +6,7 @@ import org.junit.After;
import org.junit.Before;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class InvokeErrorTest {
@@ -16,6 +17,8 @@ public class InvokeErrorTest {
Supervisor client;
Target target;
Test.Barrier barrier;
+ SimpleRequestAccessFilter filter;
+ RpcTestMethod testMethod;
@Before
public void setUp() throws ListenFailedException {
@@ -23,7 +26,9 @@ public class InvokeErrorTest {
client = new Supervisor(new Transport());
acceptor = server.listen(new Spec(0));
target = client.connect(new Spec("localhost", acceptor.port()));
- server.addMethod(new Method("test", "iib", "i", this::rpc_test));
+ filter = new SimpleRequestAccessFilter();
+ testMethod = new RpcTestMethod();
+ server.addMethod(new Method("test", "iib", "i", testMethod).requestAccessFilter(filter));
server.addMethod(new Method("test_barrier", "iib", "i", this::rpc_test_barrier));
barrier = new Test.Barrier();
}
@@ -36,22 +41,8 @@ public class InvokeErrorTest {
server.transport().shutdown().join();
}
- private void rpc_test(Request req) {
- int value = req.parameters().get(0).asInt32();
- int error = req.parameters().get(1).asInt32();
- int extra = req.parameters().get(2).asInt8();
-
- req.returnValues().add(new Int32Value(value));
- if (extra != 0) {
- req.returnValues().add(new Int32Value(value));
- }
- if (error != 0) {
- req.setError(error, "Custom error");
- }
- }
-
private void rpc_test_barrier(Request req) {
- rpc_test(req);
+ testMethod.invoke(req);
barrier.waitFor();
}
@@ -157,4 +148,40 @@ public class InvokeErrorTest {
assertEquals(ErrorCode.CONNECTION, req1.errorCode());
}
+ @org.junit.Test
+ public void testFilterFailsRequest() {
+ Request r = new Request("test");
+ r.parameters().add(new Int32Value(42));
+ r.parameters().add(new Int32Value(0));
+ r.parameters().add(new Int8Value((byte)0));
+ filter.allowed = false;
+ assertFalse(filter.invoked);
+ target.invokeSync(r, timeout);
+ assertTrue(r.isError());
+ assertTrue(filter.invoked);
+ assertFalse(testMethod.invoked);
+ assertEquals(ErrorCode.PERMISSION_DENIED, r.errorCode());
+ assertEquals("Permission denied", r.errorMessage());
+ }
+
+ private static class RpcTestMethod implements MethodHandler {
+ boolean invoked = false;
+
+ @Override public void invoke(Request req) { invoked = true; rpc_test(req); }
+
+ void rpc_test(Request req) {
+ int value = req.parameters().get(0).asInt32();
+ int error = req.parameters().get(1).asInt32();
+ int extra = req.parameters().get(2).asInt8();
+
+ req.returnValues().add(new Int32Value(value));
+ if (extra != 0) {
+ req.returnValues().add(new Int32Value(value));
+ }
+ if (error != 0) {
+ req.setError(error, "Custom error");
+ }
+ }
+ }
+
}
diff --git a/jrt/tests/com/yahoo/jrt/InvokeSyncTest.java b/jrt/tests/com/yahoo/jrt/InvokeSyncTest.java
index ca7d0db129d..ec196bea47c 100644
--- a/jrt/tests/com/yahoo/jrt/InvokeSyncTest.java
+++ b/jrt/tests/com/yahoo/jrt/InvokeSyncTest.java
@@ -12,6 +12,7 @@ import java.io.IOException;
import java.io.PrintStream;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -21,6 +22,7 @@ public class InvokeSyncTest {
Acceptor acceptor;
Supervisor client;
Target target;
+ SimpleRequestAccessFilter filter;
@Before
public void setUp() throws ListenFailedException {
@@ -28,11 +30,13 @@ public class InvokeSyncTest {
client = new Supervisor(new Transport());
acceptor = server.listen(new Spec(0));
target = client.connect(new Spec("localhost", acceptor.port()));
+ filter = new SimpleRequestAccessFilter();
server.addMethod(new Method("concat", "ss", "s", this::rpc_concat)
.methodDesc("Concatenate 2 strings")
.paramDesc(0, "str1", "a string")
.paramDesc(1, "str2", "another string")
- .returnDesc(0, "ret", "str1 followed by str2"));
+ .returnDesc(0, "ret", "str1 followed by str2")
+ .requestAccessFilter(filter));
server.addMethod(new Method("alltypes", "bhilfds", "s", this::rpc_alltypes)
.methodDesc("Method taking all types of params"));
}
@@ -84,4 +88,17 @@ public class InvokeSyncTest {
assertEquals(baos.toString(), "This was alltypes. The string param was: baz\n");
}
+ @org.junit.Test
+ public void testFilterIsInvoked() {
+ Request req = new Request("concat");
+ req.parameters().add(new StringValue("abc"));
+ req.parameters().add(new StringValue("def"));
+ assertFalse(filter.invoked);
+ target.invokeSync(req, 10);
+ assertFalse(req.isError());
+ assertEquals("abcdef", req.returnValues().get(0).asString());
+ assertTrue(filter.invoked);
+ }
+
+
}
diff --git a/jrt/tests/com/yahoo/jrt/SimpleRequestAccessFilter.java b/jrt/tests/com/yahoo/jrt/SimpleRequestAccessFilter.java
new file mode 100644
index 00000000000..38d59720848
--- /dev/null
+++ b/jrt/tests/com/yahoo/jrt/SimpleRequestAccessFilter.java
@@ -0,0 +1,9 @@
+package com.yahoo.jrt;// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+/**
+ * @author bjorncs
+ */
+class SimpleRequestAccessFilter implements RequestAccessFilter {
+ volatile boolean invoked = false, allowed = true;
+ @Override public boolean allow(Request r) { invoked = true; return allowed; }
+}