View on GitHub

Arcus Security

Azure Security development in a breeze

Create a new secret provider

Prerequisites

The secret providers are configured during the initial application build-up in the Program.cs:

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 provider

  1. Install the NuGet package Arcus.Security.Core.
  2. Implement your own implementation of the ISecretProvider ex:
    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);
        }
    }
    
  3. Optionally, you can provide an extension for a consumer-friendly way to add the provider. ex:
     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);
    })
    
  4. Now, the secret source is available in the resulting ISecretProvider registered in the dependency injection container. ex:
    [ApiController]
    public class OrderController : ControllerBase
    {
        public class OrderController(ISecretProvider secretProvider)
        {
        }
    }
    
  5. Note that when your secret provider requires caching, you can wrap the provider in a CachedSecretProvider at registration: ex:
    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:

    [ApiController]
    public class OrderController : ControllerBase
    {
        public class OrderController(ICachedSecretProvider secretProvider)
        {
        }
    }
    

Contribute your secret provider

We are open for contributions and are more than happy to receive pull requests with new secret providers! ← back