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
AddAccessTokenManagementinsideConfigure(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
SsoServiceInfocan be located.Ideally Steeltoe would bind these credentials to
SsoServiceInfoautomatically, 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
ServiceInfoFactorythat can bind your credhub service instance toSsoServiceInfo:Next add the
ServiceInfoFactoryAssemblyattribute toAssemblyInfo.csso 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:servicesunlessvcap:applicationhas been set, so you might want use this configuration format for non-CloudFoundry environments: