예제 #1
0
        /// <summary>
        /// Make a CredHubClient available to DI
        /// </summary>
        /// <remarks>Uses UAA user/password authentication if configured, otherwise mTLS</remarks>
        /// <param name="services">Service collection</param>
        /// <param name="config">App configuration</param>
        /// <param name="loggerFactory">Logger factory</param>
        /// <returns>Service collection with CredHubClient added in</returns>
        public static IServiceCollection AddCredHubClient(this IServiceCollection services, IConfiguration config, ILoggerFactory loggerFactory = null)
        {
            ILogger startupLogger = null;
            ILogger credhubLogger = null;

            if (loggerFactory != null)
            {
                startupLogger = loggerFactory.CreateLogger("Steeltoe.Security.DataProtection.CredHubCore");
                credhubLogger = loggerFactory.CreateLogger <CredHubClient>();
            }

            var credHubOptions = config.GetSection("CredHubClient").Get <CredHubOptions>();

            credHubOptions.Validate();

            CredHubClient credHubClient;

            try
            {
                startupLogger?.LogTrace("Using UAA auth for CredHub client with client id {ClientId}", credHubOptions.ClientId);
                credHubClient = CredHubClient.CreateUAAClientAsync(credHubOptions, credhubLogger).GetAwaiter().GetResult();

                services.AddSingleton <ICredHubClient>(credHubClient);
            }
            catch (Exception e)
            {
                startupLogger?.LogCritical(e, "Failed to initialize CredHub client for ServiceCollection");
            }

            return(services);
        }
예제 #2
0
        /// <summary>
        /// Reach out to a CredHub server to interpolate credentials found in VCAP_SERVICES
        /// </summary>
        /// <param name="webHostBuilder">Your app's host builder</param>
        /// <param name="loggerFactory">To enable logging in the credhub client, pass in a loggerfactory</param>
        /// <returns>Your application's host builder with credentials interpolated</returns>
        public static IWebHostBuilder UseCredHubInterpolation(this IWebHostBuilder webHostBuilder, ILoggerFactory loggerFactory = null)
        {
            ILogger startupLogger = null;
            ILogger credhubLogger = null;

            if (loggerFactory != null)
            {
                startupLogger = loggerFactory.CreateLogger("Steeltoe.Security.DataProtection.CredHubCore");
                credhubLogger = loggerFactory.CreateLogger <CredHubClient>();
            }

            var vcapServices = Environment.GetEnvironmentVariable("VCAP_SERVICES");

            // don't bother interpolating if there aren't any credhub references
            if (vcapServices != null && vcapServices.Contains("credhub-ref"))
            {
                webHostBuilder.ConfigureAppConfiguration((context, config) =>
                {
                    var builtConfig = config.Build();
                    CredHubClient credHubClient;

                    var credHubOptions = builtConfig.GetSection("CredHubClient").Get <CredHubOptions>();
                    credHubOptions.Validate();
                    try
                    {
                        startupLogger?.LogTrace("Using UAA auth for CredHub client with client id {ClientId}", credHubOptions.ClientId);
                        credHubClient = CredHubClient.CreateUAAClientAsync(credHubOptions, credhubLogger).GetAwaiter().GetResult();
                    }
                    catch (Exception e)
                    {
                        startupLogger?.LogCritical(e, "Failed to initialize CredHub client");

                        // return early to prevent call we know will fail
                        return;
                    }

                    try
                    {
                        // send the interpolate request to CredHub
                        string interpolated = credHubClient.InterpolateServiceDataAsync(vcapServices).GetAwaiter().GetResult();

                        // update the environment variable for this process
                        Environment.SetEnvironmentVariable("VCAP_SERVICES", interpolated);
                    }
                    catch (Exception e)
                    {
                        startupLogger?.LogCritical(e, "Failed to interpolate service data with CredHub");
                    }
                });
            }
            else
            {
                startupLogger?.LogInformation("No CredHub references found in VCAP_SERVICES");
            }

            return(webHostBuilder);
        }
예제 #3
0
 /// <summary>
 /// Initialize a CredHub Client with user credentials for the appropriate UAA server
 /// </summary>
 /// <param name="credHubOptions">CredHub client configuration values</param>
 /// <param name="logger">Pass in a logger if you want logs</param>
 /// <param name="httpClient">Primarily for tests, optionally provide your own http client</param>
 /// <returns>An initialized CredHub client (using UAA OAuth)</returns>
 public static Task<CredHubClient> CreateUAAClientAsync(CredHubOptions credHubOptions, ILogger logger = null, HttpClient httpClient = null)
 {
     _logger = logger;
     _baseCredHubUrl = credHubOptions.CredHubUrl;
     var client = new CredHubClient(credHubOptions.ValidateCertificates);
     _httpClientHandler = new HttpClientHandler();
     _httpClient = httpClient ?? client.InitializeHttpClient(_httpClientHandler);
     return client.InitializeAsync(credHubOptions);
 }
예제 #4
0
        /// <summary>
        /// Expects CF_INSTANCE_CERT and CF_INSTANCE_KEY to be set in the environment (automatically set by DIEGO in cloud foundry)
        /// </summary>
        /// <param name="credHubOptions">CredHub client configuration values</param>
        /// <param name="logger">Pass in a logger if you want logs</param>
        /// <param name="httpClient">Optionally override the http client used to talk to credhub - added for tests only</param>
        /// <returns>An initialized CredHub client (using mTLS)</returns>
        public static async Task <CredHubClient> CreateMTLSClientAsync(CredHubOptions credHubOptions, ILogger logger = null, HttpClient httpClient = null)
        {
            _logger         = logger;
            _baseCredHubUrl = credHubOptions.CredHubUrl;

            var cfInstanceCert = Environment.GetEnvironmentVariable("CF_INSTANCE_CERT") ?? string.Empty;
            var cfInstanceKey  = Environment.GetEnvironmentVariable("CF_INSTANCE_KEY");

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && cfInstanceCert.StartsWith("/"))
            {
                _logger?.LogTrace("Detected Windows OS and root-relative paths for application credentials: converting to app-relative paths");
                cfInstanceCert = ".." + cfInstanceCert;
                cfInstanceKey  = ".." + cfInstanceKey;
            }

            if (string.IsNullOrEmpty(cfInstanceCert) || string.IsNullOrEmpty(cfInstanceKey))
            {
                _logger?.LogCritical("Cloud Foundry application credentials not found in the environment");
                throw new ArgumentException("Application Credentials not found (Missing ENV variable for Instance Cert and/or Key)");
            }

            _logger?.LogTrace("Application certificate: " + cfInstanceCert);
            _logger?.LogTrace("Application key: " + cfInstanceKey);
            if (File.Exists(cfInstanceCert) && File.Exists(cfInstanceKey))
            {
                var client = new CredHubClient(credHubOptions.ValidateCertificates);
                _httpClientHandler = new HttpClientHandler()
                {
                    ClientCertificateOptions = ClientCertificateOption.Manual
                };
                var certBytes      = File.ReadAllBytes(cfInstanceCert);
                var keyBytes       = File.ReadAllBytes(cfInstanceKey);
                var appCredentials = CertificateHelpers.GetX509FromBytes(certBytes, keyBytes);
                if (!appCredentials.HasPrivateKey)
                {
                    throw new Exception("Private key is missing, mTLS won't work");
                }

                _httpClientHandler.ClientCertificates.Add(appCredentials);
                _httpClient = httpClient ?? client.InitializeHttpClient(_httpClientHandler);

                return(await client.InitializeAsync());
            }
            else
            {
                throw new Exception($"Application credentials not found (Failed to load Instance Cert [{cfInstanceCert}] and/or Key [{cfInstanceKey}])");
            }
        }