private static RefreshableConfiguration GetConfiguration() { const string prefix = "APPSETTING_"; var jsonFile = Path.Combine(HostingEnvironment.MapPath("~/"), @"Settings\local.json"); // Load the configuration without injection. This allows us to read KeyVault configuration. var uninjectedBuilder = new ConfigurationBuilder() .AddJsonFile(jsonFile) // The JSON file is useful for local development. .AddEnvironmentVariables(prefix); // Environment variables take precedence. var uninjectedConfiguration = uninjectedBuilder.Build(); // Initialize KeyVault integration. var secretReaderFactory = new ConfigurationRootSecretReaderFactory(uninjectedConfiguration); var refreshSecretReaderSettings = new RefreshableSecretReaderSettings(); var refreshingSecretReaderFactory = new RefreshableSecretReaderFactory(secretReaderFactory, refreshSecretReaderSettings); var secretReader = refreshingSecretReaderFactory.CreateSecretReader(); var secretInjector = refreshingSecretReaderFactory.CreateSecretInjector(secretReader); // Attempt to inject secrets into all of the configuration strings. foreach (var pair in uninjectedConfiguration.AsEnumerable()) { if (!string.IsNullOrWhiteSpace(pair.Value)) { // We can synchronously wait here because we are outside of the request context. It's not great // but we need to fetch the initial secrets for the cache before activating any controllers or // asking DI for configuration. secretInjector.InjectAsync(pair.Value).Wait(); } } // Reload the configuration with secret injection enabled. This is was is used by the application. var injectedBuilder = new ConfigurationBuilder() .AddInjectedJsonFile(jsonFile, secretInjector) .AddInjectedEnvironmentVariables(prefix, secretInjector); var injectedConfiguration = injectedBuilder.Build(); // Now disable all secrets loads from a non-refresh path. Refresh will be called periodically from a // background thread. Foreground (request) threads MUST use the cache otherwise there will be a deadlock. refreshSecretReaderSettings.BlockUncachedReads = true; return(new RefreshableConfiguration { SecretReaderFactory = refreshingSecretReaderFactory, Root = injectedConfiguration, }); }
private static RefreshableConfiguration GetSecretInjectedConfiguration(IConfigurationRoot uninjectedConfiguration) { // Initialize KeyVault integration. var secretReaderFactory = new ConfigurationRootSecretReaderFactory(uninjectedConfiguration); var refreshSecretReaderSettings = new RefreshableSecretReaderSettings(); var refreshingSecretReaderFactory = new RefreshableSecretReaderFactory(secretReaderFactory, refreshSecretReaderSettings); var secretReader = refreshingSecretReaderFactory.CreateSecretReader(); var secretInjector = refreshingSecretReaderFactory.CreateSecretInjector(secretReader); // Attempt to inject secrets into all of the configuration strings. foreach (var pair in uninjectedConfiguration.AsEnumerable()) { if (!string.IsNullOrWhiteSpace(pair.Value)) { // We can synchronously wait here because we are outside of the request context. It's not great // but we need to fetch the initial secrets for the cache before activating any controllers or // asking DI for configuration. secretInjector.InjectAsync(pair.Value).Wait(); } } // Reload the configuration with secret injection enabled. This is used by the application. var injectedBuilder = new ConfigurationBuilder() .AddInjectedJsonFile("appsettings.json", secretInjector) .AddInjectedJsonFile("appsettings.Development.json", secretInjector) .AddInjectedEnvironmentVariables(EnvironmentVariablePrefix, secretInjector); var injectedConfiguration = injectedBuilder.Build(); // Now disable all secrets loads from a non-refresh path. Refresh will be called periodically from a // background thread. Foreground (request) threads MUST use the cache otherwise there will be a deadlock. refreshSecretReaderSettings.BlockUncachedReads = true; return(new RefreshableConfiguration { SecretReaderFactory = refreshingSecretReaderFactory, Root = injectedConfiguration, }); }
public Facts() { UnderlyingFactory = new Mock <ISecretReaderFactory>(); Settings = new RefreshableSecretReaderSettings(); SecretName = "secret"; UnderlyingReader = new Mock <ISecretReader>(); SecretInjector = new Mock <ISecretInjector>(); Secret = new Mock <ISecret>(); UnderlyingFactory .Setup(x => x.CreateSecretReader()) .Returns(() => UnderlyingReader.Object); UnderlyingFactory .Setup(x => x.CreateSecretInjector(It.IsAny <ISecretReader>())) .Returns(() => SecretInjector.Object); UnderlyingReader .Setup(x => x.GetSecretObjectAsync(It.IsAny <string>())) .ReturnsAsync(() => Secret.Object); Target = new RefreshableSecretReaderFactory( UnderlyingFactory.Object, Settings); }