diff --git a/binder/src/androidTest/java/io/grpc/binder/internal/BinderTransportTest.java b/binder/src/androidTest/java/io/grpc/binder/internal/BinderTransportTest.java index 5140057d72..c06bf88955 100644 --- a/binder/src/androidTest/java/io/grpc/binder/internal/BinderTransportTest.java +++ b/binder/src/androidTest/java/io/grpc/binder/internal/BinderTransportTest.java @@ -25,6 +25,7 @@ import io.grpc.ServerStreamTracer; import io.grpc.binder.AndroidComponentAddress; import io.grpc.binder.BindServiceFlags; import io.grpc.binder.BinderChannelCredentials; +import io.grpc.binder.BinderInternal; import io.grpc.binder.HostServices; import io.grpc.binder.InboundParcelablePolicy; import io.grpc.binder.SecurityPolicies; @@ -69,7 +70,7 @@ public final class BinderTransportTest extends AbstractTransportTest { BinderServer binderServer = new BinderServer(addr, executorServicePool, streamTracerFactories, - SecurityPolicies.serverInternalOnly(), + BinderInternal.createPolicyChecker(SecurityPolicies.serverInternalOnly()), InboundParcelablePolicy.DEFAULT); HostServices.configureService(addr, diff --git a/binder/src/main/java/io/grpc/binder/BinderInternal.java b/binder/src/main/java/io/grpc/binder/BinderInternal.java index 34f7793714..18af43ce2b 100644 --- a/binder/src/main/java/io/grpc/binder/BinderInternal.java +++ b/binder/src/main/java/io/grpc/binder/BinderInternal.java @@ -18,6 +18,7 @@ package io.grpc.binder; import android.os.IBinder; import io.grpc.Internal; +import io.grpc.binder.internal.BinderTransportSecurity; /** * Helper class to expose IBinderReceiver methods for legacy internal builders. @@ -31,4 +32,14 @@ public class BinderInternal { public static void setIBinder(IBinderReceiver receiver, IBinder binder) { receiver.set(binder); } + + /** + * Creates a {@link BinderTransportSecurity.ServerPolicyChecker} from a + * {@link ServerSecurityPolicy}. This exposes to callers an interface to check security policies + * without causing hard dependencies on a specific class. + */ + public static BinderTransportSecurity.ServerPolicyChecker createPolicyChecker( + ServerSecurityPolicy securityPolicy) { + return securityPolicy::checkAuthorizationForServiceAsync; + } } diff --git a/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java b/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java index eaa94bffc4..dafb884d6b 100644 --- a/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java +++ b/binder/src/main/java/io/grpc/binder/BinderServerBuilder.java @@ -23,11 +23,11 @@ import android.app.Service; import android.os.IBinder; import com.google.errorprone.annotations.DoNotCall; import io.grpc.ExperimentalApi; +import io.grpc.ForwardingServerBuilder; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.binder.internal.BinderServer; import io.grpc.binder.internal.BinderTransportSecurity; -import io.grpc.ForwardingServerBuilder; import io.grpc.internal.FixedObjectPool; import io.grpc.internal.GrpcUtil; import io.grpc.internal.ServerImplBuilder; @@ -84,7 +84,7 @@ public final class BinderServerBuilder listenAddress, schedulerPool, streamTracerFactories, - securityPolicy, + BinderInternal.createPolicyChecker(securityPolicy), inboundParcelablePolicy); BinderInternal.setIBinder(binderReceiver, server.getHostBinder()); return server; diff --git a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java index d91a487a57..66685cfdbb 100644 --- a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java +++ b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java @@ -17,6 +17,8 @@ package io.grpc.binder; import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import io.grpc.Status; import java.util.HashMap; import java.util.Map; @@ -42,18 +44,42 @@ public final class ServerSecurityPolicy { } /** - * Return whether the given Android UID is authorized to access a particular service. + * Returns whether the given Android UID is authorized to access a particular service. * - * IMPORTANT: This method may block for extended periods of time. + *
IMPORTANT: This method may block for extended periods of time. * * @param uid The Android UID to authenticate. * @param serviceName The name of the gRPC service being called. + * @deprecated Application code should not need to call this method. */ @CheckReturnValue + @Deprecated public Status checkAuthorizationForService(int uid, String serviceName) { return perServicePolicies.getOrDefault(serviceName, defaultPolicy).checkAuthorization(uid); } + /** + * Returns whether the given Android UID is authorized to access a particular service. + * + *
This method never throws an exception. If the execution of the security policy check
+ * fails, a failed future with such exception is returned.
+ *
+ * @param uid The Android UID to authenticate.
+ * @param serviceName The name of the gRPC service being called.
+ * @return a future with the result of the authorization check. A failed future represents a
+ * failure to perform the authorization check, not that the access is denied.
+ */
+ @CheckReturnValue
+ ListenableFuture This class provides the asynchronous version of {@link io.grpc.binder.SecurityPolicy},
+ * allowing implementations of authorization logic that involves slow or asynchronous calls
+ * without necessarily blocking the calling thread.
+ *
+ * @see io.grpc.binder.SecurityPolicy
+ */
+ public interface ServerPolicyChecker {
+ /**
+ * Returns whether the given Android UID is authorized to access a particular service.
+ *
+ * This method never throws an exception. If the execution of the security policy check
+ * fails, a failed future with such exception is returned.
+ *
+ * @param uid The Android UID to authenticate.
+ * @param serviceName The name of the gRPC service being called.
+ * @return a future with the result of the authorization check. A failed future represents a
+ * failure to perform the authorization check, not that the access is denied.
+ */
+ ListenableFuture