Overview
NuGet.Services.Configuration is a shared infrastructure library that bridges the standard Microsoft.Extensions.Configuration pipeline with Azure Key Vault secret injection. It provides custom IConfigurationSource and IConfigurationProvider wrappers that transparently resolve Key Vault secret references embedded inside configuration values — no application code needs to know whether a value came from a JSON file, an environment variable, or Key Vault.
The library also ships an older, attribute-driven configuration model built around its own IConfigurationProvider and IConfigurationFactory abstractions. This model lets configuration POCO classes declare their Key Vault key names and prefixes through [ConfigurationKey] and [ConfigurationKeyPrefix] attributes and uses ConfigurationFactory to reflectively populate them at startup. This older pattern predates the Microsoft.Extensions.Configuration binder integration and coexists with the newer SecretInjectedConfiguration wrappers.
Supporting both approaches, the library also provides ConfigurationRootSecretReaderFactory, which reads Key Vault connection details (KeyVault_VaultName, KeyVault_UseManagedIdentity, etc.) from the configuration root itself and produces the ISecretReader / ISecretInjector used by everything else. A NonCachingOptionsSnapshot<T> implementation ensures that when KeyVaultInjectingConfigurationProvider is in use, options objects are not cached across requests, allowing Key Vault secret rotation to take effect without a service restart.
Role in System
Key Vault Injection at Read Time
KeyVaultInjectingConfigurationProvider wraps any existing IConfigurationProvider and calls ISecretInjector.InjectAsync on every TryGet call. A hardcoded exclusion list prevents injection on known connection-string keys that must be passed as-is.Attribute-Driven POCO Binding
ConfigurationFactory uses reflection and TypeDescriptor to populate Configuration subclass properties. [ConfigurationKey] overrides the key name; [ConfigurationKeyPrefix] adds a prefix at the class or property level; [Required] and [DefaultValue] control error vs. fallback behavior.Cached Secret Injection Wrapper
SecretInjectedConfiguration wraps any IConfiguration after the builder stage. It uses ICachingSecretInjector.TryInjectCached first, falling back to a live Key Vault call only on a cache miss, reducing latency and request volume.Managed Identity and Certificate Auth
ConfigurationRootSecretReaderFactory supports two Key Vault auth modes: managed identity (with an optional client ID) and certificate-based auth (thumbprint, store name, store location). It rejects configurations that supply both simultaneously.Key Files and Classes
Dependencies
NuGet Package References
Internal Project References
Notable Patterns and Implementation Details
Hardcoded injection exclusions.
KeyVaultInjectingConfigurationProvider skips secret injection for four specific keys: GalleryDb:ConnectionString, ValidationDb:ConnectionString, SupportRequestDb:ConnectionString, and StatisticsDb:ConnectionString. These are expected to contain raw ADO.NET connection strings that must not be processed as Key Vault references.Two distinct secret injection lifecycles coexist.
KeyVaultInjectingConfigurationProvider (via ConfigurationBuilderExtensions) injects on every TryGet call during the provider pipeline. SecretInjectedConfiguration (via ConfigurationUtility.ConfigureInjected) injects at options-binding time using a caching injector. SecretConfigurationReader injects eagerly at construction and on Reload. Services may use any of these; newer code generally prefers the SecretInjectedConfiguration path.NonCachingOptionsSnapshot<T> must be registered explicitly. The default IOptionsSnapshot<T> caches the bound options object for the lifetime of the current scope (request). When Key Vault secret rotation is required, the consuming service must replace the default registration with NonCachingOptionsSnapshot<T> using services.Add(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(NonCachingOptionsSnapshot<>))) before services.AddOptions().