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

Add Channel Credentials #7294

Merged
merged 6 commits into from Oct 7, 2020
Merged

Add Channel Credentials #7294

merged 6 commits into from Oct 7, 2020

Conversation

ejona86
Copy link
Member

@ejona86 ejona86 commented Aug 6, 2020

Since this is huge I'm very willing to split this into multiple PRs and have this be an "overview" of all the changes. My main concern with that is how many back-and-forths that may require, since so much of this is connected and the commit "Migrate users of ManagedChannelBuilder.{forTarget,forAddress} to ChannelCredentials" is important to see how this plays out in real code. I'd suggest "skipping ahead" and looking at that commit first.

Notably, it is annoying to have to remember which ChannelCredentials have public constructors and which have a create() method. I think it would probably be best to get rid of the public constructors and always have create()/newBuilder(). If I did that, then it's not 100% clear to me whether we should have create() return ChannelCredentials or the concrete type (e.g., TlsChannelCredentials). ChannelCredentials should be fully adequate for the producers of the credentials (the application) and might make it easier to migrate the internal credential implementations. The best example of this is OkHttp's SslSocketFactoryChannelCredentials; it seemed beneficial to hide the internal data structure to allow it to morph over time. That doesn't really apply the same to the credentials in io.grpc though.

if (CheckGcpEnvironment.isOnGcp()) {
callCredentials = MoreCallCredentials.from(ComputeEngineCredentials.create());
} else {
callCredentials = new FailingCallCredentials(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have been meaning to ask this. I understand this matches the old behavior but if you are not on Gcp is there a reason to fail each call instead of failing channel creation? Wouldn't it be better to fail early when the environment is wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't tend to fail channel creation based on I/O; we do it when you use the API incorrectly. So I think we did it this way to fail in the normal way we fail for I/O.

try {
callCredentials = MoreCallCredentials.from(GoogleCredentials.getApplicationDefault());
} catch (IOException e) {
// TODO(ejona): Should this just throw?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I commented elsewhere throwing sounds better than FailingCallCredentials unless you want to match existing behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other case is a bit different. We can check if we're on GCP by looking at the BIOS information, which would be pretty quick and reliable. And ComputeEngineCredentials doesn't do any I/O when created.

In this case getApplicationDefault() itself does network I/O and can fail for reasons other than misconfiguration. It seems wrong to permanently break a channel in the case of that failure without providing a good way for users to manage the error themselves. So that's why I suggested throwing here.

Actually, I guess there is another option here: create CallCredentials that call getApplicationDefault() as part of its loading of credentials and if it fails it could continue retrying.

In either case, though, I don't think it is appropriate to change the behavior in this PR. And we probably can't change the existing builder. But we do really want to decide the API for GoogleDefaultChannelCredentials before stabilizing it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we shall also call CheckGcpEnvironment.isOnGcp() for GoogleDefaultChannelCredentials.

Do we expect caller of GoogleDefaultChannelCredentials outside GCP? It is not safe to call ALTS without GCP platform check.

If we do plan to support GoogleDefaultChannelCredentials outside GCP, we can do platform check, if running outside GCP, disable ALTS, only TLS is allowed. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we expect caller of GoogleDefaultChannelCredentials outside GCP? It is not safe to call ALTS without GCP platform check.

Absolutely we do. In that case we won't get any gRPCLB addresses and so won't trigger the ALTS code path.

The entire point of GoogleDefaultChannelCredentials (which mirrors C core) is to auto-select the proper credentials to use when communicating with Google independent of where you are. Just like GoogleCredentials.getApplicationDefault().

In any case, I do not want to change existing behavior in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, google_default_credentials in c core can only be run on GCP. Agree this PR should not change existing behavior.
It is reasonable to not perform GCP check for GoogleDefaultCredentials, as we trust DNS to signal if we enable ALTS or not. If GDC runs outside GCP, ALTS code path won't be triggered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ComputeEngineChannelCredentials is the one restricted to GCP. No reason to restrict GoogleDefaultChannelCredentials to GCP (similar to the behavior of GoogleDefaultChannelBuilder)

@jiangtaoli2016
Copy link
Contributor

@ejona86 Thanks much for implementation! Security team is long waiting for this PR.

@sanjaypujare
Copy link
Contributor

Finished this round of review. It will also be good to resolve the merge conflicts that exist now.

@ejona86
Copy link
Member Author

ejona86 commented Oct 2, 2020

@sanjaypujare, I've pushed individual commits with the changes. I'm working on rebasing next, but when I do so it will be harder to see what new changes I've made.

I also still need to update the TODO experimental APIs to their actual URL.

@sanjaypujare
Copy link
Contributor

@sanjaypujare, I've pushed individual commits with the changes. I'm working on rebasing next, but when I do so it will be harder to see what new changes I've made.

I also still need to update the TODO experimental APIs to their actual URL.

Okay. I went thru the latest changes/comments and added a few comments myself. Will take a look again once the new changes are in.

Copy link
Contributor

@sanjaypujare sanjaypujare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

AltsChannelBuilder could be improved a bit more by removing the call to
InternalNettyChannelBuilder.setProtocolNegotiatorFactory. However, to do
that cleanest would require reworking how port is plumbed in
NettyChannelBuilder and potentially AbstractManagedChannelImplBuilder to
move getDefaultPort() to ProtocolNegotiator from ClientFactory. Saving
that for another day.
@ejona86 ejona86 merged commit a547e23 into grpc:master Oct 7, 2020
@ejona86 ejona86 deleted the channelcreds branch October 7, 2020 18:58
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants