Skip to content

feat(auth): add external account url sourced credentials #2217

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

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

alvarowolfx
Copy link
Collaborator

Fixes #2079

@alvarowolfx alvarowolfx requested a review from sai-sunder-s May 19, 2025 18:00
Copy link

codecov bot commented May 19, 2025

Codecov Report

Attention: Patch coverage is 83.56164% with 12 lines in your changes missing coverage. Please review.

Project coverage is 89.58%. Comparing base (9bb3c6e) to head (e4601c2).
Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
...ls/external_account_sources/url_sourced_account.rs 70.83% 7 Missing ⚠️
src/auth/src/credentials/external_account.rs 90.90% 4 Missing ⚠️
src/auth/src/credentials.rs 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2217      +/-   ##
==========================================
+ Coverage   89.08%   89.58%   +0.49%     
==========================================
  Files          62       64       +2     
  Lines        2392     2449      +57     
==========================================
+ Hits         2131     2194      +63     
+ Misses        261      255       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +127 to +131
let token = Token {
token: token_res.access_token,
token_type: token_res.token_type,
expires_at: Some(Instant::now() + Duration::from_secs(token_res.expires_in)),
metadata: None,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can We instead make the exchange_token method return the Token itself?

Copy link
Collaborator

@coryan coryan left a comment

Choose a reason for hiding this comment

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

The copyright year nits are blocking. I have not done an in-depth review either, not that you should need one, just letting you know.

Copy link
Collaborator

@coryan coryan left a comment

Choose a reason for hiding this comment

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

Please restore the copyright year for credentials.rs the rest of my comments are just suggestions.

@coryan coryan marked this pull request as ready for review May 20, 2025 20:41
@coryan coryan requested a review from a team as a code owner May 20, 2025 20:41
coryan
coryan previously approved these changes May 20, 2025
Copy link
Collaborator

@coryan coryan left a comment

Choose a reason for hiding this comment

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

I don't have substantive suggestions, lots of nits, so approved.

@@ -17,6 +17,9 @@ pub mod mds;
pub mod service_account;
pub mod user_account;

pub mod external_account;
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets keep this private until we figure out twosigma's requirements regarding openssl and custom request client.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The problem is that by doing that, I can't use the module on the auth integration tests.

}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct CredentialSourceFormat {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does CredentialSourceFormat, CredentialSourceHeaders, ExecutableConfig, CredentialSource need to be public?

Some(format) => {
let json_response: Value = serde_json::from_str(&response_text).unwrap();
let subject_token = json_response
.get(&format.subject_token_field_name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add the format of the response in comments or link to a source. If not this is hard to understand.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the response from the subject token provider is dynamic and have a field named defined by the subject_token_field_name. So it's something like { "{subject_token_field_name}": "a token" }

/// Creates a new builder using [external_account_config] JSON value.
///
/// [external_account_config]: https://cloud.google.com/iam/docs/workload-download-cred-and-grant-access#download-configuration
pub fn new(external_account_config: Value) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

With this design, if for whatever reason the user wants to build a workload credential through code instead of loading from config, they have no way of doing it.

Can we design in such a way that every workload cred type has its own builder.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can create a URLSourcedExternalAccountCredential struct and that would provide a builder interface. Under the hood it would use an ExternalAccountCredential, so it's mostly a wrapper and more direct way of creating the type

Copy link
Contributor

Choose a reason for hiding this comment

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

The builder for url sourced cred should also allow user to override scopes atleast. When user is building a cred, they could override scopes. If you do not have scopes in byoid builders, user would call with_scopes and it would do nothing for some cred types.

pub fn with_scopes<I, S>(mut self, scopes: I) -> Self

Copy link
Contributor

Choose a reason for hiding this comment

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

This will also solve your macro problem

)
}
_ => {
unreachable!("expected Url Sourced credential")
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 cool!

}

#[async_trait::async_trait]
impl SubjectTokenProvider for UrlSourcedCredentials {
Copy link
Contributor

Choose a reason for hiding this comment

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

unit test for UrlSourcedCredentials?

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.

URL Sourced Credentials
3 participants