-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
xds: add support for custom, per-target credentials on the transport. #11919
Conversation
…transport does nothing
@@ -65,14 +77,19 @@ public GrpcXdsTransport(ManagedChannel channel) { | |||
this.channel = checkNotNull(channel, "channel"); | |||
} | |||
|
|||
void setCallCredentials(CallCredentials callCredentials) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not pass this in the constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
xds/src/main/java/io/grpc/xds/XdsTransportCallCredentialsProvider.java
Outdated
Show resolved
Hide resolved
if (SharedXdsClientPoolProvider.getDefaultProvider().get(target) != null) { | ||
return false; | ||
} | ||
xdsTransportCallCredentials.put(target, creds); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
xds/src/main/java/io/grpc/xds/XdsTransportCallCredentialsProvider.java
Outdated
Show resolved
Hide resolved
…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
} | ||
|
||
@VisibleForTesting | ||
static class GrpcXdsTransport implements XdsTransport { | ||
|
||
private final ManagedChannel channel; | ||
private CallCredentials callCredentials; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
@@ -65,14 +77,19 @@ public GrpcXdsTransport(ManagedChannel channel) { | |||
this.channel = checkNotNull(channel, "channel"); | |||
} | |||
|
|||
void setCallCredentials(CallCredentials callCredentials) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: return directly without the local variable since you aren't calling set() any more?
@@ -59,6 +59,8 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
CallCredentials
object 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 correctCallCredentials
object 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
XdsTransportCallCredentialsProvider
before creating the channel for the target. If called when there is already an existing channel for the target,XdsTransportCallCredentialsProvider.setTransportCallCredentials()
will ignore theCallCredentials
object that was newly passed in.