FractalDataWorks.Services.SecretManagers
0.4.0-preview.6
dotnet add package FractalDataWorks.Services.SecretManagers --version 0.4.0-preview.6
NuGet\Install-Package FractalDataWorks.Services.SecretManagers -Version 0.4.0-preview.6
<PackageReference Include="FractalDataWorks.Services.SecretManagers" Version="0.4.0-preview.6" />
<PackageVersion Include="FractalDataWorks.Services.SecretManagers" Version="0.4.0-preview.6" />
<PackageReference Include="FractalDataWorks.Services.SecretManagers" />
paket add FractalDataWorks.Services.SecretManagers --version 0.4.0-preview.6
#r "nuget: FractalDataWorks.Services.SecretManagers, 0.4.0-preview.6"
#:package FractalDataWorks.Services.SecretManagers@0.4.0-preview.6
#addin nuget:?package=FractalDataWorks.Services.SecretManagers&version=0.4.0-preview.6&prerelease
#tool nuget:?package=FractalDataWorks.Services.SecretManagers&version=0.4.0-preview.6&prerelease
FractalDataWorks.Services.SecretManagers
Implementation package for secret management services in the FractalDataWorks framework. Provides DefaultSecretManagerProvider, SecretManagerTypeBase, and command implementations for secret operations across different providers.
Installation
dotnet add package FractalDataWorks.Services.SecretManagers
Target Framework: net10.0
Service Registration (Three-Phase Pattern)
Secret managers use a three-phase registration pattern for proper startup initialization:
var builder = WebApplication.CreateBuilder(args);
// Optional: Create logger for startup diagnostics (before DI is built)
using var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
// Phase 1: Configure (binds IOptions from configuration)
SecretManagerTypes.Configure(builder.Services, builder.Configuration, loggerFactory);
// Phase 1: Register (adds factories to DI)
SecretManagerTypes.Register(builder.Services, loggerFactory);
var app = builder.Build();
// Phase 2: Initialize (optional, for eager loading)
SecretManagerTypes.Initialize(app.Services, loggerFactory);
app.Run();
Note: Initialize() is optional. When called, it eagerly resolves all factories at startup. When omitted, factories resolve lazily on first use.
Package Contents
This package provides:
DefaultSecretManagerProvider- Provider implementation for resolving secret manager servicesSecretManagerTypeBase<TService, TFactory, TConfiguration>- Base class for secret manager type definitionsSecretManagerTypes- Source-generated collection of secret manager typesSecretValue- Secure container for secret data with proper disposal- Command implementations:
GetSecretManagerCommand,SetSecretManagementCommand,DeleteSecretManagementCommand,ListSecretsManagementCommand
DefaultSecretManagerProvider
The provider acts as a mini-IoC container for secret manager services, using a three-phase registration pattern.
From DefaultSecretManagerProvider.cs:44-63:
public sealed class DefaultSecretManagerProvider : ServiceProvider, ISecretManagerProvider
{
private readonly Dictionary<string, ISecretManagerServiceFactory> _factories = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, Func<string, ISecretManagerConfiguration?>> _configLoaders = new(StringComparer.OrdinalIgnoreCase);
private readonly ConcurrentDictionary<string, ISecretManagerConfiguration> _configurationCache = new(StringComparer.OrdinalIgnoreCase);
private readonly ILogger<DefaultSecretManagerProvider> _logger;
private readonly IConfiguration _configuration;
public DefaultSecretManagerProvider(
ILogger<DefaultSecretManagerProvider> logger,
IConfiguration configuration)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
Creating a Secret Manager by Configuration Name
The provider implements IFdwServiceProvider<ISecretManager, ISecretManagerConfiguration>, providing Create() methods:
public class MyService
{
private readonly ISecretManagerProvider _secretManagerProvider;
public MyService(ISecretManagerProvider secretManagerProvider)
{
_secretManagerProvider = secretManagerProvider;
}
public IGenericResult<ISecretManager> GetSecretManager(string name)
{
// Create secret manager by configuration name
var result = _secretManagerProvider.Create(name);
if (!result.IsSuccess)
{
// Handle failure
return result;
}
// Use the secret manager
var secretManager = result.Value!;
return result;
}
}
Configuration
Secret managers are configured in the SecretManagers section. The provider reads the SecretManagerType discriminator to determine which factory to use.
Configuration example from DefaultSecretManagerProvider.cs:31-42:
{
"SecretManagers": {
"AzureKeyVault": {
"SecretManagerType": "AzureKeyVault",
"VaultUri": "https://myvault.vault.azure.net/",
"AuthenticationMethod": "ManagedIdentity"
}
}
}
SecretManagerTypeBase
Base class for defining secret manager service types with provider-specific capabilities.
From SecretManagerTypeBase.cs:24-30:
public abstract class SecretManagerTypeBase<TService, TFactory, TConfiguration> :
ServiceTypeBase<TService, TFactory, TConfiguration, DefaultSecretManagerProvider>,
ISecretManagerType<TService, TFactory, TConfiguration>
where TService : class, ISecretManager
where TFactory : class, ISecretManagerServiceFactory<TService, TConfiguration>
where TConfiguration : class, ISecretManagerConfiguration
{
Provider Capabilities
From SecretManagerTypeBase.cs:39-52:
/// <summary>
/// Gets the secret store types supported by this provider.
/// </summary>
public string[] SupportedSecretStores { get; }
/// <summary>
/// Gets the secret types supported by this provider.
/// </summary>
public IReadOnlyList<string> SupportedSecretTypes { get; }
/// <summary>
/// Gets a value indicating whether this provider supports secret rotation.
/// </summary>
public bool SupportsRotation { get; }
/// <summary>
/// Gets a value indicating whether this provider supports secret versioning.
/// </summary>
public bool SupportsVersioning { get; }
SecretManagerTypes Collection
Source-generated collection of secret manager service types.
From SecretManagerTypes.cs:1-26:
[ExcludeFromCodeCoverage]
[ServiceTypeCollection(
typeof(SecretManagerTypeBase<ISecretManager, ISecretManagerServiceFactory<ISecretManager, ISecretManagerConfiguration>, ISecretManagerConfiguration>),
typeof(ISecretManagerType),
typeof(SecretManagerTypes),
GenerateProvider = true,
ServiceInterface = typeof(ISecretManager),
ConfigurationInterface = typeof(ISecretManagerConfiguration),
ProviderType = typeof(DefaultSecretManagerProvider),
ProviderInterface = typeof(ISecretManagerProvider))]
public partial class SecretManagerTypes : ServiceTypeCollectionBase<
SecretManagerTypeBase<ISecretManager, ISecretManagerServiceFactory<ISecretManager, ISecretManagerConfiguration>, ISecretManagerConfiguration>,
ISecretManagerType<ISecretManager, ISecretManagerServiceFactory<ISecretManager, ISecretManagerConfiguration>, ISecretManagerConfiguration>>
{
}
Commands
GetSecretManagerCommand
Command for retrieving secrets from a provider.
From Commands/GetSecretManagementCommand.cs:15-37:
public sealed class GetSecretManagerCommand : SecretManagerCommandBase, ISecretManagerCommand<SecretValue>
{
public GetSecretManagerCommand(
string? container,
string secretKey,
IReadOnlyDictionary<string, object?>? parameters = null,
IReadOnlyDictionary<string, object>? metadata = null,
TimeSpan? timeout = null)
: base("GetSecret", container, secretKey, typeof(SecretValue), parameters, metadata, timeout)
{
if (string.IsNullOrWhiteSpace(secretKey))
throw new ArgumentException("Secret key cannot be null or empty for GetSecret operation.", nameof(secretKey));
}
/// <inheritdoc/>
public override bool IsSecretModifying => false;
public string? Version => Parameters.TryGetValue(nameof(Version), out var version) ? version?.ToString() : null;
public bool IncludeMetadata => Parameters.TryGetValue(nameof(IncludeMetadata), out var include) &&
include is bool includeMetadata && includeMetadata;
Factory methods for creating commands from Commands/GetSecretManagementCommand.cs:63-98:
public static GetSecretManagerCommand Latest(string? container, string secretKey, bool includeMetadata = false, TimeSpan? timeout = null)
{
var parameters = includeMetadata
? new Dictionary<string, object?>(StringComparer.Ordinal) { [nameof(IncludeMetadata)] = true }
: null;
return new GetSecretManagerCommand(container, secretKey, parameters, null, timeout);
}
public static GetSecretManagerCommand ForVersion(string? container, string secretKey, string version, bool includeMetadata = false, TimeSpan? timeout = null)
{
if (string.IsNullOrWhiteSpace(version))
throw new ArgumentException("Version cannot be null or empty.", nameof(version));
var parameters = new Dictionary<string, object?>(StringComparer.Ordinal)
{
[nameof(Version)] = version
};
if (includeMetadata)
{
parameters[nameof(IncludeMetadata)] = true;
}
return new GetSecretManagerCommand(container, secretKey, parameters, null, timeout);
}
SecretValue
Secure container for secret data with proper disposal patterns.
From SecretValue.cs:16-69:
public sealed class SecretValue : IDisposable
{
private bool _disposed;
private SecureString? _secureValue;
private byte[]? _binaryValue;
private readonly bool _isBinary;
/// <summary>
/// Gets the secret identifier or key name.
/// </summary>
public string Key { get; }
/// <summary>
/// Gets the secret version identifier.
/// </summary>
public string? Version { get; }
/// <summary>
/// Gets the date and time when the secret was created.
/// </summary>
public DateTimeOffset CreatedAt { get; }
/// <summary>
/// Gets the date and time when the secret was last modified.
/// </summary>
public DateTimeOffset ModifiedAt { get; }
/// <summary>
/// Gets the date and time when the secret expires.
/// </summary>
public DateTimeOffset? ExpiresAt { get; }
/// <summary>
/// Gets a value indicating whether this secret contains binary data.
/// </summary>
public bool IsBinary => _isBinary;
/// <summary>
/// Gets a value indicating whether this secret has expired.
/// </summary>
public bool IsExpired => ExpiresAt.HasValue && DateTimeOffset.UtcNow > ExpiresAt.Value;
/// <summary>
/// Gets additional metadata associated with the secret.
/// </summary>
public IReadOnlyDictionary<string, object> Metadata { get; }
Secure access pattern from SecretValue.cs:220-233:
public TResult AccessStringValue<TResult>(Func<string, TResult> accessor)
{
var value = GetStringValue();
try
{
return accessor(value);
}
finally
{
// Note: In production, consider using more secure memory clearing techniques
// This is a simplified implementation
}
}
Available Secret Manager Implementations
| Package | Secret Type | Purpose |
|---|---|---|
FractalDataWorks.Services.SecretManagers.AzureKeyVault |
AzureKeyVault | Azure Key Vault integration |
Implementing a Custom Secret Manager Type
See the Azure Key Vault implementation for a complete example.
From ../FractalDataWorks.Services.SecretManagers.AzureKeyVault/AzureKeyVaultSecretManagerType.cs:37-57:
[ServiceTypeOption(typeof(SecretManagerTypes), "AzureKeyVault")]
public sealed class AzureKeyVaultSecretManagerType
: SecretManagerTypeBase<ISecretManager, IAzureKeyVaultSecretManagerFactory, AzureKeyVaultConfiguration>
{
public AzureKeyVaultSecretManagerType()
: base(
name: "AzureKeyVault",
sectionName: "AzureKeyVault",
displayName: "Azure Key Vault",
description: "Microsoft Azure Key Vault secret management service with support for managed identity and service principal authentication",
supportedSecretStores: ["AzureKeyVault"],
supportedSecretTypes: ["Password", "ConnectionString", "ApiKey", "Certificate", "Key"],
supportsRotation: true,
supportsVersioning: true,
supportsSoftDelete: true,
supportsAccessPolicies: true,
maxSecretSizeBytes: 25600) // Azure Key Vault limit is 25 KB
{
}
Dependencies
This package depends on:
FractalDataWorks.Collections- TypeCollection infrastructureFractalDataWorks.Services.Abstractions- Service contractsFractalDataWorks.Services.SecretManagers.Abstractions- Secret manager interfacesFractalDataWorks.Services.Abstractions- ServiceType base classesFractalDataWorks.Results- Railway-Oriented ProgrammingFractalDataWorks.Services- ServiceProvider base classMicrosoft.Extensions.DependencyInjection.Abstractions- DI abstractionsMicrosoft.Extensions.Logging.Abstractions- Logging abstractions
Related Packages
- FractalDataWorks.Services.SecretManagers.Abstractions - Interfaces and contracts
- FractalDataWorks.Services.Abstractions - Service infrastructure
- FractalDataWorks.Services.Abstractions - ServiceType patterns
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FractalDataWorks.Collections (>= 0.4.0-preview.6)
- FractalDataWorks.Configuration.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Results (>= 0.4.0-preview.6)
- FractalDataWorks.Services (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Connections.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.SecretManagers.Abstractions (>= 0.4.0-preview.6)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FractalDataWorks.Services.SecretManagers:
| Package | Downloads |
|---|---|
|
CyberdyneDevelopment.Mc3Po.Protocols
Protocol infrastructure for mc3-po - base classes, provider, and ServiceType integration |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|