Short Problem Statement:
How to get value from Cloud Foundry CredHub to be used inside ConfigureServices(IServiceCollection services)
?
Existing Condition:
Let's say that I have a class called SystemConfig
for holding configuration values. I use a combination of json file and dotnet secrets in 'Development' stage for storing those values, and they can be retrieved via
services.Configure<SystemConfig>(Configuration.GetSection("GLOBAL"));
In 'SIT' stage, I use Pivotal Cloud Foundry to host the application and a combination of ConfigServer - CredHub for storing configuration values. Values from CredHub can be retrieved inside Configure(IApplicationBuilder app)
via
var credhub = app.ApplicationServices.GetService<IOptions<CloudFoundryServicesOptions>>().Value.Services["credhub"].First(x => x.Name.Equals("credhub-instance"));
var sysConfig = app.ApplicationServices.GetService<IOptions<SystemConfig>>().Value;
sysConfig.SAMPLE_A = credhub.Credentials[nameof(sysConfig.SAMPLE_A)].Value;
The problem arises when I need to configure Access Token Management from IdentityModel.AspNetCore
inside ConfigureServices
:
services.AddAccessTokenManagement(x =>
{
x.Client.Clients.Add("key_sample", new IdentityModel.Client.ClientCredentialsTokenRequest()
{
Address = "sysConfig.SAMPLE_A",
ClientId = "taken from sysConfig as well",
ClientSecret = "taken from sysConfig as well"
});
});
The method AddAccessTokenManagement
can only be used inside ConfigureService(IServiceCollection services)
but at the same time I don't have values from CredHub yet because they are retrieved inside Configure(IApplicationBuilder app)
.
Usage of services.BuildServiceProvider()
is not recommended as well since it will create additional copy of Singleton services that might lead to unexpected bugs.
So the question boils down to :
- Can we retrieve CredHub value inside
ConfigureService(IServiceCollection services)
? - If it is not possible, then can we somehow set
AddAccessTokenManagement
insideConfigure(IApplicationBuilder app)
?
I can't speak to the intricacies of IdentityModel here, and at a glance I don't see anything that makes this easy from that side, but I have a solution that should work that uses Steeltoe Connectors by customizing the way
SsoServiceInfo
can be located.Ideally Steeltoe would bind these credentials to
SsoServiceInfo
automatically, but there isn't currently anything built in that makes that connection. This code will work to retrieve the service info by the time we're done here:In order to enable the above code, we'll need to add a custom
ServiceInfoFactory
that can bind your credhub service instance toSsoServiceInfo
:Next add the
ServiceInfoFactoryAssembly
attribute toAssemblyInfo.cs
so Steeltoe can find your new factory:Also, Connectors build on the CloudFoundry Configuration Provider, so be sure you've added it to your host builder or configuration builder with something like this:
Finally, please note that as of v3.0, Steeltoe won't recognize
vcap:services
unlessvcap:application
has been set, so you might want use this configuration format for non-CloudFoundry environments: