Esempio n. 1
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);
        }