using Microsoft.Extensions.Configuration; namespace QRRapidoApp.Configuration { /// /// Configuration provider that reads Docker Secrets from /run/secrets/ /// Secrets are mounted as files in Swarm mode. /// public class DockerSecretsConfigurationProvider : ConfigurationProvider { private readonly string _secretsPath; private readonly Dictionary _secretKeyMappings; public DockerSecretsConfigurationProvider(string secretsPath, Dictionary secretKeyMappings) { _secretsPath = secretsPath; _secretKeyMappings = secretKeyMappings; } public override void Load() { Data = new Dictionary(StringComparer.OrdinalIgnoreCase); if (!Directory.Exists(_secretsPath)) { return; } var secretsLoaded = 0; foreach (var mapping in _secretKeyMappings) { var secretFileName = mapping.Key; var configKey = mapping.Value; var secretFilePath = Path.Combine(_secretsPath, secretFileName); if (File.Exists(secretFilePath)) { try { var secretValue = (string?)File.ReadAllText(secretFilePath).Trim(); if (!string.IsNullOrEmpty(secretValue)) { Data[configKey] = secretValue; secretsLoaded++; } } catch (Exception) { // Silently ignore read errors - will fall back to other config sources } } } // Set indicator that secrets were loaded from Docker if (secretsLoaded > 0) { Data["App:SecretsLoaded"] = "true"; } } } public class DockerSecretsConfigurationSource : IConfigurationSource { public string SecretsPath { get; set; } = "/run/secrets"; public Dictionary SecretKeyMappings { get; set; } = new(); public IConfigurationProvider Build(IConfigurationBuilder builder) { return new DockerSecretsConfigurationProvider(SecretsPath, SecretKeyMappings); } } public static class DockerSecretsConfigurationExtensions { /// /// Adds Docker Secrets as a configuration source. /// Maps secret file names to configuration keys. /// public static IConfigurationBuilder AddDockerSecrets( this IConfigurationBuilder builder, Action? configure = null) { var source = new DockerSecretsConfigurationSource { // Default mappings for QRRapido secrets SecretKeyMappings = new Dictionary { // Stripe ["stripe_secret_key"] = "Stripe:SecretKey", ["stripe_webhook_secret"] = "Stripe:WebhookSecret", // MongoDB ["mongodb_connection_string"] = "ConnectionStrings:MongoDB", // OAuth - Google ["google_client_id"] = "Authentication:Google:ClientId", ["google_client_secret"] = "Authentication:Google:ClientSecret", // OAuth - Microsoft ["microsoft_client_id"] = "Authentication:Microsoft:ClientId", ["microsoft_client_secret"] = "Authentication:Microsoft:ClientSecret", } }; configure?.Invoke(source); builder.Add(source); return builder; } } }