Example #1
0
        public KeyVaultSecretProvider(IKeyVaultAuthentication authentication, IKeyVaultConfiguration vaultConfiguration, KeyVaultOptions options, ILogger <KeyVaultSecretProvider> logger)
        {
            Guard.NotNull(vaultConfiguration, nameof(vaultConfiguration), "Requires a Azure Key Vault configuration to setup the secret provider");
            Guard.NotNull(authentication, nameof(authentication), "Requires an Azure Key Vault authentication instance to authenticate with the vault");

            VaultUri = $"{vaultConfiguration.VaultUri.Scheme}://{vaultConfiguration.VaultUri.Host}";

            _authentication  = authentication;
            _options         = options;
            _isUsingAzureSdk = false;

            Logger = logger ?? NullLogger <KeyVaultSecretProvider> .Instance;
        }
Example #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="KeyVaultSecretProvider"/> class.
        /// </summary>
        /// <param name="tokenCredential">The requested authentication type for connecting to the Azure Key Vault instance</param>
        /// <param name="vaultConfiguration">Configuration related to the Azure Key Vault instance to use</param>
        /// <param name="options">The additional options to configure the provider.</param>
        /// <param name="logger">The logger to write diagnostic trace messages during the interaction with the Azure Key Vault.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="tokenCredential"/> cannot be <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="vaultConfiguration"/> cannot be <c>null</c>.</exception>
        public KeyVaultSecretProvider(TokenCredential tokenCredential, IKeyVaultConfiguration vaultConfiguration, KeyVaultOptions options, ILogger <KeyVaultSecretProvider> logger)
        {
            Guard.NotNull(vaultConfiguration, nameof(vaultConfiguration), "Requires a Azure Key Vault configuration to setup the secret provider");
            Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to authenticate with the vault");

            VaultUri = $"{vaultConfiguration.VaultUri.Scheme}://{vaultConfiguration.VaultUri.Host}";

            _secretClient    = new SecretClient(vaultConfiguration.VaultUri, tokenCredential);
            _options         = options;
            _isUsingAzureSdk = true;

            Logger = logger ?? NullLogger <KeyVaultSecretProvider> .Instance;
        }
        public void LoadEmptyKeyVaultOptions()
        {
            IConfiguration  cfg      = new ConfigurationBuilder().Build();
            KeyVaultOptions actualKv = new();

            cfg.Bind("KeyVault", actualKv);

            var expectedKv = new KeyVaultOptions
            {
                Name             = string.Empty,
                IdentityClientId = string.Empty
            };

            actualKv.Should().BeEquivalentTo(expectedKv);
        }
        public KeyVaultSecretProvider(IKeyVaultAuthentication authentication, IKeyVaultConfiguration vaultConfiguration, KeyVaultOptions options, ILogger <KeyVaultSecretProvider> logger)
        {
            Guard.NotNull(vaultConfiguration, nameof(vaultConfiguration), "Requires a Azure Key Vault configuration to setup the secret provider");
            Guard.NotNull(authentication, nameof(authentication), "Requires an Azure Key Vault authentication instance to authenticate with the vault");

            VaultUri = $"{vaultConfiguration.VaultUri.Scheme}://{vaultConfiguration.VaultUri.Host}";
            Guard.For <UriFormatException>(
                () => !VaultUriRegex.IsMatch(VaultUri),
                "Requires the Azure Key Vault host to be in the right format, see https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#objects-identifiers-and-versioning");

            _authentication  = authentication;
            _options         = options;
            _isUsingAzureSdk = false;

            Logger = logger ?? NullLogger <KeyVaultSecretProvider> .Instance;
        }
Example #5
0
        public static IConfigurationBuilder AddCostributeAzureKeyVault(this IConfigurationBuilder builder)
        {
            var rootConfig      = builder.Build();
            var keyVaultOptions = new KeyVaultOptions();

            rootConfig.GetSection(typeof(KeyVaultOptions).Name).Bind(keyVaultOptions);

            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient            = new KeyVaultClient(
                new KeyVaultClient.AuthenticationCallback(
                    azureServiceTokenProvider.KeyVaultTokenCallback));

            builder.AddAzureKeyVault(
                keyVaultOptions.VaultUri, keyVaultClient, new DefaultKeyVaultSecretManager());

            return(builder);
        }
        public void LoadKeyVaultOptions()
        {
            IConfiguration  cfg      = GetConfiguration();
            KeyVaultOptions actualKv = new();

            cfg.Bind("KeyVault", actualKv);

            var expectedKv = new KeyVaultOptions
            {
                Name             = "example-kv",
                IdentityClientId = "Lorem",
                ReloadInterval   = TimeSpan.FromSeconds((2 * 60) + 15)
            };

            expectedKv.Prefixes.AddRange(new[] { "Example1", "Example2" });

            actualKv.Should().BeEquivalentTo(expectedKv);
        }
Example #7
0
 public KeyVaultIntegration(KeyVaultOptions options)
 {
     SecretClient      = new SecretClient(vaultUri: new Uri(options.Url), credential: new DefaultAzureCredential(), options: options.SecretOptions);
     CertificateClient = new CertificateClient(vaultUri: new Uri(options.Url), credential: new DefaultAzureCredential(), options: options.CertificateOptions);
     KeyClient         = new KeyClient(vaultUri: new Uri(options.Url), credential: new DefaultAzureCredential(), options: options.KeyOptions);
 }
Example #8
0
        public static IHostBuilder Create(IConfiguration configuration, bool runAsWindowsService, ILogger logger)
        {
            var builder = new HostBuilder();

            var serverOptions = new OakproxyServerOptions();

            serverOptions.Configure(configuration.GetSection("Server"));

            var proxyOptions = ConfigurationBinder.Get <ProxyOptions>(configuration);

            if (!OptionsAreValid(serverOptions, logger, "Server") || !OptionsAreValid(proxyOptions, logger))
            {
                return(null);
            }

            var subsystemConfiguration = ConfigurationBinder.Get <HostingSubsystemConfiguration>(configuration.GetSection("Configuration"),
                                                                                                 binderOptions => binderOptions.BindNonPublicProperties = true) ?? HostingSubsystemConfiguration.Empty();

            builder
            .UseContentRoot(Program.GetExecutableDirectory())
            .ConfigureHostConfiguration(builder => builder.AddConfiguration(subsystemConfiguration.Host));

            if (runAsWindowsService)
            {
                builder.UseWindowsService();
            }

            builder
            .ConfigureAppConfiguration(builder => builder.AddConfiguration(configuration))
            .ConfigureLogging((hostBuilderContext, loggingBuilder) =>
            {
                if (subsystemConfiguration.Logging.Exists())
                {
                    loggingBuilder.AddConfiguration(subsystemConfiguration.Logging);
                }
                else
                {
                    loggingBuilder.AddFilter(null, serverOptions.LogLevelInternal);
                }

                if (runAsWindowsService)
                {
                    loggingBuilder.AddProvider(new DeferringLoggerProvider(new EventLogLoggerProvider(new EventLogSettings
                    {
                        SourceName = "OAKProxy"
                    })));
                }
                else
                {
                    loggingBuilder.AddConsole();
                }
            })
            .UseDefaultServiceProvider((context, options) =>
            {
                options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
            })
            .ConfigureServices((context, services) =>
            {
                services.AddOptions <ProxyOptions>()
                .Bind(configuration)
                .ValidateDataAnnotations();

                services.AddSingleton(Options.Create(serverOptions));

                if (!String.IsNullOrWhiteSpace(serverOptions.ApplicationInsightsKey))
                {
                    services.AddApplicationInsightsTelemetry(options =>
                    {
                        options.InstrumentationKey = serverOptions.ApplicationInsightsKey;
                        subsystemConfiguration.ApplicationInsights.Bind(options);
                    });
                    services.AddApplicationInsightsTelemetryProcessor <OakproxyTelemetryProcessor>();
                }

                services.AddTransient <IStartupFilter, HostingPipelineStartup>();

                if (serverOptions.UseForwardedHeaders || serverOptions.UseAzureApplicationGateway)
                {
                    services.Configure <ForwardedHeadersOptions>(options =>
                    {
                        options.ForwardedHeaders = ForwardedHeaders.All;
                        options.KnownNetworks.Clear();
                        options.KnownProxies.Clear();
                        subsystemConfiguration.ForwardedHeaders.Bind(options);

                        if (serverOptions.UseAzureApplicationGateway)
                        {
                            options.ForwardedHostHeaderName = "X-Original-Host";
                        }
                    });
                }

                if (serverOptions.KeyManagement != null)
                {
                    var dataProtectionBuilder = services.AddDataProtection();
                    var kmOptions             = serverOptions.KeyManagement;

                    kmOptions.LoadCertificates(configuration.GetSection(ConfigurationPath.Combine("Server", "KeyManagement")));

                    if (!String.IsNullOrEmpty(kmOptions.StoreToFilePath))
                    {
                        var directoryInfo = new DirectoryInfo(kmOptions.StoreToFilePath);
                        if (!directoryInfo.Exists)
                        {
                            throw new DirectoryNotFoundException("The specified key storage directory does not exist.");
                        }
                        dataProtectionBuilder.PersistKeysToFileSystem(directoryInfo);
                    }
                    else if (!String.IsNullOrEmpty(kmOptions.StoreToBlobContainer))
                    {
                        var blobUri = new Uri(kmOptions.StoreToBlobContainer);
                        if (String.IsNullOrEmpty(blobUri.Query))
                        {
                            var azureServiceTokenProvider = new AzureServiceTokenProvider();
                            var tokenAndFrequency         = StorageTokenRenewerAsync(azureServiceTokenProvider, CancellationToken.None)
                                                            .GetAwaiter().GetResult();

                            TokenCredential tokenCredential = new TokenCredential(tokenAndFrequency.Token,
                                                                                  StorageTokenRenewerAsync,
                                                                                  azureServiceTokenProvider,
                                                                                  tokenAndFrequency.Frequency.Value);

                            var storageCredentials = new StorageCredentials(tokenCredential);
                            var cloudBlockBlob     = new CloudBlockBlob(blobUri, storageCredentials);
                            dataProtectionBuilder.PersistKeysToAzureBlobStorage(cloudBlockBlob);
                        }
                        else
                        {
                            dataProtectionBuilder.PersistKeysToAzureBlobStorage(blobUri);
                        }
                    }

                    if (!String.IsNullOrEmpty(kmOptions.ProtectWithKeyVaultKey))
                    {
                        var keyVaultSection = configuration.GetSection(ConfigurationPath.Combine("Server", "KeyVault"));
                        var kvOptions       = new KeyVaultOptions(keyVaultSection);

                        var keyIdBuilder = new UriBuilder(kvOptions.VaultUri)
                        {
                            Path = $"/keys/${kmOptions.ProtectWithKeyVaultKey}"
                        };
                        var keyId = keyIdBuilder.Uri.ToString();

                        if (kvOptions.ClientId == null)
                        {
                            // Use Managed Identity
                            var azureServiceTokenProvider = new AzureServiceTokenProvider();
                            var authenticationCallback    = new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback);
                            dataProtectionBuilder.ProtectKeysWithAzureKeyVault(new KeyVaultClient(authenticationCallback), keyId);
                        }
                        else
                        {
                            if (kvOptions.ClientSecret != null)
                            {
                                dataProtectionBuilder.ProtectKeysWithAzureKeyVault(keyId, kvOptions.ClientId, kvOptions.ClientSecret);
                            }
                            else if (kvOptions.Certificate != null)
                            {
                                dataProtectionBuilder.ProtectKeysWithAzureKeyVault(keyId, kvOptions.ClientId, kvOptions.Certificate);
                            }
                        }
                    }
                    else if (kmOptions.ProtectWithCertificate != null)
                    {
                        dataProtectionBuilder.ProtectKeysWithCertificate(kmOptions.ProtectWithCertificate);

                        if (kmOptions.UnprotectWithCertificates != null)
                        {
                            dataProtectionBuilder.UnprotectKeysWithAnyCertificate(kmOptions.UnprotectWithCertificates);
                        }
                    }
                    else if (kmOptions.ProtectWithDpapiNg != null)
                    {
                        if (kmOptions.ProtectWithDpapiNg.UseSelfRule)
                        {
                            dataProtectionBuilder.ProtectKeysWithDpapiNG();
                        }
                        else
                        {
                            dataProtectionBuilder.ProtectKeysWithDpapiNG(kmOptions.ProtectWithDpapiNg.DescriptorRule, kmOptions.ProtectWithDpapiNg.DescriptorFlags);
                        }
                    }
                    else
                    {
                        throw new Exception("Unvalidated options would have allowed for unprotected key storage.");
                    }
                }

                services.AddHttpContextAccessor();
                services.AddHealthChecks();
                services.AddOakproxy(proxyOptions);
            })
            .ConfigureWebHost(configure =>
            {
                configure.UseUrls(serverOptions.Urls);
                configure.UseKestrel((builderContext, options) =>
                {
                    options.Configure(subsystemConfiguration.Kestrel);

                    if (serverOptions.HttpsCertificate != null)
                    {
                        options.ConfigureHttpsDefaults(configureHttps => configureHttps.ServerCertificate = serverOptions.HttpsCertificate);
                    }
                });
                configure.Configure(builder => builder.UseOakproxy());
            });

            return(builder);
        }
 public ConfigurationOptions()
 {
     Data     = new DatabaseOptions();
     KeyVault = new KeyVaultOptions();
 }
Example #10
0
        public SecretAccess(IOptions <KeyVaultOptions> keyVaultOptions)
        {
            _keyVaultOptions = keyVaultOptions.Value;

            _kvURL = $"https://{_keyVaultOptions.KeyVaultName}.vault.azure.net";
        }