xds: add support for custom, per-target credentials on the transport.#11919
xds: add support for custom, per-target credentials on the transport.#11919AshZhang wants to merge 12 commits intogrpc:masterfrom
Conversation
…transport does nothing
| this.channel = checkNotNull(channel, "channel"); | ||
| } | ||
|
|
||
| void setCallCredentials(CallCredentials callCredentials) { |
There was a problem hiding this comment.
Why not pass this in the constructor?
There was a problem hiding this comment.
Replaced the setter with a CallCredentials parameter in the constructors. I originally used a setter here to avoid impacting GrpcXdsTransport constructor callsites (e.g. across tests), but I have updated those now.
There was a problem hiding this comment.
FWIW, you could have left the old constructors in place and them just becoming something like this(serverInfo, null). If there's only a few callsites, it is nice to update the old callsites with the new parameters. But if there are a lot, then leaving the old constructors in place is easy and simple.
| if (SharedXdsClientPoolProvider.getDefaultProvider().get(target) != null) { | ||
| return false; | ||
| } | ||
| xdsTransportCallCredentials.put(target, creds); |
There was a problem hiding this comment.
So once registered this will exist for the life of the process. Are there memory usage concerns there?
There was a problem hiding this comment.
Updated RefCountedXdsClientObjectPool to remove the (target, CallCredentials) entry when the xDS client is cleaned up at refcount 0.
There was a problem hiding this comment.
Is that what we're doing in the other languages? That actually sounds racy for this configuration, as a channel could be shutting down when you configuring the CallCreds.
| * <p>A custom {@code CallCredentials} can only be set once on the xDS transport; in other words, | ||
| * it is not possible to change the custom transport {@code CallCredentials} for an existing xDS | ||
| * client. If {@code setTransportCallCredentials} is called when there is already an existing xDS | ||
| * client for the target, then this does nothing and returns false. |
There was a problem hiding this comment.
The false return is not reliable. So we should weaken the language here a bit to say it "attempts" or "tries" to return false, or say it is "best effort".
Are the callers actually going to use the return value?
There was a problem hiding this comment.
Done, reworded the javadoc.
The return value is informational for callers to know whether their custom transport per-RPC credential is actually being used. A false return value gives clients the choice to handle it in any way - e.g. print a warning log, fail, or ignore.
…grpc#11724) Per-rpc verification of authority specified via call options or set by the LB API against peer cert's subject names.
…olProvider, and remove old creds when xDS client is deleted
| static class GrpcXdsTransport implements XdsTransport { | ||
|
|
||
| private final ManagedChannel channel; | ||
| private CallCredentials callCredentials; |
| this.channel = checkNotNull(channel, "channel"); | ||
| } | ||
|
|
||
| void setCallCredentials(CallCredentials callCredentials) { |
There was a problem hiding this comment.
FWIW, you could have left the old constructors in place and them just becoming something like this(serverInfo, null). If there's only a few callsites, it is nice to update the old callsites with the new parameters. But if there are a lot, then leaving the old constructors in place is easy and simple.
| @Override | ||
| public XdsTransport create(Bootstrapper.ServerInfo serverInfo) { | ||
| return new GrpcXdsTransport(serverInfo); | ||
| GrpcXdsTransport transport = new GrpcXdsTransport(serverInfo, callCredentials); |
There was a problem hiding this comment.
nit: return directly without the local variable since you aren't calling set() any more?
| private final Object lock = new Object(); | ||
| private final AtomicReference<Map<String, ?>> bootstrapOverride = new AtomicReference<>(); | ||
| private final Map<String, ObjectPool<XdsClient>> targetToXdsClientMap = new ConcurrentHashMap<>(); | ||
| private static final Map<String, CallCredentials> transportCallCredentials = |
There was a problem hiding this comment.
This class is already a singleton/has a default instance. Make this non-static.
| if (SharedXdsClientPoolProvider.getDefaultProvider().get(target) != null) { | ||
| return false; | ||
| } | ||
| xdsTransportCallCredentials.put(target, creds); |
There was a problem hiding this comment.
Is that what we're doing in the other languages? That actually sounds racy for this configuration, as a channel could be shutting down when you configuring the CallCreds.
| @@ -35,34 +36,45 @@ | |||
| final class GrpcXdsTransportFactory implements XdsTransportFactory { | |||
|
|
|||
| static final GrpcXdsTransportFactory DEFAULT_XDS_TRANSPORT_FACTORY = | |||
There was a problem hiding this comment.
Move this into the tests that use it? It isn't used any more in production. (I probably wouldn't make it a CONSTANT like it is here, at it is no longer the DEFAULT and such. I'd probably just create a new instance when needed.)
|
Closing this as we are going to use |
Add support for custom, per-target (per-RPC) credentials on the xDS transport.
This allows clients to use different credentials when requesting xDS resources for different targets that may require different authorization tokens to access.
To use a custom credential on the transport during resolution, the application is responsible for associating a
CallCredentialsobject with a target inXdsTransportCallCredentialsProvider. The application then creates a channel to the target as usual, and the xDS client library takes care of looking up the correctCallCredentialsobject to use when resolving the target.A custom per-target credential can only be set once for the channel / xDS transport, so it must be added to
XdsTransportCallCredentialsProviderbefore creating the channel for the target. If called when there is already an existing channel for the target,XdsTransportCallCredentialsProvider.setTransportCallCredentials()will ignore theCallCredentialsobject that was newly passed in.