Skip to content

Commit

Permalink
Merge identity/1.10.2-rel back to main (Azure#39331)
Browse files Browse the repository at this point in the history
* Bug fixes for development time credentials

* update project version

* Increment package version after release of Azure.Identity (Azure#39170)

* tests

---------

Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com>
  • Loading branch information
2 people authored and matthohn-msft committed Oct 27, 2023
1 parent 8c5dfc5 commit 5cfd3f6
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 7 deletions.
7 changes: 7 additions & 0 deletions sdk/identity/Azure.Identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
### Other Changes
- Updated Microsoft.Identity.Client dependency to version 4.56.0

## 1.10.2 (2023-10-10)

### Bugs Fixed

- Bug fixes for development time credentials.


## 1.10.1 (2023-09-12)

### Bugs Fixed
Expand Down
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/src/Azure.Identity.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<AssemblyTitle>Microsoft Azure.Identity Component</AssemblyTitle>
<Version>1.11.0-beta.1</Version>
<!--The ApiCompatVersion is managed automatically and should not generally be modified manually.-->
<ApiCompatVersion>1.10.1</ApiCompatVersion>
<ApiCompatVersion>1.10.2</ApiCompatVersion>
<PackageTags>Microsoft Azure Identity;$(PackageCommonTags)</PackageTags>
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
<NoWarn>$(NoWarn);3021;AZC0011</NoWarn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ internal AzureCliCredential(CredentialPipeline pipeline, IProcessService process
_pipeline = pipeline;
_path = !string.IsNullOrEmpty(EnvironmentVariables.Path) ? EnvironmentVariables.Path : DefaultPath;
_processService = processService ?? ProcessService.Default;
TenantId = options?.TenantId;
TenantId = Validations.ValidateTenantId(options?.TenantId, $"{nameof(options)}.{nameof(options.TenantId)}", true);
AdditionallyAllowedTenantIds = TenantIdResolver.ResolveAddionallyAllowedTenantIds((options as ISupportsAdditionallyAllowedTenants)?.AdditionallyAllowedTenants);
ProcessTimeout = options?.ProcessTimeout ?? TimeSpan.FromSeconds(13);
_isChainedCredential = options?.IsChainedCredential ?? false;
Expand Down Expand Up @@ -121,6 +121,7 @@ private async ValueTask<AccessToken> RequestCliAccessTokenAsync(bool async, Toke
string resource = ScopeUtilities.ScopesToResource(context.Scopes);
string tenantId = TenantIdResolver.Resolve(TenantId, context, AdditionallyAllowedTenantIds);

Validations.ValidateTenantId(tenantId, nameof(context.TenantId), true);
ScopeUtilities.ValidateScope(resource);

GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ internal AzureDeveloperCliCredential(CredentialPipeline pipeline, IProcessServic
_logAccountDetails = options?.Diagnostics?.IsAccountIdentifierLoggingEnabled ?? false;
_pipeline = pipeline;
_processService = processService ?? ProcessService.Default;
TenantId = options?.TenantId;
TenantId = Validations.ValidateTenantId(options?.TenantId, $"{nameof(options)}.{nameof(options.TenantId)}", true);
AdditionallyAllowedTenantIds = TenantIdResolver.ResolveAddionallyAllowedTenantIds((options as ISupportsAdditionallyAllowedTenants)?.AdditionallyAllowedTenants);
ProcessTimeout = options?.ProcessTimeout ?? TimeSpan.FromSeconds(13);
_isChainedCredential = options?.IsChainedCredential ?? false;
Expand Down Expand Up @@ -112,6 +112,13 @@ private async ValueTask<AccessToken> RequestCliAccessTokenAsync(bool async, Toke
{
string tenantId = TenantIdResolver.Resolve(TenantId, context, AdditionallyAllowedTenantIds);

Validations.ValidateTenantId(tenantId, nameof(context.TenantId), true);

foreach (var scope in context.Scopes)
{
ScopeUtilities.ValidateScope(scope);
}

GetFileNameAndArguments(context.Scopes, tenantId, out string fileName, out string argument);
ProcessStartInfo processStartInfo = GetAzureDeveloperCliProcessStartInfo(fileName, argument);
using var processRunner = new ProcessRunner(_processService.Create(processStartInfo), ProcessTimeout, _logPII, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ internal AzurePowerShellCredential(AzurePowerShellCredentialOptions options, Cre
UseLegacyPowerShell = false;
_logPII = options?.IsUnsafeSupportLoggingEnabled ?? false;
_logAccountDetails = options?.Diagnostics?.IsAccountIdentifierLoggingEnabled ?? false;
TenantId = options?.TenantId;
TenantId = Validations.ValidateTenantId(options?.TenantId, $"{nameof(options)}.{nameof(options.TenantId)}", true);
_pipeline = pipeline ?? CredentialPipeline.GetInstance(options);
_processService = processService ?? ProcessService.Default;
AdditionallyAllowedTenantIds = TenantIdResolver.ResolveAddionallyAllowedTenantIds((options as ISupportsAdditionallyAllowedTenants)?.AdditionallyAllowedTenants);
Expand Down Expand Up @@ -139,9 +139,12 @@ private async ValueTask<AccessToken> RequestAzurePowerShellAccessTokenAsync(bool
{
string resource = ScopeUtilities.ScopesToResource(context.Scopes);

ScopeUtilities.ValidateScope(resource);
var tenantId = TenantIdResolver.Resolve(TenantId, context, AdditionallyAllowedTenantIds);

Validations.ValidateTenantId(tenantId, nameof(context.TenantId), true);

ScopeUtilities.ValidateScope(resource);

GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
ProcessStartInfo processStartInfo = GetAzurePowerShellProcessStartInfo(fileName, argument);
using var processRunner = new ProcessRunner(
Expand Down
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/src/ScopeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static class ScopeUtilities
private const string DefaultSuffix = "/.default";
private const string ScopePattern = "^[0-9a-zA-Z-_.:/]+$";

private const string InvalidScopeMessage = "The specified scope is not in expected format. Only alphanumeric characters, '.', '-', ':', '_', and '/' are allowed";
internal const string InvalidScopeMessage = "The specified scope is not in expected format. Only alphanumeric characters, '.', '-', ':', '_', and '/' are allowed";
private static readonly Regex scopeRegex = new Regex(ScopePattern);

public static string ScopesToResource(string[] scopes)
Expand Down
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/src/Validations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Azure.Identity
{
internal static class Validations
{
private const string InvalidTenantIdErrorMessage = "Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names";
internal const string InvalidTenantIdErrorMessage = "Invalid tenant id provided. You can locate your tenant id by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names";

private const string NullTenantIdErrorMessage = "Tenant id cannot be null. You can locate your tenant id by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names";

Expand Down
55 changes: 55 additions & 0 deletions sdk/identity/Azure.Identity/tests/AzureCliCredentialTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
Expand Down Expand Up @@ -148,5 +150,58 @@ public void ConfigureCliProcessTimeout_ProcessTimeout([Values(true, false)] bool
}
Assert.AreEqual(AzureCliCredential.AzureCliTimeoutError, ex.Message);
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyCtorTenantIdValidation(char testChar)
{
string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

Assert.Throws<ArgumentException>(() => new AzureCliCredential(new AzureCliCredentialOptions { TenantId = tenantIdBuilder.ToString() }), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenTenantIdValidation(char testChar)
{
AzureCliCredential credential = InstrumentClient(new AzureCliCredential());

string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(MockScopes.Default, tenantId: tenantIdBuilder.ToString());

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenScopeValidation(char testChar)
{
AzureCliCredential credential = InstrumentClient(new AzureCliCredential());

string scope = MockScopes.Default.ToString();

for (int i = 0; i < scope.Length; i++)
{
StringBuilder scopeBuilder = new StringBuilder(scope);

scopeBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(new string[] { scopeBuilder.ToString() });

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), ScopeUtilities.InvalidScopeMessage);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
Expand Down Expand Up @@ -134,5 +135,58 @@ public void ConfigureCliProcessTimeout_ProcessTimeout([Values(true, false)] bool
}
Assert.AreEqual(AzureDeveloperCliCredential.AzdCliTimeoutError, ex.Message);
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyCtorTenantIdValidation(char testChar)
{
string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

Assert.Throws<ArgumentException>(() => new AzureDeveloperCliCredential(new AzureDeveloperCliCredentialOptions { TenantId = tenantIdBuilder.ToString() }), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenTenantIdValidation(char testChar)
{
AzureDeveloperCliCredential credential = InstrumentClient(new AzureDeveloperCliCredential());

string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(MockScopes.Default, tenantId: tenantIdBuilder.ToString());

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenScopeValidation(char testChar)
{
AzureDeveloperCliCredential credential = InstrumentClient(new AzureDeveloperCliCredential());

string scope = MockScopes.Default.ToString();

for (int i = 0; i < scope.Length; i++)
{
StringBuilder scopeBuilder = new StringBuilder(scope);

scopeBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(new string[] { scopeBuilder.ToString() });

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), ScopeUtilities.InvalidScopeMessage);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,58 @@ public void AuthenticateWithAzurePowerShellCredential_CanceledByUser()
new AzurePowerShellCredential(new AzurePowerShellCredentialOptions(), CredentialPipeline.GetInstance(null), new TestProcessService(testProcess)));
Assert.CatchAsync<OperationCanceledException>(async () => await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default), cts.Token));
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyCtorTenantIdValidation(char testChar)
{
string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

Assert.Throws<ArgumentException>(() => new AzurePowerShellCredential(new AzurePowerShellCredentialOptions { TenantId = tenantIdBuilder.ToString() }), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenTenantIdValidation(char testChar)
{
AzurePowerShellCredential credential = InstrumentClient(new AzurePowerShellCredential());

string tenantId = Guid.NewGuid().ToString();

for (int i = 0; i < tenantId.Length; i++)
{
StringBuilder tenantIdBuilder = new StringBuilder(tenantId);

tenantIdBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(MockScopes.Default, tenantId: tenantIdBuilder.ToString());

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), Validations.InvalidTenantIdErrorMessage);
}
}

[TestCaseSource(nameof(NegativeTestCharacters))]
public void VerifyGetTokenScopeValidation(char testChar)
{
AzurePowerShellCredential credential = InstrumentClient(new AzurePowerShellCredential());

string scope = MockScopes.Default.ToString();

for (int i = 0; i < scope.Length; i++)
{
StringBuilder scopeBuilder = new StringBuilder(scope);

scopeBuilder.Insert(i, testChar);

var tokenRequestContext = new TokenRequestContext(new string[] { scopeBuilder.ToString() });

Assert.ThrowsAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(tokenRequestContext), ScopeUtilities.InvalidScopeMessage);
}
}
}
}
2 changes: 2 additions & 0 deletions sdk/identity/Azure.Identity/tests/CredentialTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ public override string ToString()
}
}

public static readonly char[] NegativeTestCharacters = new char[] { '|', '&', ';', '\'', '"', '!', '@', '$', '%', '^', '*', '(', ')', '=', '[', ']', '{', '}', '<', '>', '?' };

public static IEnumerable<AllowedTenantsTestParameters> GetAllowedTenantsTestCases()
{
string tenant = Guid.NewGuid().ToString();
Expand Down

0 comments on commit 5cfd3f6

Please sign in to comment.