Create a new secret provider
#
PrerequisitesThe secret providers are configured during the initial application build-up in the Program.cs
:
using Microsoft.Extensions.Hosting;
public class Program{ public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); }
public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureSecretStore((context, config, builder) => { builder.AddEnvironmentVariables(); }) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>()); }}
This section describes how a new secret store source can be added to the pipeline.
#
Developing a secret providerInstall the NuGet package
Arcus.Security.Core
.Implement your own implementation of the
ISecretProvider
ex:using Arcus.Security.Core; namespace Application.Security.CustomProviders{ public class RegistrySecretProvider : ISecretProvider { public Task<string> GetRawSecretAsync(string secretName) { object value = Registry.LocalMachine.GetValue(secretName); return Task.FromResult(value?.ToString()); } public async Task<Secret> GetSecretAsync(string secretName) { string secretValue = await GetRawSecretAsync(secretName); return new Secret(secretValue); } }}
Optionally, you can provide an extension for a consumer-friendly way to add the provider. ex:
namespace Microsoft.Extensions.Hosting { public static class SecretStoreBuilderExtensions { public static SecretStoreBuilder AddRegistry(this SecretStoreBuilder builder) { var provider = new RegistrySecretProvider(); return builder.AddProvider(provider); } } }
And in the
Startup.cs
:.ConfigureSecretStore((context, config, builder) =>{ builder.AddRegistry();})
Or, you can use your provider directly.
.ConfigureSecretStore((context, config, builder) => { var provider = new RegistrySecretProvider(); builder.AddProvider(provider);})
Now, the secret source is available in the resulting
ISecretProvider
registered in the dependency injection container. ex:using Arcus.Security.Core; namespace Application.Controllers{ [ApiController] public class OrderController : ControllerBase { public class OrderController(ISecretProvider secretProvider) { } }}
Note that when your secret provider requires caching, you can wrap the provider in a
CachedSecretProvider
at registration: ex:using Arcus.Security.Core.Caching; namespace Microsoft.Extensions.Hosting { public static class SecretStoreBuilderExtensions { public static SecretStoreBuilder AddCachedRegistry(this SecretStoreBuilder builder) { var provider = new RegistrySecretProvider(); var configuration = new CacheConfiguration(TimeSpan.FromSeconds(5)); return builder.AddProvider(new CachedSecretProvider(provider, configuration)); } } }
When accessing the provider in the application, you can use the
ICachedSecretProvider
to have access to the cache-specific methods. ex:using Arcus.Security.Core.Caching; namespace Application.Controllers { [ApiController] public class OrderController : ControllerBase { public class OrderController(ICachedSecretProvider secretProvider) { } } }
#
Contribute your secret providerWe are open for contributions and are more than happy to receive pull requests with new secret providers!