diff --git a/api/src/main/java/io/grpc/ServerCall.java b/api/src/main/java/io/grpc/ServerCall.java
index d391cb5c79af..62d256f6a030 100644
--- a/api/src/main/java/io/grpc/ServerCall.java
+++ b/api/src/main/java/io/grpc/ServerCall.java
@@ -208,7 +208,20 @@ public void setMessageCompression(boolean enabled) {
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1704")
public void setCompression(String compressor) {
- // noop
+ }
+
+ /**
+ * Returns the level of security guarantee in communications
+ *
+ *
Determining the level of security offered by the transport for RPCs on server-side.
+ * This can be approximated by looking for the SSLSession, but that doesn't work for ALTS and
+ * maybe some future TLS approaches. May returns a lower security level in the face of
+ * uncertainty.
+ *
+ * @return non-{@code null} SecurityLevel enum
+ */
+ public SecurityLevel getSecurityLevel() {
+ return SecurityLevel.NONE;
}
/**
diff --git a/core/src/main/java/io/grpc/internal/ServerCallImpl.java b/core/src/main/java/io/grpc/internal/ServerCallImpl.java
index b31aadd08a9f..46ce2caaddcc 100644
--- a/core/src/main/java/io/grpc/internal/ServerCallImpl.java
+++ b/core/src/main/java/io/grpc/internal/ServerCallImpl.java
@@ -19,6 +19,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static io.grpc.internal.GrpcAttributes.ATTR_SECURITY_LEVEL;
import static io.grpc.internal.GrpcUtil.ACCEPT_ENCODING_SPLITTER;
import static io.grpc.internal.GrpcUtil.CONTENT_LENGTH_KEY;
import static io.grpc.internal.GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY;
@@ -36,6 +37,7 @@
import io.grpc.InternalDecompressorRegistry;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
+import io.grpc.SecurityLevel;
import io.grpc.ServerCall;
import io.grpc.Status;
import io.perfmark.PerfMark;
@@ -250,6 +252,15 @@ public MethodDescriptor getMethodDescriptor() {
return method;
}
+ @Override
+ public SecurityLevel getSecurityLevel() {
+ if (getAttributes() == null) {
+ return super.getSecurityLevel();
+ }
+ final SecurityLevel securityLevel = getAttributes().get(ATTR_SECURITY_LEVEL);
+ return securityLevel == null ? super.getSecurityLevel() : securityLevel;
+ }
+
/**
* Close the {@link ServerStream} because an internal error occurred. Allow the application to
* run until completion, but silently ignore interactions with the {@link ServerStream} from now
diff --git a/core/src/test/java/io/grpc/internal/ServerCallImplTest.java b/core/src/test/java/io/grpc/internal/ServerCallImplTest.java
index 9c25f4748049..160659e325ee 100644
--- a/core/src/test/java/io/grpc/internal/ServerCallImplTest.java
+++ b/core/src/test/java/io/grpc/internal/ServerCallImplTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.when;
import com.google.common.io.CharStreams;
+import io.grpc.Attributes;
import io.grpc.CompressorRegistry;
import io.grpc.Context;
import io.grpc.DecompressorRegistry;
@@ -41,6 +42,7 @@
import io.grpc.MethodDescriptor;
import io.grpc.MethodDescriptor.Marshaller;
import io.grpc.MethodDescriptor.MethodType;
+import io.grpc.SecurityLevel;
import io.grpc.ServerCall;
import io.grpc.Status;
import io.grpc.internal.ServerCallImpl.ServerStreamListenerImpl;
@@ -314,6 +316,7 @@ private void serverSendsOne_okFailsOnMissingResponse(
serverCallTracer,
PerfMark.createTag());
serverCall.close(Status.OK, new Metadata());
+
ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(Status.class);
verify(stream, times(1)).cancel(statusCaptor.capture());
assertEquals(Status.Code.INTERNAL, statusCaptor.getValue().getCode());
@@ -352,6 +355,23 @@ public void getNullAuthority() {
verify(stream).getAuthority();
}
+ @Test
+ public void getSecurityLevel() {
+ Attributes attributes = Attributes.newBuilder()
+ .set(GrpcAttributes.ATTR_SECURITY_LEVEL, SecurityLevel.INTEGRITY).build();
+ when(stream.getAttributes()).thenReturn(attributes);
+ assertEquals(SecurityLevel.INTEGRITY, call.getSecurityLevel());
+ verify(stream, times(2)).getAttributes();
+ }
+
+ @Test
+ public void getNullSecurityLevel() {
+ when(stream.getAttributes()).thenReturn(null);
+ assertEquals(SecurityLevel.NONE, call.getSecurityLevel());
+ verify(stream).getAttributes();
+ }
+
+
@Test
public void setMessageCompression() {
call.setMessageCompression(true);