Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I apply a io.grpc.CallCredentials to ServiceOptions? #18

Closed
Capstan opened this issue Sep 30, 2019 · 10 comments · Fixed by #26
Closed

How do I apply a io.grpc.CallCredentials to ServiceOptions? #18

Capstan opened this issue Sep 30, 2019 · 10 comments · Fixed by #26
Assignees
Labels
api: spanner type: feature request

Comments

@Capstan
Copy link

@Capstan Capstan commented Sep 30, 2019

I have a private class that generates io.grpc.CallCredentials to authorize to Cloud Spanner. Apparently the ServiceOptions.Builder.setCredentials only knows about com.google.auth.Credentials. I know that the Cloud Spanner communication is done over gRPC. Is there a way to apply my CallCredentials?

@olavloite olavloite self-assigned this Oct 1, 2019
@olavloite
Copy link
Contributor

@olavloite olavloite commented Oct 1, 2019

I assume that you are using the Spanner client library, as you are referencing the ServiceOptions.Builder.setCredentials method.

The short answer for the Spanner client library is: No, that is currently not possible.

The slightly longer answer:
io.grpc.CallCredentials can be used to specify credentials per gRPC call. The Spanner client library currently only supports using one set of credentials that will be used for all gRPC calls that will be executed by a com.google.cloud.spanner.Spanner instance, as the actual gRPC calls are hidden from the user. Calling the method com.google.cloud.spanner.DatabaseClient.readWriteTransaction() could for example trigger several gRPC calls to create a session and start the actual transaction before control is handed back to the caller. The client library therefore expects the user to supply a static set of credentials when the com.google.cloud.spanner.Spanner instance is created.

Based on your question however, I do assume that it is not your goal specify different credentials per gRPC call, but that you would just like to use the io.grpc.CallCredentials that you already have to create a com.google.cloud.spanner.Spanner instance. Is that assumption correct? Or do you actually want to use different credentials for different gRPC calls?

@Capstan
Copy link
Author

@Capstan Capstan commented Oct 1, 2019

Your assumption is correct. It's a static principal, but not a static set of credentials, since refreshing may occur between underlying retries behind the gRPC stub.

@olavloite
Copy link
Contributor

@olavloite olavloite commented Oct 2, 2019

I'm not sure I understand what you mean with your last comment. If you provide credentials through the normal SpannerOptions#setCredentials(Credentials) method, the client library will take care of refreshing any access tokens when that is necessary, so as a consumer of the library you don't have to worry about this.

Could you explain a little bit more in detail what the reason is that you want to use io.grpc.CallCredentials instead of just supplying a static set of credentials?

@Capstan
Copy link
Author

@Capstan Capstan commented Oct 2, 2019

There are several bespoke things going on here, primarily in Google's monorepo:

  • Since we're primarily a direct RPC-using shop, we support extensions to the default gRPC stubs that allow configurable behavior that happens below the stub for all stubs. This includes things like retry policies, shedding load based on server monitoring, request hedging. These are stock behaviors before anyone piles on thick clients, e.g., Cloud Spanner, on top of RPC servers.
  • Google, internally, has a slightly different authentication system, so OAuth tokens aren't what we're using, and we take care to ensure people aren't using OAuth for non-public APIs.
  • Between these two, the RPC stub extension mechanism is very restrictive about what kinds of creds it supports, e.g., so clients don't pass in some static, non-refreshable token, and that they don't pass in the wrong type of auth. This is done by type checking and bazel BUILD visibility limits to ensure reviews occur.

So, whether or not a client library does some intelligence above the gRPC stub, we still are limited in what the underlying substrate will accept. What we have is an internal type that passes the type check and supports io.grpc.CallCredentials, and there's no current way to assign that credential in to the spanner client.

I've not been able to track how a GoogleDefaultCredentials eventually gets exchanged into a io.grpc.auth.GoogleAuthLibraryCallCredentials, but if I knew how that worked, I could likely build the equivalent for our Guarded CallCredentials that would be built via a new Guarded Credentials which would implement com.google.auth.Credentials.

@Capstan
Copy link
Author

@Capstan Capstan commented Oct 2, 2019

This might be a byproduct of MoreCallCredentials.from, which as a static method, doesn't allow the Credentials to determine anything about the final type.

olavloite referenced this issue in olavloite/google-cloud-java Oct 3, 2019
Allow the user to supply io.grpc.CallCredentials instead
of only com.google.auth.Credentials. Any CallCredentials
supplied will take precedence above the Credentials set on
SpannerOptions.

Fixes #6373
@olavloite
Copy link
Contributor

@olavloite olavloite commented Oct 3, 2019

@Capstan Would the proposed change in googleapis/google-cloud-java#6426 solve your problem? It adds the possibility of setting a CallCredentialsProvider on the SpannerOptions. See L348 of GapicSpannerRpcTest for an example on how to use it.

@Capstan
Copy link
Author

@Capstan Capstan commented Oct 4, 2019

That looks good, yes. I need to forward this to my colleague who'd be consuming it.

@Capstan
Copy link
Author

@Capstan Capstan commented Oct 4, 2019

/cc @tsalomie

@chingor13 chingor13 transferred this issue from googleapis/google-cloud-java Jan 7, 2020
@chingor13 chingor13 added the type: feature request label Jan 7, 2020
olavloite added a commit that referenced this issue Jan 10, 2020
Adds support for using CallCredentials that could vary per call
instead of only static credentials passed in at startup.

Fixes #18
@olavloite
Copy link
Contributor

@olavloite olavloite commented Jan 13, 2020

/cc @Capstan Could you (and your colleague) have a look at #26?

@Capstan
Copy link
Author

@Capstan Capstan commented Jan 13, 2020

olavloite added a commit that referenced this issue Jan 14, 2020
* feat: add support for CallCredentials

Adds support for using CallCredentials that could vary per call
instead of only static credentials passed in at startup.

Fixes #18

* fix: declare dependency usage
@google-cloud-label-sync google-cloud-label-sync bot added the api: spanner label Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner type: feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants