On the blog post “How to Configure .Net Core Environments With Practical Examples”, we shared the .NET Core Environment Configuration with the appsettings.json file.
As you can see, the appsettings.json file helps us to store the configuration, the setting, etc. However, there is a big concern that all information on this file can be accessed by anyone who has the source code or the server that hosted the app. For this reason, it’s not a good place to store sensitive data.
But what is sensitive data? Sensitive data is anything that can be potentially exploited by a third party. For example, API keys, connection strings, tokens, username, emails, passwords, password hashes, potentially some URLs, etc. In this article, I would like to share with you how to secure sensitive data in local and production environments.
How to secure sensitive data in the development environment (Locally)
In the development environment, sensitive data should not be stored in configuration files, much less in source code itself. But it should be easy to be updated.
You can choose either to store your configuration in the environment variables or as a user secret by using the Secret Manager. Neither of these options is good enough for production since they store your data as plain texts instead of encrypting the data. However, you can use them to avoid conflicts while working with other developers in a project. By doing this, you don’t have to worry if secrets and environment variables are committed by mistakes.
According to Wikipedia, an environment variable is a dynamic-named value that can affect the way running processes will behave on a computer.
For Windows in CMD: you can use the “set” command to set an environment variable with the syntax like this:
|set [variable name]=[value]|
You can check the full options for set command.
set ConnectionStrings_ProjectConnectionString=server=\\DEV-SERVER; database=DatabaseName; User Id=myaccount; Password=mypassword;
And then you can use “set” without any arguments to list all environment variables.
Example: The same command with the above CMD is:
|[System.Environment]::SetEnvironmentVariable('ConnectionStrings_ProjectConnectionString','server=\\DEV-SERVER; database=DatabaseName; User Id=myaccount; Password=mypassword;',[System.EnvironmentVariableTarget]::User)|
You can check your variable with:
If you need to read the environment variable programmatically, please refer to “How to Configure .Net Core Environments With Practical Examples”. It also includes the tutorial to manage environment variables with the windows GUI.
.NET Core provides a secrets manager tool to store sensitive data during the development. This tool allows you to store your sensitive data locally on your machine, outside the project tree.
To start using secrets, you need to enable them. Go to the project directory and enter the command:
|dotnet user-secrets init|
As the result, the command creates an entry in the .csproj file:
Now to create or modify a secret, you can use the dotnet user-secrets set command as follows:
|dotnet user-secrets set "ConnectionStrings_ProjectConnectionString" "server=\\DEV-SERVER; database=DatabaseName; User Id=myaccount; Password=mypassword;"|
And then use the below “list” command to check if you’ve successfully added it:
|dotnet user-secrets list|
Here is the result:
To access the user secret in .NET Core project, you will need to add some additional codes for ConfigurationBuilder as below:
To remove a secret you can use “dotnet user-secrets remove [secret key]”, and use “dotnet user-secrets clear” to remove all.
But if you are using Visual Studio you can easily manage the user secret by GUI. Just right click on the project and choose “Manage User Secrets”.
The secrets.json file will be opened with all your secrets settings. Now, you can edit and save it just like the “appsettings.json” file.
This secrets.json file is not super secure, and the keys are not encrypted. However, it provides an easy way to avoid storing secrets in your project config files and having to remember to add them to the source control ignore list.
Using the Azure Key Vault to secure sensitive data in the production environment
Azure Key Vault is a cloud service for securely storing and accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, or cryptographic keys. You can change the secret directly from the Azure portal and no need to re-deploy your application.
Setting up Azure key vault
To setup key vault on the Azure portal, you need to follow the following steps:
1. From the Azure portal menu or the Home page, select Create a resource
2. In the search box, enter Key Vault
3. From the results list, choose Key Vault
4. On the Key Vault section, choose to Create
5. On the Create key vault section, provide the following information
- Subscription: choose a subscription
- Resource group: choose to create new and enter a resource group name
- Key vault name: a unique name is required
- Region: choose your region
- Pricing tier: check the pricing for azure key vault here
Note: Leave the other options to their defaults.
6. Click on “Review + create” to finish your setting
Now, let’s add your secrets. You can refer to this Azure Quickstart for the details of how to create an Azure key vault and add a secret with the Azure portal.
Connecting .NET Core app with Azure key vault
To connect your .NET Core app with Azure key vault, you will need to do some further steps:
- First, you need to install some NuGet packages as below:
- Next, you need to add some configuration on the Program.cs file.
The “https://contoso-vault2.vault.azure.net/” is the “DNS Name” on your Azure key vault overview page.
If your application is hosted on Azure. You can easily manage the access to Azure key vault on the Azure portal under “Access policies”.
If you don’t use Azure you can follow this Microsoft document to config the IP firewall or certificate to connect the Azure key vault from outside of the Azure network.
Once the app is connected with the Azure key vault, you can update the Azure Key Vault without updating and redeploying the application.
However, you need to restart the app to refresh the Key Vault cache since the application caches the secret from the key vault on the application startup. Though, it is not a good idea.
Fortunately, we can specify a ReloadInterval to reload the secrets from the Key Vault whenever the Reload Interval duration is over. Just update the config for the above Azure key vault like this:
As you can see, there are several options for securing sensitive configuration data, each with different levels of security and ease of use. No matter which option you ultimately select, follow these basic guidelines:
- never commit secrets or sensitive data to a code repository, even a private repository
- do not store secrets or sensitive data in source code
- use an encryption mechanism for your data if you can
- Rick Anderson, Kirk Larkin, Daniel Roth, and Scott Addie, Safe storage of app secrets in development in ASP.NET Core, https://docs.microsoft.com, 2020
- Environment variable, https://en.wikipedia.org, 2020
- set (environment variable), https://docs.microsoft.com, 2017
- Quickstart: Set and retrieve a secret from Azure Key Vault using the Azure portal, https://docs.microsoft.com, 2019
- Authenticate to Azure Key Vault, https://docs.microsoft.com, 2020
About the author
|Hi, my name is Tan! I am currently working as a Software Engineer at Enlab Software and I mostly focus on Software Architectures, Development, and Software Re-factoring.
I love coding and learning new technologies so I'm excited to share my knowledge with you!