Skip to content

Conversation

@amanda-tarafa
Copy link
Contributor

Towards #2033.

Also refactors the existing external account credential tests to make it easier to reuse test code.

FYI: @lsirac, @jpassing , @moserware

@amanda-tarafa amanda-tarafa requested a review from jskeet September 9, 2022 22:47
@amanda-tarafa amanda-tarafa requested a review from a team as a code owner September 9, 2022 22:47
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.

Various nits and a few questions, but basically fine as far as I can see - I'm not a subject-matter expert on this though.

get => new TheoryData<string, Type>
{
{ DummyUrlSourcedExternalAccountCredentialFileContents, typeof(UrlSourcedExternalAccountCredential) },
{ DummyFileSourcedExternalAccountCredentialFileContents, typeof (FileSourcedExternalAccountCredential) },
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: remove space after typeof. (I wouldn't have noticed it if it hadn't been for the inconsistency with the one above.

Copy link
Collaborator

Choose a reason for hiding this comment

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

(Note: both of these comments apply twice below as well.)


[Fact]
public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential()
public static TheoryData<string, Type> ExternalAccountCredentialTestData
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just make this expression-bodied?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, on all three

Assert.Contains($"subject_token={SubjectTokenText}", contentText);
Assert.Contains($"scope={scope}", contentText);

return new HttpResponseMessage
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd probably do the serialization in a separate statement above, then just return new HttpResponseMessage { Content = new StringContent(content, Encoding.UTF8) }; - aside from anything else, that's simpler when debugging.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Given all the code below, it might also be worth extracting new HttpResponseMessage { Content = new StringContent(content, Encoding.UTF8) } into a helper method.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In fact, we might want a helper method to do everything - just given the access token and expiry, as that's all that really seems to vary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

{
accessToken = ImpersonatedAccessToken,
expireTime = "2020-05-13T16:00:00.045123456Z"
}))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This one doesn't specify UTF-8 - is that relevant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After extracting it does, not sure if it was default already.

/// <inheritdoc/>
protected override Task<string> GetSubjectTokenAsync(CancellationToken taskCancellationToken)
{
var fileContent = File.ReadAllText(SubjectTokenFilePath);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we definitely want to read the file here, rather than in the constructor? What's the expected behavior if this file changes over time?

Copy link
Contributor

Choose a reason for hiding this comment

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

The file content can change at any time, so I think it's correct to read the file here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it is expected that the subject token may be refreshed and the refreshed subject token should be used each time.

I had this question in general for subject tokens, regardless of whether they are URL or file or otherwise sourced, they can always change, on every access token refresh the subject tokens should be requested anew.

}
else
{
var jsonResponse = NewtonsoftJsonSerializer.Instance.Deserialize<Dictionary<string, string>>(fileContent);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we okay with this failing with a Json.NET-specific error if the field doesn't exist, or isn't a string?

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'll wrap the exceptions from here on the parent class, as we could also get IOExceptions if the file is not present, etc. I've added tests as well for both credentials.

/// <inheritdoc/>
protected override Task<string> GetSubjectTokenAsync(CancellationToken taskCancellationToken)
{
var fileContent = File.ReadAllText(SubjectTokenFilePath);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is an async method, so you could read the file asynchronously too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no File.ReadAllTextAsync pre .NET 7 (which surprised me a little) and I prefered code simplicity. But yes, changing now...

/// <inheritdoc/>
protected override Task<string> GetSubjectTokenAsync(CancellationToken taskCancellationToken)
{
var fileContent = File.ReadAllText(SubjectTokenFilePath);
Copy link
Contributor

Choose a reason for hiding this comment

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

The file content can change at any time, so I think it's correct to read the file here.

Copy link
Contributor Author

@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 addressed all review comments, PTAL.


[Fact]
public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential()
public static TheoryData<string, Type> ExternalAccountCredentialTestData
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, on all three

/// <inheritdoc/>
protected override Task<string> GetSubjectTokenAsync(CancellationToken taskCancellationToken)
{
var fileContent = File.ReadAllText(SubjectTokenFilePath);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it is expected that the subject token may be refreshed and the refreshed subject token should be used each time.

I had this question in general for subject tokens, regardless of whether they are URL or file or otherwise sourced, they can always change, on every access token refresh the subject tokens should be requested anew.

/// <inheritdoc/>
protected override Task<string> GetSubjectTokenAsync(CancellationToken taskCancellationToken)
{
var fileContent = File.ReadAllText(SubjectTokenFilePath);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no File.ReadAllTextAsync pre .NET 7 (which surprised me a little) and I prefered code simplicity. But yes, changing now...

}
else
{
var jsonResponse = NewtonsoftJsonSerializer.Instance.Deserialize<Dictionary<string, string>>(fileContent);
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'll wrap the exceptions from here on the parent class, as we could also get IOExceptions if the file is not present, etc. I've added tests as well for both credentials.

Assert.Contains($"subject_token={SubjectTokenText}", contentText);
Assert.Contains($"scope={scope}", contentText);

return new HttpResponseMessage
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

{
accessToken = ImpersonatedAccessToken,
expireTime = "2020-05-13T16:00:00.045123456Z"
}))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

After extracting it does, not sure if it was default already.

{
return await GetSubjectTokenAsyncImpl(taskCancellationTokne).ConfigureAwait(false);
}
catch(Exception ex)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Micro-nit: space before (

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. I'll rebase all and merge after green! Thanks.

@amanda-tarafa amanda-tarafa merged commit d584dc7 into googleapis:main Sep 14, 2022
@amanda-tarafa amanda-tarafa deleted the wif-file-based branch September 14, 2022 09:01
amanda-tarafa added a commit to amanda-tarafa/google-api-dotnet-client that referenced this pull request Oct 18, 2022
Features
- googleapis#2228 Supports Quota Project environment variable for ADC.
- googleapis#2219 Removes obsolete OOB code.
   BREAKING CHANGE: We have removed OOB support from the library because the feature is not supported by Google OAuth as of October 3rd 2022. See the [official announcement](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob) for more information.
- googleapis#2216 Log errors when trying to reach Compute's metadata server.
- googleapis#2177, googleapis#2197, googleapis#2200, googleapis#2206, googleapis#2215, googleapis#2235 Support for Workload Identity Federation and Worforce Identity Federation.
- googleapis#2103 Compute credentials support explicit scopes.
- googleapis#2096 Improves deserialization error handling.
amanda-tarafa added a commit that referenced this pull request Oct 18, 2022
Features
- #2228 Supports Quota Project environment variable for ADC.
- #2219 Removes obsolete OOB code.
   BREAKING CHANGE: We have removed OOB support from the library because the feature is not supported by Google OAuth as of October 3rd 2022. See the [official announcement](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob) for more information.
- #2216 Log errors when trying to reach Compute's metadata server.
- #2177, #2197, #2200, #2206, #2215, #2235 Support for Workload Identity Federation and Worforce Identity Federation.
- #2103 Compute credentials support explicit scopes.
- #2096 Improves deserialization error handling.
amanda-tarafa added a commit to amanda-tarafa/google-api-dotnet-client that referenced this pull request Nov 30, 2022
And support version: 1.58.0-beta02 => 1.58.0

Bug fixes:

- googleapis#2273 Don't attempt to use an empty/null media type in batch responses
- googleapis#2251 Which fixes a typo on then name of one of the AWS Credential environment variables.
- googleapis#2264 Which adds a missing line break in AWS Credential canonical request.

Features
- googleapis#2269 Support per-request max retry configuration.
- googleapis#2228 Supports Quota Project environment variable for ADC.
- googleapis#2219 Removes obsolete OOB code. BREAKING CHANGE: We have removed OOB support from the library because the feature is not supported by Google OAuth as of October 3rd 2022. See the [official announcement](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob) for more information.
- googleapis#2216 Log errors when trying to reach Compute's metadata server.
- googleapis#2177, googleapis#2197, googleapis#2200, googleapis#2206, googleapis#2215, googleapis#2235 Support for Workload Identity Federation and Worforce Identity Federation.
- googleapis#2103 Compute credentials support explicit scopes.
- googleapis#2096 Improves deserialization error handling.
amanda-tarafa added a commit to amanda-tarafa/google-api-dotnet-client that referenced this pull request Nov 30, 2022
And support version: 1.58.0-beta02 => 1.58.0

Dependencies:

- Client libraries no longer target netstandard1.0 or net40.

Bug fixes:

- googleapis#2273 Don't attempt to use an empty/null media type in batch responses
- googleapis#2251 Which fixes a typo on then name of one of the AWS Credential environment variables.
- googleapis#2264 Which adds a missing line break in AWS Credential canonical request.

Features
- googleapis#2269 Support per-request max retry configuration.
- googleapis#2228 Supports Quota Project environment variable for ADC.
- googleapis#2219 Removes obsolete OOB code. BREAKING CHANGE: We have removed OOB support from the library because the feature is not supported by Google OAuth as of October 3rd 2022. See the [official announcement](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob) for more information.
- googleapis#2216 Log errors when trying to reach Compute's metadata server.
- googleapis#2177, googleapis#2197, googleapis#2200, googleapis#2206, googleapis#2215, googleapis#2235 Support for Workload Identity Federation and Worforce Identity Federation.
- googleapis#2103 Compute credentials support explicit scopes.
- googleapis#2096 Improves deserialization error handling.
amanda-tarafa added a commit that referenced this pull request Nov 30, 2022
And support version: 1.58.0-beta02 => 1.58.0

Dependencies:

- Client libraries no longer target netstandard1.0 or net40.

Bug fixes:

- #2273 Don't attempt to use an empty/null media type in batch responses
- #2251 Which fixes a typo on then name of one of the AWS Credential environment variables.
- #2264 Which adds a missing line break in AWS Credential canonical request.

Features
- #2269 Support per-request max retry configuration.
- #2228 Supports Quota Project environment variable for ADC.
- #2219 Removes obsolete OOB code. BREAKING CHANGE: We have removed OOB support from the library because the feature is not supported by Google OAuth as of October 3rd 2022. See the [official announcement](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html#disallowed-oob) for more information.
- #2216 Log errors when trying to reach Compute's metadata server.
- #2177, #2197, #2200, #2206, #2215, #2235 Support for Workload Identity Federation and Worforce Identity Federation.
- #2103 Compute credentials support explicit scopes.
- #2096 Improves deserialization error handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants