diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java index fd9c55887c..123cd80a1e 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java @@ -43,6 +43,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import com.google.auth.oauth2.ComputeEngineCredentials; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.protobuf.ByteString; import com.google.protobuf.EmptyProtos.Empty; @@ -68,7 +70,6 @@ import io.grpc.testing.integration.Messages.StreamingInputCallRequest; import io.grpc.testing.integration.Messages.StreamingInputCallResponse; import io.grpc.testing.integration.Messages.StreamingOutputCallRequest; import io.grpc.testing.integration.Messages.StreamingOutputCallResponse; - import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -76,6 +77,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import java.io.IOException; +import java.io.InputStream; import java.util.Arrays; import java.util.List; import java.util.concurrent.ArrayBlockingQueue; @@ -632,6 +634,43 @@ public abstract class AbstractTransportTest { verifyNoMoreInteractions(responseObserver); } + /** Sends a large unary rpc with service account credentials. */ + public void serviceAccountCreds(String jsonKey, InputStream credentialsStream, String authScope) + throws Exception { + // cast to ServiceAccountCredentials to double-check the right type of object was created. + GoogleCredentials credentials = + (ServiceAccountCredentials) GoogleCredentials.fromStream(credentialsStream); + credentials = credentials.createScoped(Arrays.asList(authScope)); + TestServiceGrpc.TestServiceBlockingStub stub = blockingStub.configureNewStub() + .addInterceptor(new ClientAuthInterceptor(credentials, testServiceExecutor)) + .build(); + final SimpleRequest request = SimpleRequest.newBuilder() + .setFillUsername(true) + .setFillOauthScope(true) + .setResponseSize(314159) + .setResponseType(PayloadType.COMPRESSABLE) + .setPayload(Payload.newBuilder() + .setBody(ByteString.copyFrom(new byte[271828]))) + .build(); + + final SimpleResponse response = stub.unaryCall(request); + assertFalse(response.getUsername().isEmpty()); + assertTrue("Received username: " + response.getUsername(), + jsonKey.contains(response.getUsername())); + assertFalse(response.getOauthScope().isEmpty()); + assertTrue("Received oauth scope: " + response.getOauthScope(), + authScope.contains(response.getOauthScope())); + + final SimpleResponse goldenResponse = SimpleResponse.newBuilder() + .setOauthScope(response.getOauthScope()) + .setUsername(response.getUsername()) + .setPayload(Payload.newBuilder() + .setType(PayloadType.COMPRESSABLE) + .setBody(ByteString.copyFrom(new byte[314159]))) + .build(); + assertEquals(goldenResponse, response); + } + /** Sends a large unary rpc with compute engine credentials. */ public void computeEngineCreds(String serviceAccount, String oauthScope) throws Exception { ComputeEngineCredentials credentials = new ComputeEngineCredentials(); diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java index 9f8ecaf926..e6af322843 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java @@ -31,6 +31,8 @@ package io.grpc.testing.integration; +import com.google.common.io.Files; + import io.grpc.ChannelImpl; import io.grpc.testing.TestUtils; import io.grpc.transport.netty.GrpcSslContexts; @@ -39,9 +41,12 @@ import io.grpc.transport.netty.NettyChannelBuilder; import io.grpc.transport.okhttp.OkHttpChannelBuilder; import io.netty.handler.ssl.SslContext; +import java.io.File; +import java.io.FileInputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; +import java.nio.charset.Charset; import javax.net.ssl.SSLSocketFactory; @@ -85,6 +90,7 @@ public class TestServiceClient { private boolean useTestCa; private boolean useOkHttp; private String defaultServiceAccount; + private String serviceAccountKeyFile; private String oauthScope; private Tester tester = new Tester(); @@ -131,6 +137,8 @@ public class TestServiceClient { } } else if ("default_service_account".equals(key)) { defaultServiceAccount = value; + } else if ("service_account_key_file".equals(key)) { + serviceAccountKeyFile = value; } else if ("oauth_scope".equals(key)) { oauthScope = value; } else { @@ -152,9 +160,11 @@ public class TestServiceClient { + "\n --use_tls=true|false Whether to use TLS. Default " + c.useTls + "\n --use_test_ca=true|false Whether to trust our fake CA. Default " + c.useTestCa + "\n --use_okhttp=true|false Whether to use OkHttp instead of Netty. Default " - + c.useOkHttp + + c.useOkHttp + "\n --default_service_account Email of GCE default service account. Default " - + c.defaultServiceAccount + + c.defaultServiceAccount + + "\n --service_account_key_file Path to service account json key file." + + c.serviceAccountKeyFile + "\n --oauth_scope Scope for OAuth tokens. Default " + c.oauthScope ); System.exit(1); @@ -206,6 +216,10 @@ public class TestServiceClient { tester.cancelAfterFirstResponse(); } else if ("compute_engine_creds".equals(testCase)) { tester.computeEngineCreds(defaultServiceAccount, oauthScope); + } else if ("service_account_creds".equals(testCase)) { + String jsonKey = Files.toString(new File(serviceAccountKeyFile), Charset.forName("UTF-8")); + FileInputStream credentialsStream = new FileInputStream(new File(serviceAccountKeyFile)); + tester.serviceAccountCreds(jsonKey, credentialsStream, oauthScope); } else { throw new IllegalArgumentException("Unknown test case: " + testCase); }