Skip to content

Commit 4f13458

Browse files
author
Aditya Abhishek
committed
2nd commit
1 parent 5790e3f commit 4f13458

6 files changed

Lines changed: 170 additions & 93 deletions

File tree

src/VirtualClient/Module.props

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@
3131

3232
<!-- Azure.Messaging.EventHubs -->
3333
<Azure_Messaging_EventHubs_PackageVersion>5.11.5</Azure_Messaging_EventHubs_PackageVersion>
34+
35+
<!-- Azure.Security.KeyVault.Certificates -->
36+
<Azure_Security_KeyVault_Certificates_PackageVersion>4.7.0</Azure_Security_KeyVault_Certificates_PackageVersion>
37+
38+
<!-- Azure.Security.KeyVault.Keys -->
39+
<Azure_Security_KeyVault_Keys_PackageVersion>4.7.0</Azure_Security_KeyVault_Keys_PackageVersion>
40+
41+
<!-- Azure.Security.KeyVault.Secrets -->
42+
<Azure_Security_KeyVault_Secrets_PackageVersion>4.7.0</Azure_Security_KeyVault_Secrets_PackageVersion>
3443

3544
<!-- Azure.Storage.Blobs -->
3645
<Azure_Storage_Blobs_PackageVersion>12.18.0</Azure_Storage_Blobs_PackageVersion>
@@ -149,7 +158,10 @@
149158
<!-- YamlDotNet -->
150159
<YamlDotNet_PackageVersion>15.1.1</YamlDotNet_PackageVersion>
151160

152-
</PropertyGroup>
161+
162+
163+
164+
</PropertyGroup>
153165

154166
<!--
155167
******************************************************************************

src/VirtualClient/VirtualClient.Core.FunctionalTests/VirtualClient.Core.FunctionalTests.csproj

Lines changed: 23 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -35,95 +35,43 @@
3535
Extensions Packages in Default Location
3636
-->
3737
<Target Name="CopyExtensionsPackagesToDefaultLocation" AfterTargets="Build">
38-
<Copy
39-
SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll"
40-
DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_1.dll"
41-
ContinueOnError="false"
42-
/>
43-
44-
<Copy
45-
SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.json"
46-
DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-1.json"
47-
ContinueOnError="false"
48-
/>
49-
50-
<Copy
51-
SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.yml"
52-
DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-1.yml"
53-
ContinueOnError="false"
54-
/>
55-
56-
<Copy
57-
SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-2.yaml"
58-
DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-2.yaml"
59-
ContinueOnError="false"
60-
/>
61-
62-
<Copy
63-
SourceFiles="$(ProjectDir)extensions_package_1.vcpkg"
64-
DestinationFiles="$(OutputPath)packages\extensions_package_1\extensions_package_1.vcpkg"
65-
ContinueOnError="false"
66-
/>
38+
<Copy SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll" DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_1.dll" ContinueOnError="false" />
39+
40+
<Copy SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.json" DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-1.json" ContinueOnError="false" />
41+
42+
<Copy SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.yml" DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-1.yml" ContinueOnError="false" />
43+
44+
<Copy SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-2.yaml" DestinationFiles="$(OutputPath)packages\extensions_package_1\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-2.yaml" ContinueOnError="false" />
45+
46+
<Copy SourceFiles="$(ProjectDir)extensions_package_1.vcpkg" DestinationFiles="$(OutputPath)packages\extensions_package_1\extensions_package_1.vcpkg" ContinueOnError="false" />
6747

6848
</Target>
6949

7050
<!--
7151
Extensions Packages in User-Defined/Non-Default Location (e.g. VC_PACKAGES_PATH).
7252
-->
7353
<Target Name="CopyExtensionsPackagesToNonDefaultLocation" AfterTargets="Build">
74-
<Copy
75-
SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll"
76-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_2.dll"
77-
ContinueOnError="false"
78-
/>
79-
80-
<Copy
81-
SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.json"
82-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-2.json"
83-
ContinueOnError="false"
84-
/>
85-
86-
<Copy
87-
SourceFiles="$(ProjectDir)extensions_package_2.vcpkg"
88-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\extensions_package_2.vcpkg"
89-
ContinueOnError="false"
90-
/>
91-
92-
<Copy
93-
SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll"
94-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_3.dll"
95-
ContinueOnError="false"
96-
/>
97-
98-
<Copy
99-
SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.yml"
100-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-3.yml"
101-
ContinueOnError="false"
102-
/>
103-
104-
<Copy
105-
SourceFiles="$(ProjectDir)extensions_package_3.vcpkg"
106-
DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\extensions_package_3.vcpkg"
107-
ContinueOnError="false"
108-
/>
54+
<Copy SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_2.dll" ContinueOnError="false" />
55+
56+
<Copy SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.json" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-2.json" ContinueOnError="false" />
57+
58+
<Copy SourceFiles="$(ProjectDir)extensions_package_2.vcpkg" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_2\extensions_package_2.vcpkg" ContinueOnError="false" />
59+
60+
<Copy SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\$(PlatformArchitectureName)\Example.VirtualClient.Extensions_3.dll" ContinueOnError="false" />
61+
62+
<Copy SourceFiles="$(ProjectDir)profiles\EXAMPLE-EXTENSIONS-1.yml" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\$(PlatformArchitectureName)\profiles\EXAMPLE-EXTENSIONS-3.yml" ContinueOnError="false" />
63+
64+
<Copy SourceFiles="$(ProjectDir)extensions_package_3.vcpkg" DestinationFiles="$(OutputPath)extensions_packages\extensions_package_3\extensions_package_3.vcpkg" ContinueOnError="false" />
10965

11066
</Target>
11167

11268
<!--
11369
Extensions Binaries in User-Defined/Non-Default Location (e.g. VC_LIBRARY_PATH).
11470
-->
11571
<Target Name="CopyExtensionsBinariesToNonDefaultLocationInOutput" AfterTargets="Build">
116-
<Copy
117-
SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll"
118-
DestinationFiles="$(OutputPath)extensions\extensions_1\Example.VirtualClient.Extensions_4.dll"
119-
ContinueOnError="false"
120-
/>
121-
122-
<Copy
123-
SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll"
124-
DestinationFiles="$(OutputPath)extensions\extensions_2\Example.VirtualClient.Extensions_5.dll"
125-
ContinueOnError="false"
126-
/>
72+
<Copy SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll" DestinationFiles="$(OutputPath)extensions\extensions_1\Example.VirtualClient.Extensions_4.dll" ContinueOnError="false" />
73+
74+
<Copy SourceFiles="$(OutputPath)VirtualClient.Core.FunctionalTests.dll" DestinationFiles="$(OutputPath)extensions\extensions_2\Example.VirtualClient.Extensions_5.dll" ContinueOnError="false" />
12775

12876
</Target>
12977

src/VirtualClient/VirtualClient.Core.UnitTests/VirtualClient.Core.UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
<ItemGroup>
13-
<PackageReference Include="Moq" Version="$(Moq_PackageVersion)" />
13+
<PackageReference Include="Moq" Version="$(Moq_PackageVersion)" />
1414
<PackageReference Include="NUnit" Version="$(NUnit_PackageVersion)" />
1515
<PackageReference Include="NUnit3TestAdapter" Version="$(NUnit3TestAdapter_PackageVersion)" />
1616
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(Microsoft_NET_Test_Sdk_PackageVersion)" />

src/VirtualClient/VirtualClient.Core/KeyVaultManager.cs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,23 @@ public async Task<KeyVaultDescriptor> GetSecretAsync(
7070
{
7171
this.ValidateKeyVaultStore();
7272
this.StoreDescription.ThrowIfNull(nameof(this.StoreDescription));
73-
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName), nameof(descriptor.VaultUri));
73+
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName));
7474

75-
var vaultUri = new Uri(descriptor.VaultUri);
76-
var secretName = descriptor.ObjectName;
75+
// Use descriptor.VaultUri if set, otherwise use the store's EndpointUri
76+
Uri vaultUri = !string.IsNullOrWhiteSpace(descriptor.VaultUri)
77+
? new Uri(descriptor.VaultUri)
78+
: ((DependencyKeyVaultStore)this.StoreDescription).EndpointUri;
7779

78-
var client = new SecretClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
80+
string secretName = descriptor.ObjectName;
81+
82+
SecretClient client = new SecretClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
7983

8084
try
8185
{
8286
return await (retryPolicy ?? KeyVaultManager.DefaultRetryPolicy).ExecuteAsync(async () =>
8387
{
8488
KeyVaultSecret secret = await client.GetSecretAsync(secretName, cancellationToken: cancellationToken);
85-
var result = new KeyVaultDescriptor(descriptor)
89+
KeyVaultDescriptor result = new KeyVaultDescriptor(descriptor)
8690
{
8791
Value = secret.Value,
8892
Version = secret.Properties.Version,
@@ -142,19 +146,23 @@ public async Task<KeyVaultDescriptor> GetKeyAsync(
142146
IAsyncPolicy retryPolicy = null)
143147
{
144148
this.ValidateKeyVaultStore();
145-
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName), nameof(descriptor.VaultUri));
149+
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName));
150+
151+
// Use descriptor.VaultUri if set, otherwise use the store's EndpointUri
152+
Uri vaultUri = !string.IsNullOrWhiteSpace(descriptor.VaultUri)
153+
? new Uri(descriptor.VaultUri)
154+
: ((DependencyKeyVaultStore)this.StoreDescription).EndpointUri;
146155

147-
var vaultUri = new Uri(descriptor.VaultUri);
148-
var keyName = descriptor.ObjectName;
156+
string keyName = descriptor.ObjectName;
149157

150-
var client = new KeyClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
158+
KeyClient client = new KeyClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
151159

152160
try
153161
{
154162
return await (retryPolicy ?? KeyVaultManager.DefaultRetryPolicy).ExecuteAsync(async () =>
155163
{
156164
KeyVaultKey key = await client.GetKeyAsync(keyName, cancellationToken: cancellationToken);
157-
var result = new KeyVaultDescriptor(descriptor)
165+
KeyVaultDescriptor result = new KeyVaultDescriptor(descriptor)
158166
{
159167
ObjectType = KeyVaultObjectType.Key,
160168
ObjectName = keyName,
@@ -213,19 +221,23 @@ public async Task<KeyVaultDescriptor> GetCertificateAsync(
213221
IAsyncPolicy retryPolicy = null)
214222
{
215223
this.ValidateKeyVaultStore();
216-
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName), nameof(descriptor.VaultUri));
224+
KeyVaultManager.ValidateDescriptor(descriptor, nameof(descriptor.ObjectName));
225+
226+
// Use descriptor.VaultUri if set, otherwise use the store's EndpointUri
227+
Uri vaultUri = !string.IsNullOrWhiteSpace(descriptor.VaultUri)
228+
? new Uri(descriptor.VaultUri)
229+
: ((DependencyKeyVaultStore)this.StoreDescription).EndpointUri;
217230

218-
var vaultUri = new Uri(descriptor.VaultUri);
219-
var certName = descriptor.ObjectName;
231+
string certName = descriptor.ObjectName;
220232

221-
var client = new CertificateClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
233+
CertificateClient client = new CertificateClient(vaultUri, ((DependencyKeyVaultStore)this.StoreDescription).Credentials);
222234

223235
try
224236
{
225237
return await (retryPolicy ?? KeyVaultManager.DefaultRetryPolicy).ExecuteAsync(async () =>
226238
{
227239
KeyVaultCertificateWithPolicy cert = await client.GetCertificateAsync(certName, cancellationToken: cancellationToken);
228-
var result = new KeyVaultDescriptor(descriptor)
240+
KeyVaultDescriptor result = new KeyVaultDescriptor(descriptor)
229241
{
230242
ObjectType = KeyVaultObjectType.Certificate,
231243
ObjectName = certName,
@@ -278,7 +290,7 @@ public async Task<KeyVaultDescriptor> GetCertificateAsync(
278290
private static void ValidateDescriptor(DependencyDescriptor descriptor, params string[] requiredProperties)
279291
{
280292
descriptor.ThrowIfNull(nameof(descriptor));
281-
foreach (var property in requiredProperties)
293+
foreach (string property in requiredProperties)
282294
{
283295
if (!descriptor.ContainsKey(property) || string.IsNullOrWhiteSpace(descriptor[property]?.ToString()))
284296
{

src/VirtualClient/VirtualClient.Core/VirtualClient.Core.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
<ItemGroup>
1212
<!-- Global package dependency versions are defined in the Module.props for the solution. -->
1313
<PackageReference Include="Azure.Identity" Version="$(Azure_Identity_PackageVersion)" />
14+
<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="$(Azure_Security_KeyVault_Certificates_PackageVersion)" />
15+
<PackageReference Include="Azure.Security.KeyVault.Keys" Version="$(Azure_Security_KeyVault_Keys_PackageVersion)" />
16+
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="$(Azure_Security_KeyVault_Secrets_PackageVersion)" />
1417
<!-- PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(Microsoft_Extensions_FileSystemGlobbing_PackageVersion)" /-->
1518
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="$(Microsoft_CodeAnalysis_CSharp_Scripting_PackageVersion)" />
1619
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="$(System_Diagnostics_PerformanceCounter_PackageVersion)" />
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
// REMOVE THIS FILE FROM HERE! WE DONT NEED IT.
5+
6+
namespace VirtualClient.Dependencies
7+
{
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
using Microsoft.Extensions.DependencyInjection;
14+
using VirtualClient.Common.Extensions;
15+
using VirtualClient.Common.Telemetry;
16+
using VirtualClient.Contracts;
17+
18+
/// <summary>
19+
/// Resolves secret values from Azure Key Vault using the injected IKeyVaultManager.
20+
/// </summary>
21+
public class DependencySecretResolution : VirtualClientComponent
22+
{
23+
/// <summary>
24+
/// Initializes a new instance of the <see cref="DependencySecretResolution"/> class.
25+
/// </summary>
26+
/// <param name="dependencies">Provides all of the required dependencies to the Virtual Client component.</param>
27+
/// <param name="parameters">
28+
/// Parameters defined in the execution profile or supplied to the Virtual Client on the command line.
29+
/// </param>
30+
public DependencySecretResolution(IServiceCollection dependencies, IDictionary<string, IConvertible> parameters = null)
31+
: base(dependencies, parameters)
32+
{
33+
}
34+
35+
/// <summary>
36+
/// The list of secret names to resolve from the Key Vault.
37+
/// </summary>
38+
public IList<string> SecretNames
39+
{
40+
get
41+
{
42+
string names = this.Parameters.GetValue<string>(nameof(this.SecretNames));
43+
return string.IsNullOrWhiteSpace(names)
44+
? new List<string>()
45+
: names.Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries)
46+
.Select(n => n.Trim())
47+
.ToList();
48+
}
49+
50+
set
51+
{
52+
this.Parameters[nameof(this.SecretNames)] = string.Join(";", value);
53+
}
54+
}
55+
56+
/// <summary>
57+
/// The resolved secrets (name-value pairs).
58+
/// </summary>
59+
public IDictionary<string, string> ResolvedSecrets { get; private set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
60+
61+
/// <summary>
62+
/// Resolves the secrets from Key Vault and stores them in <see cref="ResolvedSecrets"/>.
63+
/// </summary>
64+
protected override async Task ExecuteAsync(EventContext telemetryContext, CancellationToken cancellationToken)
65+
{
66+
if (this.SecretNames == null || !this.SecretNames.Any())
67+
{
68+
throw new DependencyException(
69+
"At least one secret name must be specified to resolve secrets.",
70+
ErrorReason.DependencyDescriptionInvalid);
71+
}
72+
73+
IKeyVaultManager keyVaultManager = this.Dependencies.GetService<IKeyVaultManager>();
74+
if (keyVaultManager == null)
75+
{
76+
throw new DependencyException(
77+
"Key Vault manager is not available. Ensure the dependency is registered.",
78+
ErrorReason.DependencyDescriptionInvalid);
79+
}
80+
81+
var resolved = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
82+
83+
foreach (string secretName in this.SecretNames)
84+
{
85+
var descriptor = new KeyVaultDescriptor
86+
{
87+
ObjectName = secretName,
88+
ObjectType = KeyVaultObjectType.Secret
89+
// VaultUri is not set here; the manager uses its injected store.
90+
};
91+
92+
KeyVaultDescriptor secret = await keyVaultManager.GetSecretAsync(descriptor, cancellationToken);
93+
resolved[secretName] = secret.Value;
94+
}
95+
96+
this.ResolvedSecrets = resolved;
97+
98+
// Optionally, add resolved secret names to telemetry context (do not log values in production!)
99+
telemetryContext.AddContext("resolvedSecrets", string.Join(",", this.ResolvedSecrets.Keys));
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)