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

feat: add impersonated credential support #1838

Merged
merged 25 commits into from
May 11, 2021

Conversation

arithmetic1728
Copy link
Contributor

@arithmetic1728 arithmetic1728 commented Apr 19, 2021

This PR adds impersonated credential support. ImpersonatedCredentials allowing credentials issued to a user or service account to impersonate another service account.The cloud reference is: https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials#sa-credentials-oauth. (Googlers see go/dotnet-auth-impersonated-creds for the design doc.)

The following shows how to create an impersonated credential.

# Start with a GoogleCredential which wraps either user credential or service account credential
var sourceCredential = GoogleCredential.FromFile("service_account_json_path");

# Create an impersonated credential which allows the source credential to impersonate the targetPrincipal service account.
var credential = sourceCredential.Impersonate(targetPrincipal, delegates, scopes, lifetimeInSeconds);

Then you can use it to get access token and id token the same way as you do for other types of GoogleCredential.

To sign bytes.

var signedBytes = await (credential.UnderlyingCredential as ImpersonatedCredential).SignBytes(bytesToSign);

@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Apr 19, 2021
@arithmetic1728 arithmetic1728 marked this pull request as ready for review April 19, 2021 23:42
Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

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

First pass - these are mostly nits for formatting etc... I'd need another pass to really check the impersonation-specific logic.

@jskeet
Copy link
Collaborator

jskeet commented Apr 20, 2021

I've suggested that @amanda-tarafa holds off on reviewing this until you've had a chance to work through this first round of review comments, btw. I'm not perturbed by there being a lot of comments - that's normally the way for new contributors to any code base, so please don't consider it any sort of personal judgement :)

@amanda-tarafa
Copy link
Contributor

Can you please, as part of this PR, move #1312 out of the backlog. And then just reopen it and assign it to you. Thanks!

@arithmetic1728
Copy link
Contributor Author

Can you please, as part of this PR, move #1312 out of the backlog. And then just reopen it and assign it to you. Thanks!

@amanda-tarafa I moved #1840 out of backlog in this PR. Please reopen it and assign to me since I don't have write permission to do so. Thanks!

@arithmetic1728
Copy link
Contributor Author

@jskeet Thank you for all the comments and suggestions! They are super helpful! :) PTAL.

Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

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

A few more comments... I haven't validated all the changes, but Amanda will have another look anyway before we're done.

Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

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

A couple of nits left, but I think we're nearly there. Amanda may well find things I missed though :)

Copy link
Contributor

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

I've left some specific comments but I'd also like to explore the possibility of adding an IBlogSigner interface, that can be implemented by ImpersonatedCredential and ServiceAccountCredential and GoogleCredential. GoogleCredential checks first for the underlying credential being an IBlobSigner, else it fails (similiar to OIdc). In that way:
a) The user doesn't have to cast the underlying credential to ImpersonatedCredential which is always a bad user experience.
b) We make more discoverable the capability of ServiceAccountCredential for signing.
c) We don't have to make ImpersonatedCredential public.

@arithmetic1728
Copy link
Contributor Author

@amanda-tarafa PTAL, thanks!

Copy link
Contributor

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

Most comments are just nits. Thanks!

Comment on lines 106 to 110
var body = NewtonsoftJsonSerializer.Instance.Serialize(bodyJson);
var content = new StringContent(body, Encoding.UTF8, "application/json");

var response = await HttpClient.PostAsync(TokenServerUrl, content, taskCancellationToken).ConfigureAwait(false);
var newToken = await TokenResponse.FromHttpResponseAsync(response, Clock, Logger).ConfigureAwait(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

See TokenRequestExtensions. I think you can add similar extension methods there for ImpersonationAccessTokenRequest, and reuse ParameterUtils as well so you don't need to do any of this here.
Same for the other requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure if this is necessary. This basically means moving these methods to TokenRequestExtensions class. ParameterUtils won't be used because it url encodes the body instead of using json format.

Audience = oidcTokenOptions.TargetAudience,
IncludeEmail = true
};
var body = NewtonsoftJsonSerializer.Instance.Serialize(bodyJson);
Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment above for adding extension methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same as above

Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs Outdated Show resolved Hide resolved
Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs Outdated Show resolved Hide resolved
arithmetic1728 and others added 10 commits May 6, 2021 15:46
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
arithmetic1728 and others added 3 commits May 6, 2021 16:44
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Copy link
Contributor

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

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

LGTM. Just a few more nits.

@jskeet check my suggestion for the summary of ImpersonatedCredential.

I will address the setting of the bearer token on the HttpClient in a separate PR, since I have to refactor those bits anyway as part of #1851

namespace Google.Apis.Auth.OAuth2
{
/// <summary>
/// ImpersonatedCredentials allowing credentials issued to a user or service account to impersonate
Copy link
Contributor

Choose a reason for hiding this comment

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

This class is internal now, so the description is slightly less important. I'm leaving a suggestions with what I think could acceptable, @jskeet what do you think?

Src/Support/Google.Apis.Auth/OAuth2/IBlobSigner.cs Outdated Show resolved Hide resolved
arithmetic1728 and others added 7 commits May 11, 2021 09:40
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com>
@amanda-tarafa
Copy link
Contributor

I'll merge now. We can do a release once I'm done with #1851. I'll try to have that done this week.

@amanda-tarafa amanda-tarafa merged commit 6b29aa0 into googleapis:master May 11, 2021
@arithmetic1728
Copy link
Contributor Author

@amanda-tarafa Thank you!

amanda-tarafa added a commit to amanda-tarafa/google-api-dotnet-client that referenced this pull request Jun 15, 2021
Features
* googleapis#1832 Helper for loading Client Secrets directly from file.
* googleapis#1838 and googleapis#1874 Support for credential impersonation.
* googleapis#1851 Make it easier to configure a credential's HTTP client, in particular it's now easier to set a proxy to be used for token fetching.
Fixes
* googleapis#1874 ServiceAccountCredential should copy scopes from initializer.
Dependencies
* googleapis#1842 System.Net.Http to 4.3.4
* googleapis#1873 Add target for .NET 4.6.1
amanda-tarafa added a commit to amanda-tarafa/google-api-dotnet-client that referenced this pull request Jun 15, 2021
Features
* googleapis#1832 Helper for loading Client Secrets directly from file.
* googleapis#1838 and googleapis#1874 Support for credential impersonation.
* googleapis#1851 Make it easier to configure a credential's HTTP client, in particular it's now easier to set a proxy to be used for token fetching.

Fixes
* googleapis#1874 ServiceAccountCredential should copy scopes from initializer.

Dependencies
* googleapis#1842 System.Net.Http to 4.3.4
* googleapis#1873 Add target for .NET 4.6.1
amanda-tarafa added a commit that referenced this pull request Jun 15, 2021
Features
* #1832 Helper for loading Client Secrets directly from file.
* #1838 and #1874 Support for credential impersonation.
* #1851 Make it easier to configure a credential's HTTP client, in particular it's now easier to set a proxy to be used for token fetching.

Fixes
* #1874 ServiceAccountCredential should copy scopes from initializer.

Dependencies
* #1842 System.Net.Http to 4.3.4
* #1873 Add target for .NET 4.6.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants