All articles

C# Interview Guide: Secrets Management — User Secrets, Azure Key Vault, Managed Identity

2 min read
#0
0 reads
0 reading now
0 shares

Q23 — Secrets Management — User Secrets, Azure Key Vault, Managed Identity

Level: Mid-Level | Topic: Security

The Problem

Secrets committed to source control are a leading cause of breaches. The correct approach: use different secret stores per environment, with zero credentials needed in production code via Managed Identity.

Environment Strategy

  • Development: dotnet user-secrets — stored outside the project directory in ~/.microsoft/usersecrets/, never committed to git.
  • CI/CD: Environment variables or GitHub Actions Secrets / Azure DevOps Variable Groups — injected at build time, not stored in code.
  • Staging/Production: Azure Key Vault (or AWS Secrets Manager / HashiCorp Vault) accessed via Managed Identity — no client secrets needed at all.

Code Example

# Development — dotnet user-secrets
dotnet user-secrets init --project src/Api
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=...;..."
dotnet user-secrets set "Jwt:Key" "super-secret-dev-key-32chars!!"
dotnet user-secrets list

// Production — Azure Key Vault via Managed Identity (zero credentials in code)
// Packages: Azure.Extensions.AspNetCore.Configuration.Secrets, Azure.Identity

public static IHostBuilder AddSecretsManagement(this IHostBuilder host)
{
    host.ConfigureAppConfiguration((ctx, config) =>
    {
        if (ctx.HostingEnvironment.IsDevelopment())
        {
            config.AddUserSecrets<Program>();  // dev only
            return;
        }

        // Production: Key Vault via Managed Identity — NO credentials in code!
        var keyVaultUri = new Uri(ctx.Configuration["KeyVault:Uri"]
            ?? throw new InvalidOperationException("KeyVault:Uri not configured"));

        config.AddAzureKeyVault(
            keyVaultUri,
            new DefaultAzureCredential(),           // uses Managed Identity in Azure
            new AzureKeyVaultConfigurationOptions
            {
                ReloadInterval = TimeSpan.FromMinutes(5)  // auto-reload rotated secrets
            });
    });
    return host;
}

// Strongly-typed access with startup validation
builder.Services.AddOptions<DatabaseOptions>()
    .BindConfiguration(DatabaseOptions.SectionName)
    .ValidateDataAnnotations()
    .ValidateOnStart();  // fail fast on missing secrets at startup

// Secret rotation — IOptionsMonitor picks up changes without restart
public class RotatingSecretService
{
    private readonly IOptionsMonitor<DatabaseOptions> _optionsMonitor;

    public RotatingSecretService(IOptionsMonitor<DatabaseOptions> monitor)
    {
        _optionsMonitor = monitor;
        _optionsMonitor.OnChange(opts =>
            Console.WriteLine("Connection string rotated — reconnecting pool"));
    }

    public string CurrentConnectionString
        => _optionsMonitor.CurrentValue.DefaultConnection;
}

Senior Insight

Managed Identity is the gold standard for production — it eliminates entire categories of secrets (no client IDs, no client secrets, no rotation concerns for the identity itself). Use ValidateOnStart() with ValidateDataAnnotations() so misconfigured secrets cause a startup failure with a clear error rather than a runtime exception in production. Set ReloadInterval on Key Vault configuration so rotated secrets are picked up without a restart.

ShareLinkedInX

Comments

Share your thoughts without signing in.