Skip to content

Commit a0e0acd

Browse files
authored
Feature - add Azure Key Vault secret store overloads w/o Managed Identity clientId (#236)
* Feature - add Azure Key Vault secret store overloads w/o Managed Identity clientId * pr-style: remove unnecessary blank line
1 parent cf0101d commit a0e0acd

File tree

2 files changed

+221
-1
lines changed

2 files changed

+221
-1
lines changed

src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs

+108
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,27 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedServiceIdentityWithO
372372
configureOptions);
373373
}
374374

375+
/// <summary>
376+
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
377+
/// </summary>
378+
/// <param name="builder">The builder to create the secret store.</param>
379+
/// <param name="rawVaultUri">The Uri of the Azure Key Vault you want to connect to.</param>
380+
/// The optional client id to authenticate for a user assigned managed identity.
381+
/// More information on user assigned managed identities can be found here: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview#how-a-user-assigned-managed-identity-works-with-an-azure-vm</param>
382+
/// <param name="allowCaching">The flag to indicate whether to include caching during secret retrieval in Azure key vault.</param>
383+
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="builder"/> is <c>null</c>.</exception>
384+
/// <exception cref="ArgumentException">Thrown when the <paramref name="rawVaultUri"/> is blank.</exception>
385+
public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
386+
this SecretStoreBuilder builder,
387+
string rawVaultUri,
388+
bool allowCaching = false)
389+
{
390+
Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider");
391+
Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store");
392+
393+
return AddAzureKeyVaultWithManagedIdentity(builder, rawVaultUri, clientId: null, allowCaching: allowCaching);
394+
}
395+
375396
/// <summary>
376397
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
377398
/// </summary>
@@ -402,6 +423,38 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
402423
allowCaching: allowCaching);
403424
}
404425

426+
/// <summary>
427+
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
428+
/// </summary>
429+
/// <param name="builder">The builder to create the secret store.</param>
430+
/// <param name="rawVaultUri">The Uri of the Azure Key Vault you want to connect to.</param>
431+
/// <param name="allowCaching">The flag to indicate whether to include caching during secret retrieval in Azure key vault.</param>
432+
/// <param name="configureOptions">The optional additional options to configure the Azure Key Vault secret source.</param>
433+
/// <param name="name">The unique name to register this Azure Key Vault provider in the secret store.</param>
434+
/// <param name="mutateSecretName">The optional function to mutate the secret name before looking it up.</param>
435+
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="builder"/> is <c>null</c>.</exception>
436+
/// <exception cref="ArgumentException">Thrown when the <paramref name="rawVaultUri"/> is blank.</exception>
437+
public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
438+
this SecretStoreBuilder builder,
439+
string rawVaultUri,
440+
Action<KeyVaultOptions> configureOptions,
441+
string name,
442+
Func<string, string> mutateSecretName,
443+
bool allowCaching = false)
444+
{
445+
Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider");
446+
Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store");
447+
448+
return AddAzureKeyVaultWithManagedIdentity(
449+
builder,
450+
rawVaultUri,
451+
clientId: null,
452+
configureOptions: configureOptions,
453+
name: name,
454+
mutateSecretName: mutateSecretName,
455+
allowCaching: allowCaching);
456+
}
457+
405458
/// <summary>
406459
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
407460
/// </summary>
@@ -500,6 +553,29 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedServiceIdentityWithO
500553
configureOptions);
501554
}
502555

556+
/// <summary>
557+
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
558+
/// </summary>
559+
/// <param name="builder">The builder to create the secret store.</param>
560+
/// <param name="rawVaultUri">The Uri of the Azure Key Vault you want to connect to.</param>
561+
/// <param name="cacheConfiguration">The configuration to control how the caching will be done.</param>
562+
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="builder"/> is <c>null</c>.</exception>
563+
/// <exception cref="ArgumentException">Thrown when the <paramref name="rawVaultUri"/> is blank.</exception>
564+
public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
565+
this SecretStoreBuilder builder,
566+
string rawVaultUri,
567+
ICacheConfiguration cacheConfiguration)
568+
{
569+
Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider");
570+
Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store");
571+
572+
return AddAzureKeyVaultWithManagedIdentity(
573+
builder,
574+
rawVaultUri,
575+
cacheConfiguration,
576+
clientId: null);
577+
}
578+
503579
/// <summary>
504580
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
505581
/// </summary>
@@ -529,6 +605,38 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
529605
name: null,
530606
mutateSecretName: null);
531607
}
608+
609+
/// <summary>
610+
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.
611+
/// </summary>
612+
/// <param name="builder">The builder to create the secret store.</param>
613+
/// <param name="rawVaultUri">The Uri of the Azure Key Vault you want to connect to.</param>
614+
/// <param name="cacheConfiguration">The configuration to control how the caching will be done.</param>
615+
/// <param name="configureOptions">The optional additional options to configure the Azure Key Vault secret source.</param>
616+
/// <param name="name">The unique name to register this Azure Key Vault provider in the secret store.</param>
617+
/// <param name="mutateSecretName">The optional function to mutate the secret name before looking it up.</param>
618+
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="builder"/> is <c>null</c>.</exception>
619+
/// <exception cref="ArgumentException">Thrown when the <paramref name="rawVaultUri"/> is blank.</exception>
620+
public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity(
621+
this SecretStoreBuilder builder,
622+
string rawVaultUri,
623+
ICacheConfiguration cacheConfiguration,
624+
Action<KeyVaultOptions> configureOptions,
625+
string name,
626+
Func<string, string> mutateSecretName)
627+
{
628+
Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider");
629+
Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store");
630+
631+
return AddAzureKeyVaultWithManagedIdentity(
632+
builder,
633+
rawVaultUri,
634+
cacheConfiguration,
635+
clientId: null,
636+
configureOptions: configureOptions,
637+
name: name,
638+
mutateSecretName: mutateSecretName);
639+
}
532640

533641
/// <summary>
534642
/// Adds Azure Key Vault as a secret source which uses Managed Identity authentication.

src/Arcus.Security.Tests.Unit/KeyVault/Extensions/SecretStoreBuilderExtensionsTests.cs

+113-1
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,22 @@ public void AddAzureKeyVaultWithManagedServiceIdentity_WithCachingWithBlankVault
536536
// Assert
537537
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
538538
}
539-
539+
540+
[Theory]
541+
[ClassData(typeof(Blanks))]
542+
public void AddAzureKeyVaultWithManagedIdentitySimple_WithoutVaultUriWithoutClientId_Throws(string vaultUri)
543+
{
544+
// Arrange
545+
var builder = new HostBuilder();
546+
547+
// Act
548+
builder.ConfigureSecretStore(
549+
(config, stores) => stores.AddAzureKeyVaultWithManagedIdentity(vaultUri));
550+
551+
// Assert
552+
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
553+
}
554+
540555
[Theory]
541556
[ClassData(typeof(Blanks))]
542557
public void AddAzureKeyVaultWithManagedIdentitySimple_WithoutVaultUri_Throws(string vaultUri)
@@ -552,6 +567,22 @@ public void AddAzureKeyVaultWithManagedIdentitySimple_WithoutVaultUri_Throws(str
552567
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
553568
}
554569

570+
[Theory]
571+
[ClassData(typeof(Blanks))]
572+
public void AddAzureKeyVaultWithManagedIdentitySimpleCacheConfiguration_WithoutVaultUriWithoutClientId_Throws(string vaultUri)
573+
{
574+
// Arrange
575+
var builder = new HostBuilder();
576+
var cacheConfiguration = new CacheConfiguration();
577+
578+
// Act
579+
builder.ConfigureSecretStore(
580+
(config, stores) => stores.AddAzureKeyVaultWithManagedIdentity(vaultUri, cacheConfiguration));
581+
582+
// Assert
583+
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
584+
}
585+
555586
[Theory]
556587
[ClassData(typeof(Blanks))]
557588
public void AddAzureKeyVaultWithManagedIdentitySimpleCacheConfiguration_WithoutVaultUri_Throws(string vaultUri)
@@ -583,6 +614,21 @@ public void AddAzureKeyVaultWithManagedServiceIdentityWithOptions_WithCachingWit
583614
// Assert
584615
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
585616
}
617+
618+
[Theory]
619+
[ClassData(typeof(Blanks))]
620+
public void AddAzureKeyVaultWithManagedIdentity_WithBlankVaultUriWithoutClientId_Throws(string vaultUri)
621+
{
622+
// Arrange
623+
var builder = new HostBuilder();
624+
625+
// Act
626+
builder.ConfigureSecretStore(
627+
(config, stores) => stores.AddAzureKeyVaultWithManagedIdentity(vaultUri, configureOptions: null, name: null, mutateSecretName: null));
628+
629+
// Assert
630+
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
631+
}
586632

587633
[Theory]
588634
[ClassData(typeof(Blanks))]
@@ -599,6 +645,22 @@ public void AddAzureKeyVaultWithManagedIdentity_WithBlankVaultUri_Throws(string
599645
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
600646
}
601647

648+
[Theory]
649+
[ClassData(typeof(Blanks))]
650+
public void AddAzureKeyVaultWithManagedIdentity_WithCachingWithBlankVaultUriWithoutClientId_Throws(string vaultUri)
651+
{
652+
// Arrange
653+
var builder = new HostBuilder();
654+
var cacheConfiguration = Mock.Of<ICacheConfiguration>();
655+
656+
// Act
657+
builder.ConfigureSecretStore(
658+
(config, stores) => stores.AddAzureKeyVaultWithManagedIdentity(vaultUri, cacheConfiguration: cacheConfiguration, configureOptions: null, name: null, mutateSecretName: null));
659+
660+
// Assert
661+
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
662+
}
663+
602664
[Theory]
603665
[ClassData(typeof(Blanks))]
604666
public void AddAzureKeyVaultWithManagedIdentity_WithCachingWithBlankVaultUri_Throws(string vaultUri)
@@ -615,6 +677,30 @@ public void AddAzureKeyVaultWithManagedIdentity_WithCachingWithBlankVaultUri_Thr
615677
Assert.ThrowsAny<ArgumentException>(() => builder.Build());
616678
}
617679

680+
[Fact]
681+
public void AddAzureKeyVaultWithManagedIdentity_WithValidArgumentsWithoutClientId_CreatesProvider()
682+
{
683+
// Arrange
684+
var builder = new HostBuilder();
685+
686+
// Act
687+
builder.ConfigureSecretStore(
688+
(config, stores) =>
689+
{
690+
stores.AddAzureKeyVaultWithManagedIdentity(
691+
GenerateVaultUri(),
692+
configureOptions: options => options.TrackDependency = true,
693+
name: "Azure Key Vault",
694+
mutateSecretName: name => name.Replace(":", "."));
695+
});
696+
697+
// Assert
698+
using (IHost host = builder.Build())
699+
{
700+
Assert.NotNull(host.Services.GetRequiredService<ISecretProvider>());
701+
}
702+
}
703+
618704
[Fact]
619705
public void AddAzureKeyVaultWithManagedIdentity_WithValidArguments_CreatesProvider()
620706
{
@@ -640,6 +726,32 @@ public void AddAzureKeyVaultWithManagedIdentity_WithValidArguments_CreatesProvid
640726
}
641727
}
642728

729+
[Fact]
730+
public void AddAzureKeyVaultWithManagedIdentityWithCacheConfiguration_WithValidArgumentsWithoutClientId_CreatesProvider()
731+
{
732+
// Arrange
733+
var builder = new HostBuilder();
734+
var cacheConfiguration = new CacheConfiguration();
735+
736+
// Act
737+
builder.ConfigureSecretStore(
738+
(config, stores) =>
739+
{
740+
stores.AddAzureKeyVaultWithManagedIdentity(
741+
GenerateVaultUri(),
742+
cacheConfiguration: cacheConfiguration,
743+
configureOptions: options => options.TrackDependency = true,
744+
name: "Azure Key Vault",
745+
mutateSecretName: name => name.Replace(":", "."));
746+
});
747+
748+
// Assert
749+
using (IHost host = builder.Build())
750+
{
751+
Assert.NotNull(host.Services.GetRequiredService<ISecretProvider>());
752+
}
753+
}
754+
643755
[Fact]
644756
public void AddAzureKeyVaultWithManagedIdentityWithCacheConfiguration_WithValidArguments_CreatesProvider()
645757
{

0 commit comments

Comments
 (0)