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);