神刀安全网

ASP.NET Core: No more worries about checking in secrets

30 May 2016

A number of articles have been written about the new Configuration model in ASP.NET Core, but one of the things which does not seem to be highlighted quite often, is how it can protect you from accidently checking secrets (such as connection string passwords or OAuth keys) into source control.

The have been various cases in the media over the past number of years where people have ended up on the wrong side of an Amazon Web Services bill after an unscrupulous operator have managed to get a hold of their AWS keys and used it to create EC2 instances.

In ASP.NET Core this is dead-simple.

Let us first look at a sample piece of code from the Startup class generated by one of the default ASP.NET Core application templates:

public class Startup {     public Startup(IHostingEnvironment env)     {         var builder = new ConfigurationBuilder()             .SetBasePath(env.ContentRootPath)             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)             .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)             .AddEnvironmentVariables();         Configuration = builder.Build();     }          // Rest of class omitted for brevity... } 

As you can see in the configuration of the ConfigurationBuilder , by default the configuration will be read from 3 different sources.

  1. The appsettings.json file
  2. The appsettings file which correlates with the current environment, e.g. appsettings.Development.json
  3. The environment variables

Configuration settings will be read from these 3 sources in order.

Using the enviroment-specific appsettings file

One of the first ways you can avoid checking in secrets is by using the environment-specific appsettings file and excluding that file from source control.

So in the configuration specified above, if you run on your local machine and have configured the Development environment (read more about Working with Multiple Environments ), then the ASP.NET Core runtime is going to try and load settings from an optional appsettings.Development.json file.

As you can see in the code snippet, this file is specified as optional, so what you can do is to specify your secret values inside this file, e.g.

{   "twitter": {     "consumerKey": "your consumer key goes here",     "consumerSecret": "your consumer secret goes here"   } } 

This will make the configuration settings with the keys twitter:consumerKey and twitter:consumerSecret will be available inside your application.

All you need to do is exlude the file from source conrol, so if you use Git then simply add the file to your .gitignore file , so it does not get checked in.

You can even make it more explicit that the file contains secrets, by naming it secrets.json and excluding the secrets.json file from source control:

public class Startup {     public Startup(IHostingEnvironment env)     {         var builder = new ConfigurationBuilder()             .SetBasePath(env.ContentRootPath)             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)             .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)             .AddJsonFile($"secrets.json", optional: true)             .AddEnvironmentVariables();         Configuration = builder.Build();     }          // Rest of class omitted for brevity... } 

Store them as environment variables

You may have noticed the call to AddEnvironmentVariables in the code samples above. What this does is that it will load configuration values from environment variables.

So using the example of the Twitter Consumer Key and Secret above, I can simple specify environment variables twitter:consumerKey and twitter:consumerSecret with the relevant values:

ASP.NET Core: No more worries about checking in secrets

And because of the call to AddEnvironmentVariables , the configuration settings with the keys twitter:consumerKey and twitter:consumerSecret will once again be available inside my application

Use the Secret Manager tool

One more (and probably the best) way in which you can do this is to actually use the Secret Manager Tool which is available as a .NET Core tool and was built specifically for this purpose.

You can read the article above for more detail on exactly how to use this, but what it boils down to is that there is a .NET Core tool available which you can add to your application, called the Secret Manager Tool.

You can use this tool you can specify the values for any secrets you use inside your application, and it will be stored securely on your local machine without any chance of them being checked into source control.

At runtime you can use the AddUserSecrets method to load the values of the configuration variables from the secret storage:

public Startup(IHostingEnvironment env) {     var builder = new ConfigurationBuilder()         .SetBasePath(env.ContentRootPath)         .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)         .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);      if (env.IsDevelopment())     {         // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709         builder.AddUserSecrets();     }      builder.AddEnvironmentVariables();     Configuration = builder.Build(); } 

A handy side-effect for our Auth0 samples

Let’s quickly look again at the code for specifying the configuration sources inside our application:

var builder = new ConfigurationBuilder()     .SetBasePath(env.ContentRootPath)     .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)     .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)     .AddEnvironmentVariables(); Configuration = builder.Build();  

I mentioned before that the environment variables get loaded in the order in which the configuration sources are specified, but what I did not make clear is that all configuration sources can declare the configuration settings with the same key. What will happen in this case is that the values from a subsequent configuration source will override the values from a previous configuration source.

This is useful for me when developing our Auth0 samples, because we have a clever little trick where we replace configuration values with the actual values from your Auth0 instance.

Here is the contents from the configuration file of one of our samples :

{   "AppSettings": {     "SiteTitle": "Auth0 - ASP.NET 5 Web App Sample"   },   "Auth0": {     "ClientId": "{CLIENT_ID}",     "ClientSecret": "{CLIENT_SECRET}",     "Domain": "{DOMAIN}",     "RedirectUri": "http://localhost:5001/"   } } 

Do you see those values {CLIENT_ID} , {CLIENT_SECRET} and {DOMAIN} ? When you download this sample application through our documentation website, and you are signed in to your Auth0 account, we will automatically replace those with the correct values from your Auth0 instance, so you do not have to do any configuration of the application after you have downloaded it – you can just run it immediately and it is pre-configured to work with your specific Auth0 instance.

Now previously when I worked on these samples to code and test them, I had to set the values for those configuration settings to the actual values. So instead of {CLIENT_ID} , I would have to specify the actual Client ID.

I then also had to remember that everytime I checked a sample application in to GitHub that I once again replaced the actual Client ID I used while testing the sample application with the string {CLIENT_ID} , so our sample downloader worked correctly.

From time to time I forgot to do this…

With the new multiple configuration sources in ASP.NET Core, this is a thing of the past. I never have to touch the values of those configuration settings in appsettings.json again. All I do is to specify environment variables with the correct values which will then override the values in the appsettings.json file becuase of the call to AddEnvironmentVariables .

So when I use them on my computer, the environment variables I use get specified, but when a user downloads the sample they will have the correct values specified in appsettings.json and I do not have to worry about messing things up by accident.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » ASP.NET Core: No more worries about checking in secrets

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址