Skip to content

Commit d189584

Browse files
author
Rakeshwar Reddy Kambaiahgari
committed
Merge branch 'TestImprov' of https://github.com/RakeshwarK/VirtualClient into TestImprov
2 parents 5c8c916 + 9034a40 commit d189584

28 files changed

Lines changed: 2724 additions & 94 deletions

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.57
1+
2.1.58
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace VirtualClient.Actions
5+
{
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using Moq;
12+
using NUnit.Framework;
13+
using VirtualClient.Common;
14+
using VirtualClient.Contracts;
15+
16+
[TestFixture]
17+
[Category("Functional")]
18+
public class GetAccessTokenProfileTests
19+
{
20+
private DependencyFixture dependencyFixture;
21+
22+
[OneTimeSetUp]
23+
public void SetupFixture()
24+
{
25+
this.dependencyFixture = new DependencyFixture();
26+
ComponentTypeCache.Instance.LoadComponentTypes(TestDependencies.TestDirectory);
27+
}
28+
29+
[Test]
30+
[TestCase("GET-ACCESS-TOKEN.json", PlatformID.Unix)]
31+
[TestCase("GET-ACCESS-TOKEN.json", PlatformID.Win32NT)]
32+
public void GetAccessTokenProfileParametersAreInlinedCorrectly(string profile, PlatformID platform)
33+
{
34+
this.dependencyFixture.Setup(platform);
35+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.dependencyFixture.Dependencies))
36+
{
37+
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
38+
}
39+
}
40+
41+
[Test]
42+
[TestCase("GET-ACCESS-TOKEN.json", PlatformID.Unix)]
43+
[TestCase("GET-ACCESS-TOKEN.json", PlatformID.Win32NT)]
44+
public void GetAccessTokenProfileParametersAreAvailable(string profile, PlatformID platform)
45+
{
46+
this.dependencyFixture.Setup(platform);
47+
48+
var mandatoryParameters = new List<string> { "KeyVaultUri", "TenantId" };
49+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.dependencyFixture.Dependencies))
50+
{
51+
Assert.IsEmpty(executor.Profile.Actions);
52+
Assert.AreEqual(1, executor.Profile.Dependencies.Count);
53+
54+
var dependencyBlock = executor.Profile.Dependencies.FirstOrDefault();
55+
56+
foreach (var parameters in mandatoryParameters)
57+
{
58+
Assert.IsTrue(dependencyBlock.Parameters.ContainsKey(parameters));
59+
}
60+
}
61+
}
62+
}
63+
}

src/VirtualClient/VirtualClient.Contracts/DependencyKeyVaultStore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ public DependencyKeyVaultStore(string storeName, Uri endpointUri, TokenCredentia
5353
/// </summary>
5454
public TokenCredential Credentials { get; }
5555
}
56-
}
56+
}

src/VirtualClient/VirtualClient.Core.UnitTests/EndpointUtilityTests.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ public void EndpointUtilityThrowsWhenCreatingBlobStoreReferenceForCDNUriIfUriIsV
188188
"https://anystorage.blob.core.windows.net/")]
189189
//
190190
[TestCase(
191-
"https://anystorage.blob.core.windows.net?sv=2022-11-02&ss=b&srt=co&sp=rtf&se=2024-07-02T05:15:29Z&st=2024-07-01T21:15:29Z&spr=https",
191+
"https://anystorage.blob.core.windows.net?sv=2022-11-02&ss=b&srt=co&sp=rtf&se=2024-07-02T05:15:29Z&st=2024-07-01T21:15:29Z&spr=https",
192192
"https://anystorage.blob.core.windows.net/?sv=2022-11-02&ss=b&srt=co&sp=rtf&se=2024-07-02T05:15:29Z&st=2024-07-01T21:15:29Z&spr=https")]
193193
//
194194
[TestCase(
@@ -230,7 +230,7 @@ public void EndpointUtilityCreatesTheExpectedBlobStoreReferenceForConnectionStri
230230

231231
[Test]
232232
[TestCase("https://any.service.azure.com?miid=307591a4-abb2-4559-af59-b47177d140cf", "https://any.service.azure.com")]
233-
[TestCase("https://any.service.azure.com/?miid=307591a4-abb2-4559-af59-b47177d140cf","https://any.service.azure.com/")]
233+
[TestCase("https://any.service.azure.com/?miid=307591a4-abb2-4559-af59-b47177d140cf", "https://any.service.azure.com/")]
234234
public void EndpointUtilityCreatesTheExpectedBlobStoreReferenceForUrisReferencingManagedIdentities(string uri, string expectedUri)
235235
{
236236
DependencyBlobStore store = EndpointUtility.CreateBlobStoreReference(
@@ -338,7 +338,7 @@ public void EndpointUtilityCreatesTheExpectedBlobStoreReferenceForConnectionStri
338338
Assert.IsNotNull(store.Credentials);
339339
Assert.IsInstanceOf<ClientCertificateCredential>(store.Credentials);
340340
}
341-
341+
342342
[Test]
343343
[TestCase("https://any.service.azure.com/?cid=307591a4-abb2-4559-af59-b47177d140cf&tid=985bbc17-e3a5-4fec-b0cb-40dbb8bc5959&crti=ABC&crts=any.domain.com", "https://any.service.azure.com/")]
344344
[TestCase("https://any.service.azure.com/?cid=307591a4-abb2-4559-af59-b47177d140cf&tid=985bbc17-e3a5-4fec-b0cb-40dbb8bc5959&crti=ABC CA 01&crts=any.domain.com", "https://any.service.azure.com/")]
@@ -854,5 +854,37 @@ public void CreateKeyVaultStoreReference_ConnectionString_ThrowsOnInvalid()
854854
"InvalidConnectionString",
855855
this.mockFixture.CertificateManager.Object));
856856
}
857+
858+
[Test]
859+
[TestCase("https://anyvault.vault.azure.net/?cid=123456&tid=654321")]
860+
[TestCase("https://anycontentstorage.blob.core.windows.net?cid=123456&tid=654321")]
861+
[TestCase("https://anypackagestorage.blob.core.windows.net?tid=654321")]
862+
[TestCase("https://anynamespace.servicebus.windows.net?cid=123456&tid=654321")]
863+
[TestCase("https://my-keyvault.vault.azure.net/?;tid=654321")]
864+
public void TryParseMicrosoftEntraTenantIdReference_Uri_WorksAsExpected(string input)
865+
{
866+
// Arrange
867+
Uri uri = new Uri(input);
868+
bool result = EndpointUtility.TryParseMicrosoftEntraTenantIdReference(uri, out string actualTenantId);
869+
870+
// Assert
871+
Assert.True(result);
872+
Assert.AreEqual("654321", actualTenantId);
873+
}
874+
875+
[Test]
876+
[TestCase("https://anycontentstorage.blob.core.windows.net?cid=123456&tenantId=654321")]
877+
[TestCase("https://anypackagestorage.blob.core.windows.net?miid=654321")]
878+
[TestCase("https://my-keyvault.vault.azure.net/;cid=654321")]
879+
public void TryParseMicrosoftEntraTenantIdReference_Uri_ReturnFalseWhenInvalid(string input)
880+
{
881+
// Arrange
882+
Uri uri = new Uri(input);
883+
bool result = EndpointUtility.TryParseMicrosoftEntraTenantIdReference(uri, out string actualTenantId);
884+
885+
// Assert
886+
Assert.IsFalse(result);
887+
Assert.IsNull(actualTenantId);
888+
}
857889
}
858890
}

src/VirtualClient/VirtualClient.Core/EndpointUtility.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,26 @@ public static bool TryParseCertificateReference(Uri uri, out string issuer, out
398398
return TryGetCertificateReferenceForUri(queryParameters, out issuer, out subject);
399399
}
400400

401+
/// <summary>
402+
/// Tries to parse the Microsoft Entra reference information from the provided uri. If the uri does not contain the correctly formatted client ID
403+
/// and tenant ID information the method will return false, and keep the two out parameters as null.
404+
/// Ex. https://anystore.blob.core.windows.net?cid={clientId};tid={tenantId}
405+
/// </summary>
406+
/// <param name="uri">The uri to attempt to parse the values from.</param>
407+
/// <param name="tenantId">The tenant ID from the Microsoft Entra reference.</param>
408+
/// <returns>True/False if the method was able to successfully parse both the client ID and the tenant ID from the Microsoft Entra reference.</returns>
409+
public static bool TryParseMicrosoftEntraTenantIdReference(Uri uri, out string tenantId)
410+
{
411+
string queryString = Uri.UnescapeDataString(uri.Query).Trim('?').Replace("&", ",,,");
412+
413+
IDictionary<string, string> queryParameters = TextParsingExtensions.ParseDelimitedValues(queryString)?.ToDictionary(
414+
entry => entry.Key,
415+
entry => entry.Value?.ToString(),
416+
StringComparer.OrdinalIgnoreCase);
417+
418+
return TryGetMicrosoftEntraTenantId(queryParameters, out tenantId);
419+
}
420+
401421
/// <summary>
402422
/// Returns the endpoint by verifying package uri checks.
403423
/// if the endpoint is a package uri without http or https protocols then append the protocol else return the endpoint value.
@@ -1292,5 +1312,23 @@ private static bool TryGetMicrosoftEntraReferenceForUri(IDictionary<string, stri
12921312

12931313
return parametersDefined;
12941314
}
1315+
1316+
private static bool TryGetMicrosoftEntraTenantId(IDictionary<string, string> uriParameters, out string tenantId)
1317+
{
1318+
bool parametersDefined = false;
1319+
tenantId = null;
1320+
1321+
if (uriParameters?.Any() == true)
1322+
{
1323+
if (uriParameters.TryGetValue(UriParameter.TenantId, out string microsoftEntraTenantId)
1324+
&& !string.IsNullOrWhiteSpace(microsoftEntraTenantId))
1325+
{
1326+
tenantId = microsoftEntraTenantId;
1327+
parametersDefined = true;
1328+
}
1329+
}
1330+
1331+
return parametersDefined;
1332+
}
12951333
}
12961334
}

src/VirtualClient/VirtualClient.Core/IKeyVaultManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace VirtualClient
55
{
6+
using System;
67
using System.Security.Cryptography.X509Certificates;
78
using System.Threading;
89
using System.Threading.Tasks;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
namespace VirtualClient.Identity
2+
{
3+
using System;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Azure.Core;
7+
using VirtualClient.Common.Extensions;
8+
9+
/// <summary>
10+
/// A <see cref="TokenCredential"/> implementation that uses a pre-acquired
11+
/// access token.
12+
/// </summary>
13+
public class AccessTokenCredential : TokenCredential
14+
{
15+
/// <summary>
16+
/// Creates a new instance of the <see cref="AccessTokenCredential"/> class.
17+
/// </summary>
18+
/// <param name="token">
19+
/// The access token string to use for authentication.
20+
/// </param>
21+
public AccessTokenCredential(string token)
22+
{
23+
token.ThrowIfNull(nameof(token));
24+
this.AccessToken = new AccessToken(token, DateTimeOffset.UtcNow.AddHours(1));
25+
}
26+
27+
/// <summary>
28+
/// The access token to use for authentication.
29+
/// </summary>
30+
public AccessToken AccessToken { get; }
31+
32+
/// <summary>
33+
/// Gets an access token using the underlying credentials.
34+
/// </summary>
35+
/// <param name="requestContext">Context information used when getting the access token.</param>
36+
/// <param name="cancellationToken">A token that can be used to cancel the operation.</param>
37+
/// <returns>
38+
/// An access token that can be used to authenticate with Azure resources.
39+
/// </returns>
40+
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
41+
{
42+
return this.AccessToken;
43+
}
44+
45+
/// <summary>
46+
/// Gets an access token using the underlying credentials.
47+
/// </summary>
48+
/// <param name="requestContext">Context information used when getting the access token.</param>
49+
/// <param name="cancellationToken">A token that can be used to cancel the operation.</param>
50+
/// <returns>
51+
/// An access token that can be used to authenticate with Azure resources.
52+
/// </returns>
53+
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
54+
{
55+
return new ValueTask<AccessToken>(this.AccessToken);
56+
}
57+
}
58+
}

src/VirtualClient/VirtualClient.Core/KeyVaultManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ namespace VirtualClient
1515
using Azure.Security.KeyVault.Secrets;
1616
using Polly;
1717
using VirtualClient.Common.Extensions;
18-
using VirtualClient.Contracts;
1918

2019
/// <summary>
2120
/// Provides methods for retrieving secrets, keys, and certificates from an Azure Key Vault.

0 commit comments

Comments
 (0)