我已将一台gRPC服务器部署到Google Cloud Run(完全托管),并将“必需的身份验证”选项设置为true。
我正在尝试通过Google服务帐户对来自gRPC客户端的调用进行身份验证,但是我总是遇到异常。
Exception in thread "main" io.grpc.StatusRuntimeException: UNAUTHENTICATED: HTTP status code 401
下面是我创建gRPC频道并附加服务帐户的方式。
public GrpcClient(Channel channel) throws IOException {
Credentials credentials = GoogleCredentials.getApplicationDefault();
blockingStub = CalculatorServiceGrpc
.newBlockingStub(channel)
.withCallCredentials(MoreCallCredentials.from(credentials));
}
不好意思:env var GOOGLE_APPLICATION_CREDENTIALS设置了SA的路径,并且该SA具有Cloud Run Invoker特权
有什么我想念的吗?
答案 0 :(得分:1)
从通用HTTP客户端调用Cloud Run服务器时,设置GOOGLE_APPLICATION_CREDENTIALS
无效。 (仅在您使用Google客户端库调用Google API时有效。)
即使将gRPC部署到Cloud Run,它也只是HTTP / 2,因此在Service-to-Service Authentication页上记录了对Cloud Run服务的身份验证。简而言之,这涉及到:
Authorization: Bearer [[ID_TOKEN]]
。在gRPC中,标头称为“元数据”,因此您应该找到等效的gRPC Java方法进行设置。 (这可能是每个RPC选项。)
阅读有关Go example here的内容,它基本上向您说明,在Cloud Run上运行的gRPC服务器仍以相同的方式进行身份验证。在这种情况下,还要确保告诉Java:
答案 1 :(得分:1)
经过更多研究,我能够使用IdTokenCredentials对请求进行身份验证。参见下面的结果。
public GrpcClient(Channel channel) throws IOException {
ServiceAccountCredentials saCreds = ServiceAccountCredentials
.fromStream(new FileInputStream("path\to\sa"));
IdTokenCredentials tokenCredential = IdTokenCredentials.newBuilder().setIdTokenProvider(saCreds)
.setTargetAudience("https://{projectId}-{hash}-uc.a.run.app").build();
blockingStub = CalculatorServiceGrpc
.newBlockingStub(channel)
.withCallCredentials(MoreCallCredentials.from(tokenCredential));
}