Skip to content

Commit

Permalink
feat: ADC supports universe domain
Browse files Browse the repository at this point in the history
  • Loading branch information
amanda-tarafa committed Dec 15, 2023
1 parent e0ca01a commit a45fb13
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class DefaultCredentialProviderTests

private const string InvalidCredentialFileName = "invalid_credential.json";
private const string UserCredentialFileName = "user_credential.json";
private const string UserCredentialCustomUniverseDomainFileName = "user_credential_custom_universe_domain.json";
internal const string ServiceAccountCredentialMinimalFileName = "service_account_credential_minimal.json";
private const string ServiceAccountCredentialFullFileName = "service_account_credential_full.json";
private const string BrokenServiceAccountCredentialFileName = "broken_service_account_credential.json";
Expand All @@ -74,7 +75,12 @@ public class DefaultCredentialProviderTests
private const string UrlSourcedWorkforceExternalAccountCredentialFileName = "url_sourced_workforce_external_account_credential.json";
private const string FileSourcedWorkforceExternalAccountCredentialFileName = "file_sourced_workforce_external_account_credential.json";
private const string AwsWorkforceExternalAccountCredentialFileName = "aws_workforce_external_account_credential.json";
private const string UrlSourcedExternalAccountCredentialUniverseDomainFileName = "url_sourced_external_account_credential_universe_domain.json";
private const string FileSourcedExternalAccountCredentialUniverseDomainFileName = "file_sourced_external_account_credential_universe_domain.json";
private const string AwsExternalAccountCredentialUniverseDomainFileName = "aws_external_account_credential_universe_domain.json";
private const string ImpersonatedServiceAccountCredentialFileName = "impersonated_service_account_credential.json";
private const string ImpersonatedServiceAccountCredentialUniverseDomainFileName = "impersonated_service_account_credential_universe_domain.json";
private const string ImpersonatedServiceAccountCredentialUniverseDomainDifferentFileName = "impersonated_service_account_credential_universe_domain_different.json";
private const string RecursiveImpersonatedServiceAccountCredentialName = "recursive_impersonated_service_account_credential.json";

public DefaultCredentialProviderTests()
Expand All @@ -86,6 +92,14 @@ public DefaultCredentialProviderTests()

#region UserCredential

[Fact]
public async Task GetDefaultCredential_UserCredential_CustomUniverseDomain_Fails()
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, UserCredentialCustomUniverseDomainFileName);

await Assert.ThrowsAsync<InvalidOperationException>(credentialProvider.GetDefaultCredentialAsync);
}

[Fact]
public async Task GetDefaultCredential_UserCredential_FromEnvironmentVariable()
{
Expand All @@ -96,6 +110,8 @@ public async Task GetDefaultCredential_UserCredential_FromEnvironmentVariable()
Assert.IsType<UserCredential>(credential.UnderlyingCredential);
Assert.False(credential.IsCreateScopedRequired);
Assert.Same(credential, credential.CreateScoped(new[] { "SomeScope" }));
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

[Fact]
Expand All @@ -109,6 +125,8 @@ public async Task GetDefaultCredential_UserCredential_FromWellKnownFileLocation(
Assert.IsType<UserCredential>(credential.UnderlyingCredential);
Assert.False(credential.IsCreateScopedRequired);
Assert.Same(credential, credential.CreateScoped(new[] { "SomeScope" }));
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

[Fact]
Expand All @@ -121,6 +139,8 @@ public async Task GetDefaultCredential_UserCredential_FromWellKnownFileLocationU

Assert.IsType<UserCredential>(credential.UnderlyingCredential);
Assert.False(credential.IsCreateScopedRequired);
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

#endregion
Expand Down Expand Up @@ -170,6 +190,8 @@ public async Task GetDefaultCredential_ServiceAccountCredential_Minimal()
Assert.Equal(GoogleAuthConsts.OidcTokenUrl, sa.TokenServerUrl);
Assert.Null(sa.ProjectId);
Assert.Null(sa.QuotaProject);
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

[Fact]
Expand All @@ -186,6 +208,8 @@ public async Task GetDefaultCredential_ServiceAccountCredential_Full()
Assert.Equal("TOKEN_URI", sa.TokenServerUrl);
Assert.Equal("PROJECT_ID", sa.ProjectId);
Assert.Equal("QUOTA_PROJECT_ID", sa.QuotaProject);
Assert.Equal("fake.universe.domain.com", credential.GetUniverseDomain());
Assert.Equal("fake.universe.domain.com", await credential.GetUniverseDomainAsync(default));
}

#endregion
Expand All @@ -197,7 +221,7 @@ public async Task GetDefaultCredential_ExternalAccountCredential_NoCredentialSou
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, NoCredentialSourceExternalAccountCredentialFileName);

await Assert.ThrowsAsync<InvalidOperationException>(() => credentialProvider.GetDefaultCredentialAsync());
await Assert.ThrowsAsync<InvalidOperationException>(credentialProvider.GetDefaultCredentialAsync);
}

public static TheoryData<string, Type> ExternalAccountCredentialTestData => new TheoryData<string, Type>
Expand All @@ -216,6 +240,9 @@ public async Task GetDefaultCredential_ExternalAccountCredential(string credenti
var credential = await credentialProvider.GetDefaultCredentialAsync();

Assert.IsType(expectedCredentialType, credential.UnderlyingCredential);
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));

}

public static TheoryData<string, Type> ExternalImpersonatedAccountCredentialTestData => new TheoryData<string, Type>
Expand All @@ -227,7 +254,7 @@ public async Task GetDefaultCredential_ExternalAccountCredential(string credenti

[Theory]
[MemberData(nameof(ExternalImpersonatedAccountCredentialTestData))]
public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential_Impersonated(string credentialFileName, Type expectedCredentialType)
public async Task GetDefaultCredential_ExternalAccountCredential_Impersonated(string credentialFileName, Type expectedCredentialType)
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, credentialFileName);

Expand All @@ -237,6 +264,8 @@ public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential_Imper

var impersonatedExternalCredential = (ExternalAccountCredential)credential.UnderlyingCredential;
Assert.IsType<ImpersonatedCredential>(impersonatedExternalCredential.ImplicitlyImpersonated.Value);
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

public static TheoryData<string, Type> ExternalWorkforceAccountCredentialTestData => new TheoryData<string, Type>
Expand All @@ -248,7 +277,7 @@ public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential_Imper

[Theory]
[MemberData(nameof(ExternalWorkforceAccountCredentialTestData))]
public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential_WorkforceIdentity(string credentialFileName, Type expectedCredentialType)
public async Task GetDefaultCredential_ExternalAccountCredential_WorkforceIdentity(string credentialFileName, Type expectedCredentialType)
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, credentialFileName);

Expand All @@ -258,6 +287,30 @@ public async Task GetDefaultCredential_UrlSourcedExternalAccountCredential_Workf

var workforceCredential = (ExternalAccountCredential)credential.UnderlyingCredential;
Assert.Equal("user_project", workforceCredential.WorkforcePoolUserProject);
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));
}

public static TheoryData<string, Type> ExternalAccountCredentialUniverseDomainTestData => new TheoryData<string, Type>
{
{ UrlSourcedExternalAccountCredentialUniverseDomainFileName, typeof(UrlSourcedExternalAccountCredential) },
{ FileSourcedExternalAccountCredentialUniverseDomainFileName, typeof (FileSourcedExternalAccountCredential) },
{ AwsExternalAccountCredentialUniverseDomainFileName, typeof(AwsExternalAccountCredential) } ,
};

[Theory]
[MemberData(nameof(ExternalAccountCredentialUniverseDomainTestData))]
public async Task GetDefaultCredential_ExternalAccountCredential_UniverseDomain(string credentialFileName, Type expectedCredentialType)
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, credentialFileName);

var credential = await credentialProvider.GetDefaultCredentialAsync();

Assert.IsType(expectedCredentialType, credential.UnderlyingCredential);

var workforceCredential = (ExternalAccountCredential)credential.UnderlyingCredential;
Assert.Equal("fake.universe.domain.com", credential.GetUniverseDomain());
Assert.Equal("fake.universe.domain.com", await credential.GetUniverseDomainAsync(default));
}

#endregion
Expand All @@ -277,11 +330,53 @@ public async Task GetDefaultCredential_ImpersonatedCredential_FromEnvironmentVar
Assert.Collection(impersonatedCredential.DelegateAccounts,
account => Assert.Equal("delegate-email-1", account),
account => Assert.Equal("delegate-email-2", account));
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, credential.GetUniverseDomain());
Assert.Equal(GoogleAuthConsts.DefaultUniverseDomain, await credential.GetUniverseDomainAsync(default));

var userCredential = Assert.IsType<UserCredential>(impersonatedCredential.SourceCredential.UnderlyingCredential);
Assert.Equal("REFRESH_TOKEN", userCredential.Token.RefreshToken);
}

[Fact]
public async Task GetDefaultCredential_ImpersonatedCredential_UniverseDomain()
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, ImpersonatedServiceAccountCredentialUniverseDomainFileName);

var credential = await credentialProvider.GetDefaultCredentialAsync();

var impersonatedCredential = Assert.IsType<ImpersonatedCredential>(credential.UnderlyingCredential);
Assert.Equal("service-account-email", impersonatedCredential.TargetPrincipal);
Assert.True(await impersonatedCredential.HasCustomTokenUrlCache.Value);
Assert.Collection(impersonatedCredential.DelegateAccounts,
account => Assert.Equal("delegate-email-1", account),
account => Assert.Equal("delegate-email-2", account));

Assert.Equal("fake.universe.domain.com", credential.GetUniverseDomain());
Assert.Equal("fake.universe.domain.com", await credential.GetUniverseDomainAsync(default));
}

[Fact]
public async Task GetDefaultCredential_ImpersonatedCredential_UniverseDomain_Different()
{
credentialProvider.SetEnvironmentVariable(CredentialEnvironmentVariable, ImpersonatedServiceAccountCredentialUniverseDomainDifferentFileName);

var credential = await credentialProvider.GetDefaultCredentialAsync();

var impersonatedCredential = Assert.IsType<ImpersonatedCredential>(credential.UnderlyingCredential);
Assert.Equal("service-account-email", impersonatedCredential.TargetPrincipal);
Assert.True(await impersonatedCredential.HasCustomTokenUrlCache.Value);
Assert.Collection(impersonatedCredential.DelegateAccounts,
account => Assert.Equal("delegate-email-1", account),
account => Assert.Equal("delegate-email-2", account));

Assert.Equal("target.fake.universe.domain.com", credential.GetUniverseDomain());
Assert.Equal("target.fake.universe.domain.com", await credential.GetUniverseDomainAsync(default));

var sourceGCredential = Assert.IsType<GoogleCredential>(impersonatedCredential.SourceCredential);
var sourceSACredential = Assert.IsType<ServiceAccountCredential>(sourceGCredential.UnderlyingCredential);
Assert.Equal("target.fake.universe.domain.com", sourceSACredential.UniverseDomain);
}

[Fact]
public async Task GetDefaultCredential_RecursiveImpersonatedCredential_FromEnvironmentVariable()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
"subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
"token_url": "https://sts.googleapis.com/v1/token",
"universe_domain": "fake.universe.domain.com",
"credential_source": {
"environment_id": "aws1",
"region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone",
"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials",
"regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
"imdsv2_session_token_url": "http://169.254.169.254/latest/api/token"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
"subject_token_type": "urn:ietf:params:oauth:token-type:saml2",
"token_url": "https://sts.googleapis.com/v1/token",
"universe_domain": "fake.universe.domain.com",
"credential_source": {
"file": "/var/run/saml/assertion/token"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-email:generateAccessToken",
"delegates": [
"delegate-email-1",
"delegate-email-2"
],
"universe_domain": "fake.universe.domain.com",
"source_credentials": {
"private_key_id": "PRIVATE_KEY_ID",
"private_key": "-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJJM6HT4s6btOsfe2x4zrzrwSUtmtR37XTTi0sPARTDF8uzmXy8UnE5RcVJzEH5T2Ssz/ylX4Sl/CI4Lno1l8j9GiHJb49LSRjWe4Yx936q0Xj9H0R1HTxvjUPqwAsTwy2fKBTog+q1frqc9o8s2r6LYivUGDVbhuUzCaMJsf+x3AgMBAAECgYEAi0FTXsu/zRswAUGaViQiHjrLuU65BSHXNVjV/2fLNEKnGWGqpli68z1IXY+S2nwbUak7rnGsq9/0F6jtsW+hZbLkKXUOuuExpeC5Kd6ngWX/f2jqmhlUabiQijU9cVk7pMq8EHkRtvlosnMTUAEzempuQUPwn1PZHhmJkBvZ4lECQQDCErrxl+e3BwUDcS0yVEEmCNSG6xdXs2878b8rzbe73Mmi6SuuOLi3PU92J+j+f/MOdtYrk13mEDdYmd5dhrt5AkEAwPvDEsDT/W4y4h5ngv1awGBA5aLFE1JNWM/Gwn4D1cGpEDHKFREaBtxMDCASpHJuw8r7zUywpKhmBZcfGS37bwJANdSAKfbafLfjuhqwUJ9yGpykZm/a36aTmerp/bpn1iHdg+RtCzwMcDb/TWSwibbvsflgWmHbz657y4WSWhq+8QJAWrpCNN/ZCk2zuGDo80lfUBAwkoVat8G6wWU1oZyS+vzIGef+hLb8kHsjeZPej9eIwZ39kcBbT54oELrCkRjwGwJAQ8V2A7lTZUp8AsbVqF6rbLiiUfJMo2btGclQu4DEVyS+ymFA65tXDLUuR9EDqJYdqHNZJ5B84Z5p2prkjWTLcA\u003d\u003d-----END PRIVATE KEY-----",
"client_email": "CLIENT_EMAIL",
"type": "service_account",
"universe_domain": "fake.universe.domain.com"
},
"type": "impersonated_service_account"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-email:generateAccessToken",
"delegates": [
"delegate-email-1",
"delegate-email-2"
],
"universe_domain": "target.fake.universe.domain.com",
"source_credentials": {
"private_key_id": "PRIVATE_KEY_ID",
"private_key": "-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJJM6HT4s6btOsfe2x4zrzrwSUtmtR37XTTi0sPARTDF8uzmXy8UnE5RcVJzEH5T2Ssz/ylX4Sl/CI4Lno1l8j9GiHJb49LSRjWe4Yx936q0Xj9H0R1HTxvjUPqwAsTwy2fKBTog+q1frqc9o8s2r6LYivUGDVbhuUzCaMJsf+x3AgMBAAECgYEAi0FTXsu/zRswAUGaViQiHjrLuU65BSHXNVjV/2fLNEKnGWGqpli68z1IXY+S2nwbUak7rnGsq9/0F6jtsW+hZbLkKXUOuuExpeC5Kd6ngWX/f2jqmhlUabiQijU9cVk7pMq8EHkRtvlosnMTUAEzempuQUPwn1PZHhmJkBvZ4lECQQDCErrxl+e3BwUDcS0yVEEmCNSG6xdXs2878b8rzbe73Mmi6SuuOLi3PU92J+j+f/MOdtYrk13mEDdYmd5dhrt5AkEAwPvDEsDT/W4y4h5ngv1awGBA5aLFE1JNWM/Gwn4D1cGpEDHKFREaBtxMDCASpHJuw8r7zUywpKhmBZcfGS37bwJANdSAKfbafLfjuhqwUJ9yGpykZm/a36aTmerp/bpn1iHdg+RtCzwMcDb/TWSwibbvsflgWmHbz657y4WSWhq+8QJAWrpCNN/ZCk2zuGDo80lfUBAwkoVat8G6wWU1oZyS+vzIGef+hLb8kHsjeZPej9eIwZ39kcBbT54oELrCkRjwGwJAQ8V2A7lTZUp8AsbVqF6rbLiiUfJMo2btGclQu4DEVyS+ymFA65tXDLUuR9EDqJYdqHNZJ5B84Z5p2prkjWTLcA\u003d\u003d-----END PRIVATE KEY-----",
"client_email": "CLIENT_EMAIL",
"type": "service_account",
"universe_domain": "source.fake.universe.domain.com"
},
"type": "impersonated_service_account"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"type": "service_account",
"project_id": "PROJECT_ID",
"quota_project_id": "QUOTA_PROJECT_ID",
"token_uri": "TOKEN_URI"
"token_uri": "TOKEN_URI",
"universe_domain": "fake.universe.domain.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_url": "https://sts.googleapis.com/v1/token",
"universe_domain": "fake.universe.domain.com",
"credential_source": {
"headers": {
"Metadata": "True"
},
"url": "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID",
"format": {
"type": "json",
"subject_token_field_name": "access_token"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET",
"refresh_token": "REFRESH_TOKEN",
"universe_domain": "googleapis.com",
"type": "authorized_user"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"client_id": "CLIENT_ID",
"client_secret": "CLIENT_SECRET",
"refresh_token": "REFRESH_TOKEN",
"universe_domain": "fake.universe.domain.com",
"type": "authorized_user"
}
Loading

0 comments on commit a45fb13

Please sign in to comment.