Skip to main content

Building Custom Providers

SecretsManager is designed to be extensible. You can implement your own provider for any secret backend.

Implement ISecretProvider​

Create a class that implements the ISecretProvider interface:

MyCustomSecretProvider.cs
using SecretsManager;

public class MyCustomSecretProvider : ISecretProvider
{
public async Task<SecretValue> GetSecretAsync(
string key, SecretQuery? query = null, CancellationToken ct = default)
{
// Retrieve secret from your backend
var value = await YourBackend.GetAsync(key, ct);
return new SecretValue(key, value);
}

public async Task<SecretValue> PutSecretAsync(
string key, string value, SecretMetadata? metadata = null, CancellationToken ct = default)
{
await YourBackend.SetAsync(key, value, ct);
return new SecretValue(key, value);
}

public async Task DeleteSecretAsync(string key, CancellationToken ct = default)
{
await YourBackend.DeleteAsync(key, ct);
}

public async Task<IReadOnlyList<SecretVersionInfo>> GetSecretVersionsAsync(
string key, CancellationToken ct = default)
{
return await YourBackend.ListVersionsAsync(key, ct);
}

public async Task<bool> SecretExistsAsync(string key, CancellationToken ct = default)
{
return await YourBackend.ExistsAsync(key, ct);
}

public ValueTask DisposeAsync()
{
// Clean up resources
return ValueTask.CompletedTask;
}
}

Implement ISecretProviderFactory​

To integrate with the builder pattern, implement ISecretProviderFactory:

MyCustomSecretProviderFactory.cs
using SecretsManager.Builder;

public class MyCustomSecretProviderFactory : ISecretProviderFactory
{
public string ProviderName => "mycustom";

public ISecretProvider Create(Dictionary<string, string> settings)
{
var endpoint = settings["endpoint"];
var apiKey = settings["apiKey"];
return new MyCustomSecretProvider(endpoint, apiKey);
}
}

Add Builder Extension​

Create a fluent extension method:

SecretProviderBuilderExtensions.cs
public static class SecretProviderBuilderExtensions
{
public static SecretProviderBuilder WithMyCustom(
this SecretProviderBuilder builder,
Action<MyCustomOptions>? configure = null)
{
builder.RegisterFactory(new MyCustomSecretProviderFactory());
if (configure != null)
{
var options = new MyCustomOptions();
configure(options);
builder.ApplyOptions(options);
}
return builder;
}
}
tip

Follow the existing provider implementations in the repository as reference. The FileSystem provider is the simplest starting point.