diff --git a/src/NuGet.Services.KeyVault/KeyVaultReader.cs b/src/NuGet.Services.KeyVault/KeyVaultReader.cs
index 5214f8c6f8..f6302bc190 100644
--- a/src/NuGet.Services.KeyVault/KeyVaultReader.cs
+++ b/src/NuGet.Services.KeyVault/KeyVaultReader.cs
@@ -13,14 +13,23 @@ namespace NuGet.Services.KeyVault
{
///
/// Reads secretes from KeyVault.
- /// Authentication with KeyVault is done using either a managed identity or a certificate in location:LocalMachine store name:My
+ /// Authentication with KeyVault is done using either a managed identity or a certificate in location:LocalMachine store name:My
///
public class KeyVaultReader : ISecretReader
{
private readonly KeyVaultConfiguration _configuration;
private readonly Lazy _keyVaultClient;
-
protected SecretClient KeyVaultClient => _keyVaultClient.Value;
+ internal bool _testMode;
+ internal bool _isUsingSendx5c;
+
+ internal KeyVaultReader(SecretClient secretClient, KeyVaultConfiguration configuration, bool testMode = false)
+ {
+ _configuration = configuration;
+ _keyVaultClient = new Lazy(() => secretClient);
+ _testMode = testMode;
+ InitializeClient();
+ }
public KeyVaultReader(KeyVaultConfiguration configuration)
{
@@ -97,10 +106,27 @@ private SecretClient InitializeClient()
credential = new ManagedIdentityCredential(_configuration.ClientId);
}
}
+ else if (_configuration.SendX5c)
+ {
+ var clientCredentialOptions = new ClientCertificateCredentialOptions
+ {
+ SendCertificateChain = true
+ };
+
+ credential = new ClientCertificateCredential(_configuration.TenantId, _configuration.ClientId, _configuration.Certificate, clientCredentialOptions);
+
+ // If we are in unit testing mode, we dont actually create a SecretClient
+ if (_testMode)
+ {
+ _isUsingSendx5c = true;
+ return _keyVaultClient.Value;
+ }
+ }
else
{
credential = new ClientCertificateCredential(_configuration.TenantId, _configuration.ClientId, _configuration.Certificate);
}
+
return new SecretClient(GetKeyVaultUri(_configuration), credential);
}
diff --git a/src/NuGet.Services.KeyVault/Properties/AssemblyInfo.cs b/src/NuGet.Services.KeyVault/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..cb1d0059e8
--- /dev/null
+++ b/src/NuGet.Services.KeyVault/Properties/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Runtime.CompilerServices;
+
+#if SIGNED_BUILD
+[assembly: InternalsVisibleTo("NuGet.Services.KeyVault.Tests,PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+#else
+[assembly: InternalsVisibleTo("NuGet.Services.KeyVault.Tests")]
+#endif
\ No newline at end of file
diff --git a/tests/NuGet.Services.KeyVault.Tests/KeyVaultReaderFacts.cs b/tests/NuGet.Services.KeyVault.Tests/KeyVaultReaderFacts.cs
new file mode 100644
index 0000000000..ff4398555a
--- /dev/null
+++ b/tests/NuGet.Services.KeyVault.Tests/KeyVaultReaderFacts.cs
@@ -0,0 +1,40 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
+using Azure.Security.KeyVault.Secrets;
+using Moq;
+using Xunit;
+
+namespace NuGet.Services.KeyVault.Tests
+{
+ public class KeyVaultReaderFacts
+ {
+ [Fact]
+ public void VerifyKeyvaultReaderSendX5c()
+ {
+ // Arrange
+ const string vaultName = "vaultName";
+ const string tenantId = "tenantId";
+ const string clientId = "clientId";
+
+ X509Certificate2 certificate = new X509Certificate2();
+ KeyVaultConfiguration keyVaultConfiguration = new KeyVaultConfiguration(vaultName, tenantId, clientId, certificate, sendX5c:true);
+
+ var mockSecretClient = new Mock();
+
+ // Act
+ var keyvaultReader = new KeyVaultReader(mockSecretClient.Object, keyVaultConfiguration, testMode: true);
+
+ // Assert
+
+ // The KeyVaultReader constructor is internal which accepts a SecretClient object, KeyVaultConfiguration object and a boolean testMode parameter
+ // The KeyVaultConfiguration object has the sendX5c property which is set to true
+ // The KeyVaultReader object has an internal boolean _isUsingSendx5c which is set to true if the sendX5c property is set to true
+ // The KeyVaultReader shot-circuits when the testMode is set to true instead of calling Azure KeyVault
+ Assert.True(keyvaultReader._isUsingSendx5c);
+ }
+ }
+}
\ No newline at end of file