Reputation: 2687
I'm trying to understand configuration sources in .NET Core 2. I have some secret configuration which in my development environment is stored in the project secrets.json
. As I don't want these secrets to be in the repository, so in production I want to load these from environment variables. My understanding was that the ConfigurationBuilder
would allow me to use configuration sources interchangeably but they're loaded differently.
My secrets.json
file looks a bit like this:
{
"MyApi" : {
"APIKEY": "12341234123412341234",
"TemplateIds": {
"MyTemplate": "abcdabcdabcdabcdabcdabcd"
}
}
}
And this loads with builder.GetSection("MyApi").AsEnumerable()
as expected as a list with the following items:
{[MyApi, ]}
{[MyApi:APIKEY, "12341234123412341234"]}
{[MyApi:TemplateIds, ]}
{[MyApi:TemplateIds:MyTemplate, "abcdabcdabcdabcdabcdabcd"]}
However when I set an environment variable called MyApi
with a value of {"APIKEY": "12341234123412341234", "TemplateIds": {"MyTemplate": "abcdabcdabcdabcdabcdabcd"}
, loading it with builder.GetSection("MyApi").AsEnumerable()
yields only one value, set to the whole JSON string.
My configuration builder looks like this:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("secrets/appsettings.secrets.json", optional: true)
.AddEnvironmentVariables();
So, should these two methods of loading configuration give the same results, and if so, does anyone know why they might be different in this case?
Upvotes: 2
Views: 1511
Reputation: 239430
That's because the environment variables provider doesn't process JSON. If you want to specify those settings via environment variables, you need to set each as its own environment variable. For example, for APIKEY
, you'd need an enviroment variable named MyApi.APIKEY
with the value of 12341234123412341234
. Rinse and repeat with the rest of the settings. You need to represent the hierarchy present in your JSON by joining each level together with a .
or :
.
That said, rather than creating something like secrets.json
, you should be using user secrets. It works in much the same way, and it's also JSON, but it keeps it completely abstracted from your project so there's no file you have to ignore and no file that might eventually end up committed anyways.
Also, for what it's worth, all your settings should be in appsettings.json
or one of the environment-specific versions. For "secrets", simply put in placeholders or empty values. This can then be overridden via more specific configuration like user secrets, environment variables, Azure KeyVault, etc. That way, all the config your app needs is documented in something that is checked into source control, but the actual secret values are not. Otherwise, it can be extremely hard for other developers that might need to work with the app to know what settings they need to provide. For example:
{
"MyApi" : {
"APIKEY": "***SET IN USER SECRETS OR ENVIRONMENT VARIABLE***",
"TemplateIds": {
"MyTemplate": "abcdabcdabcdabcdabcdabcd"
}
}
}
Upvotes: 4