Skip to content

Commit

Permalink
Update identity to enable live testing in sovereign clouds for multip…
Browse files Browse the repository at this point in the history
…le services (#19203)

* only identity change

* resolve error

* change hardcode string

* change to supportedclouds

* remove hardcode

* remove change

* remove hardcode

* change to have the default in a common place

* Remove the StartsWith

* Remove the TestEnvironment.KeyvaultScope

* Remove change

* add hardcode string

* Delete TestEnvVar file.

* Remove hardcoded value of KeyvaultScope, add a initial value for it

* Remove invalid changes.

Co-authored-by: Wenjie Yu (Wicresoft North America Ltd) <v-wenjyu@microsoft.com>
Co-authored-by: Tong Xu (Wicresoft North America Ltd) <v-xuto@microsoft.com>
  • Loading branch information
3 people authored May 4, 2021
1 parent bb2d0e7 commit 2650a69
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 26 deletions.
2 changes: 1 addition & 1 deletion sdk/core/Azure.Core.TestFramework/src/TestEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static TestEnvironment()
/// <summary>
/// The URL of the Azure Authority host to be used for authentication. Recorded.
/// </summary>
public string AuthorityHostUrl => GetRecordedOptionalVariable("AZURE_AUTHORITY_HOST");
public string AuthorityHostUrl => GetRecordedOptionalVariable("AZURE_AUTHORITY_HOST") ?? AzureAuthorityHosts.AzurePublicCloud.ToString();

/// <summary>
/// The suffix for Azure Storage accounts for the active cloud environment, such as "core.windows.net". Recorded.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
Expand Down Expand Up @@ -35,7 +36,7 @@ public async Task FromCertificatePath(bool usePem)

var credential = InstrumentClient(new ClientCertificateCredential(tenantId, clientId, certPath, options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure we can initially acquire a token
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);
Expand Down Expand Up @@ -70,7 +71,7 @@ public async Task FromX509Certificate2()

var credential = InstrumentClient(new ClientCertificateCredential(tenantId, clientId, cert, options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure we can initially acquire a token
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);
Expand Down Expand Up @@ -105,7 +106,7 @@ public async Task IncludeX5CClaimHeader()

var credential = InstrumentClient(new ClientCertificateCredential(tenantId, clientId, certPath, options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure we can initially acquire a token
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);
Expand All @@ -124,7 +125,7 @@ public void IncorrectCertificate()

var credential = InstrumentClient(new ClientCertificateCredential(tenantId, clientId, new X509Certificate2(certPath), options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure the incorrect client claim is rejected, handled and wrapped in AuthenticationFailedException
Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task GetToken()

var credential = InstrumentClient(new ClientSecretCredential(tenantId, clientId, secret, options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure we can initially acquire a token
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);
Expand Down Expand Up @@ -70,7 +70,7 @@ public void GetTokenIncorrectPassword()

var credential = InstrumentClient(new ClientSecretCredential(tenantId, clientId, secret, options));

var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(AzureAuthorityHosts.AzurePublicCloud) });
var tokenRequestContext = new TokenRequestContext(new[] { AzureAuthorityHosts.GetDefaultScope(new Uri(TestEnvironment.AuthorityHostUrl)) });

// ensure we can initially acquire a token
Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext));
Expand Down
2 changes: 2 additions & 0 deletions sdk/identity/Azure.Identity/tests/CredentialTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,10 @@ public static async Task<string> GetRefreshTokenAsync(IdentityTestEnvironment te
var clientId = "aebc6443-996d-45c2-90f0-388ff96faa56";
var username = testEnvironment.Username;
var password = testEnvironment.Password;
var authorityUri = new Uri(new Uri(testEnvironment.AuthorityHostUrl), testEnvironment.TestTenantId).ToString();

var client = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authorityUri)
.WithTenantId(testEnvironment.TestTenantId)
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCredential()

using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
{
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
scopes = diagnosticListener.Scopes;
}

Expand All @@ -66,6 +66,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeManagedIdentityCredential = true,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
});

Expand All @@ -82,7 +83,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()
using (await CredentialTestHelpers.CreateRefreshTokenFixtureAsync(TestEnvironment, Mode, ExpectedServiceName, cloudName))
using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
{
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
scopes = diagnosticListener.Scopes;
}

Expand All @@ -102,6 +103,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential_ParallelC
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeManagedIdentityCredential = true,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
});

Expand All @@ -117,7 +119,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential_ParallelC
{
for (int i = 0; i < 10; i++)
{
tasks.Add(Task.Run(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None)));
tasks.Add(Task.Run(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None)));
}

await Task.WhenAll(tasks);
Expand Down Expand Up @@ -153,7 +155,7 @@ public async Task DefaultAzureCredential_UseAzureCliCredential()

using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
{
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
scopes = diagnosticListener.Scopes;
}

Expand Down Expand Up @@ -187,7 +189,7 @@ public async Task DefaultAzureCredential_UseAzureCliCredential_ParallelCalls()
var tasks = new List<Task<AccessToken>>();
for (int i = 0; i < 10; i++)
{
tasks.Add(Task.Run(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None)));
tasks.Add(Task.Run(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None)));
}

await Task.WhenAll(tasks);
Expand Down Expand Up @@ -218,7 +220,7 @@ public void DefaultAzureCredential_AllCredentialsHaveFailed_CredentialUnavailabl

using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
{
Assert.CatchAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None));
Assert.CatchAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
scopes = diagnosticListener.Scopes;
}

Expand Down Expand Up @@ -275,7 +277,7 @@ public void DefaultAzureCredential_AllCredentialsHaveFailed_LastAuthenticationFa

using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
{
Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None));
Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
scopes = diagnosticListener.Scopes;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ public async Task AuthenticateWithDeviceCodeMockVerifyCallbackCancellationAsync(
[Test]
public void AuthenticateWithDeviceCodeCallbackThrowsAsync()
{
IdentityTestEnvironment testEnvironment = new IdentityTestEnvironment();
var expectedCode = Guid.NewGuid().ToString();

var expectedToken = Guid.NewGuid().ToString();
Expand All @@ -188,7 +189,7 @@ public void AuthenticateWithDeviceCodeCallbackThrowsAsync()

var cred = InstrumentClient(new DeviceCodeCredential(ThrowingDeviceCodeCallback, ClientId, options: options));

var ex = Assert.ThrowsAsync<AuthenticationFailedException>(async () => await cred.GetTokenAsync(new TokenRequestContext(new string[] { "https://vault.azure.net/.default" }), cancelSource.Token));
var ex = Assert.ThrowsAsync<AuthenticationFailedException>(async () => await cred.GetTokenAsync(new TokenRequestContext(new string[] { testEnvironment.KeyvaultScope }), cancelSource.Token));

Assert.IsInstanceOf(typeof(MockException), ex.InnerException);
}
Expand All @@ -209,14 +210,15 @@ public void DisableAutomaticAuthenticationException()

private MockResponse ProcessMockRequest(MockRequest mockRequest, string code, string token)
{
IdentityTestEnvironment testEnvironment = new IdentityTestEnvironment();
string requestUrl = mockRequest.Uri.ToUri().AbsoluteUri;

if (requestUrl.StartsWith("https://login.microsoftonline.com/common/discovery/instance"))
if (requestUrl.StartsWith(new Uri(new Uri(testEnvironment.AuthorityHostUrl), "common/discovery/instance").ToString()))
{
return DiscoveryInstanceResponse;
}

if (requestUrl.StartsWith("https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration"))
if (requestUrl.StartsWith(new Uri(new Uri(testEnvironment.AuthorityHostUrl), "organizations/v2.0/.well-known/openid-configuration").ToString()))
{
return OpenIdConfigurationResponse;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class IdentityTestEnvironment : TestEnvironment

public string TestPassword => GetOptionalVariable("AZURE_IDENTITY_TEST_PASSWORD") ?? "SANITIZED";
public string TestTenantId => GetRecordedOptionalVariable("TENANT_ID") ?? GetRecordedVariable("AZURE_IDENTITY_TEST_TENANTID");
public string KeyvaultScope => GetRecordedOptionalVariable("AZURE_KEYVAULT_SCOPE") ?? "SANITIZED";

public string ServicePrincipalClientId => GetRecordedVariable("IDENTITY_SP_CLIENT_ID");
public string ServicePrincipalTenantId => GetRecordedVariable("IDENTITY_SP_TENANT_ID");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task AuthenticateWithVscCredential()

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystem, default));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
}

Expand All @@ -43,7 +43,7 @@ public async Task AuthenticateWithVscCredential_NoSettingsFile()

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
}

Expand All @@ -56,7 +56,7 @@ public async Task AuthenticateWithVscCredential_BrokenSettingsFile()

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
}

Expand All @@ -70,7 +70,7 @@ public async Task AuthenticateWithVscCredential_EmptySettingsFile()
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));

AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
}

Expand All @@ -86,7 +86,7 @@ public async Task AuthenticateWithVscCredential_TenantInSettings()
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = Guid.NewGuid().ToString() });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, default));

AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None);
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
}

Expand All @@ -100,7 +100,7 @@ public void AuthenticateWithVscCredential_NoVscInstalled()
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystem, default));

Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None));
Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
}

[Test]
Expand All @@ -113,7 +113,7 @@ public void AuthenticateWithVscCredential_NoRefreshToken()
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = tenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystem, vscAdapter));

Assert.ThrowsAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None));
Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
}

[Test]
Expand All @@ -126,7 +126,7 @@ public void AuthenticateWithVscCredential_AuthenticationCodeInsteadOfRefreshToke
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = tenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));

Assert.ThrowsAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {"https://vault.azure.net/.default"}), CancellationToken.None));
Assert.ThrowsAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
}

[Test]
Expand All @@ -139,7 +139,7 @@ public void AuthenticateWithVscCredential_InvalidRefreshToken()
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = tenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));

Assert.ThrowsAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {".default"}), CancellationToken.None));
Assert.ThrowsAsync<CredentialUnavailableException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope }), CancellationToken.None));
}
}
}
Loading

0 comments on commit 2650a69

Please sign in to comment.