Skip to content

Commit

Permalink
Required feature update
Browse files Browse the repository at this point in the history
  • Loading branch information
neha-bhargava committed Jun 3, 2024
1 parent 5c6f22f commit 449251d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Identity.Client.Extensibility;
using Microsoft.Identity.Client.Http;
using Microsoft.Identity.Client.Internal;
using Microsoft.Identity.Client.PlatformsCommon.Shared;
using Microsoft.Identity.Client.Utils;

namespace Microsoft.Identity.Client.ManagedIdentity
Expand Down Expand Up @@ -110,19 +111,7 @@ protected override async Task<ManagedIdentityResponse> HandleResponseAsync(

var splitChallenge = challenge.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);

if (splitChallenge.Length != 2)
{
_requestContext.Logger.Error("[Managed Identity] The WWW-Authenticate header for Azure arc managed identity is not an expected format.");

var exception = MsalServiceExceptionFactory.CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityInvalidChallenge,
null,
ManagedIdentitySource.AzureArc,
null);

throw exception;
}
ValidateSplitChallenge(splitChallenge);

var authHeaderValue = "Basic " + File.ReadAllText(splitChallenge[1]);

Expand All @@ -138,5 +127,84 @@ protected override async Task<ManagedIdentityResponse> HandleResponseAsync(

return await base.HandleResponseAsync(parameters, response, cancellationToken).ConfigureAwait(false);
}

private void ValidateSplitChallenge(string[] splitChallenge)
{
if (splitChallenge.Length != 2)
{
throw CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityInvalidChallenge);
}

_requestContext.Logger.Verbose(() => $"[Managed Identity] Challenge is valid. FilePath: {splitChallenge[1]}");

if (DesktopOsHelper.IsWindows())
{
if (!IsValidWindowsPath(splitChallenge[1]))
{
throw CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityInvalidFile);
}

_requestContext.Logger.Verbose(() => "[Managed Identity] Windows path is valid.");
}
else if (DesktopOsHelper.IsLinux())
{
if (!IsValidLinuxPath(splitChallenge[1]))
{
throw CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityInvalidFile);
}

_requestContext.Logger.Verbose(() => "[Managed Identity] Linux path is valid.");
}
else
{
throw CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityPlatformNotSupported);
}

var length = new FileInfo(splitChallenge[1]).Length;

if ((!File.Exists(splitChallenge[1]) || (length) > 4096))
{
_requestContext.Logger.Error($"[Managed Identity] File does not exist or is greater than 4096 bytes. File exists: {File.Exists(splitChallenge[1])}. Length of file: {length}");
throw CreateManagedIdentityException(
MsalError.ManagedIdentityRequestFailed,
MsalErrorMessage.ManagedIdentityInvalidFile);
}

_requestContext.Logger.Verbose(() => "[Managed Identity] File exists and is less than 4096 bytes.");
}

private MsalException CreateManagedIdentityException(string errorCode, string errorMessage)
{
return MsalServiceExceptionFactory.CreateManagedIdentityException(
errorCode,
errorMessage,
null,
ManagedIdentitySource.AzureArc,
null);
}

private bool IsValidLinuxPath(string path)
{
string linuxPath = "/var/opt/azcmagent/tokens/";

return path.StartsWith(linuxPath, StringComparison.OrdinalIgnoreCase) &&
path.EndsWith(".key", StringComparison.OrdinalIgnoreCase);
}

private bool IsValidWindowsPath(string path)
{
string expandedExpectedPath = Environment.ExpandEnvironmentVariables("%ProgramData%\\AzureConnectedMachineAgent\\Tokens\\");

return path.StartsWith(expandedExpectedPath, StringComparison.OrdinalIgnoreCase) &&
path.EndsWith(".key", StringComparison.OrdinalIgnoreCase);
}
}
}
2 changes: 2 additions & 0 deletions src/client/Microsoft.Identity.Client/MsalErrorMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ public static string InvalidTokenProviderResponseValue(string invalidValueName)
public const string ManagedIdentityEndpointInvalidUriError = "[Managed Identity] The environment variable {0} contains an invalid Uri {1} in {2} managed identity source.";
public const string ManagedIdentityNoChallengeError = "[Managed Identity] Did not receive expected WWW-Authenticate header in the response from Azure Arc Managed Identity Endpoint.";
public const string ManagedIdentityInvalidChallenge = "[Managed Identity] The WWW-Authenticate header in the response from Azure Arc Managed Identity Endpoint did not match the expected format.";
public const string ManagedIdentityInvalidFile = "[Managed Identity] The file on the file path in the WWW-Authenticate header is not secure.";
public const string ManagedIdentityPlatformNotSupported = "[Managed Identity] The platform is not supported by Azure Arc. Azure Arc only supports Windows and Linux.";
public const string ManagedIdentityUserAssignedNotSupported = "[Managed Identity] User assigned identity is not supported by the {0} Managed Identity. To authenticate with the system assigned identity omit the client id in ManagedIdentityApplicationBuilder.Create().";
public const string ManagedIdentityUserAssignedNotConfigurableAtRuntime = "[Managed Identity] Service Fabric user assigned managed identity ClientId or ResourceId is not configurable at runtime.";
public const string CombinedUserAppCacheNotSupported = "Using a combined flat storage, like a file, to store both app and user tokens is not supported. Use a partitioned token cache (for ex. distributed cache like Redis) or separate files for app and user token caches. See https://aka.ms/msal-net-token-cache-serialization .";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Identity.Test.Common.Core.Helpers;
using Microsoft.Identity.Test.Common.Core.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute.Core;
using static Microsoft.Identity.Test.Common.Core.Helpers.ManagedIdentityTestUtil;

namespace Microsoft.Identity.Test.Unit.ManagedIdentityTests
Expand Down Expand Up @@ -78,8 +79,10 @@ await mi.AcquireTokenForManagedIdentity("scope")
}
}

[TestMethod]
public async Task AzureArcAuthHeaderInvalidAsync()
[DataTestMethod]
[DataRow("somefile=filename", MsalErrorMessage.ManagedIdentityInvalidChallenge)]
[DataRow("path/filename", MsalErrorMessage.ManagedIdentityInvalidFile)]
public async Task AzureArcAuthHeaderInvalidAsync(string filename, string errorMessage)
{
using (new EnvVariableContext())
using (var httpManager = new MockHttpManager(isManagedIdentity: true))
Expand Down

0 comments on commit 449251d

Please sign in to comment.