Most of the Web app’s rely on secrets to perform security operation and those secrets includes api-keys, database connection string, encryption key etc. The disclosure of these secrets could lead to unauthorised access to the third party.
For the above problem, Microsoft has come up with Azure Key Vault for the application on cloud. In case, you want to use vault in on-premise, I would recommend you to check for Hashi corp vault. In this article, we’ll be looking only at Azure key vault and secret manager for development purpose.
https://www.hashicorp.com/products/vault/
In case, you are not using Azure, I would recommend you to go for free trail by using below url
Secret Manager Overview
During development, it’s not recommends to use Azure Key vault. Firstly, due to cost involved. Secondly, developer will have their own configuration settings and therefore, it’s not recommended to use separate Azure key vault for all the developers. To overcome above problems in development, we can use secret manager instead of exposing the secrets .
Configuring Secret Manager in asp.net core
Enabling Security Manager:
The secret manager tool operates on project specific configuration setting stored in your user profile. You need to use init keyword by running on project directory
dotnet user-secrets init
This will create Guid for UserSecretId in the project file.
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>daa22e2e-9bdc-4745-b0a1-00221944c9b6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.3" />
</ItemGroup>
</Project>
In Windows, secret will be stored in below file path
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
Whereas in Linux/mac,
~/.microsoft/usersecrets/<user_secrets_id>/secrets.json
Set Secrets
You can set a secrets by using set keywords
dotnet user-secrets set api-key “1234”
similiarly, we can do the same for connection string as well. ex:
"ConnectionStrings": { "DefaultConnection": "Server=tcp:XXX.database.windows.net,1433;Initial Catalog=EFCore;Persist Security Info=False;User ID=username; Password=Password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"}
We can set the secret for connection string using colon separator. Ex: ConnectionStrings:DefaultConnection
dotnet user-secrets set ConnectionStrings:DefaultConnection “Server=tcp:XXX.database.windows.net,1433;Initial Catalog=EFCore;Persist Security Info=False;User ID=username; Password=Password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;”
Display all the secrets
Display all the secrets by using list keyword.
dotnet user-secrets list
Secret Manager changes in code
There are absolutely no changes required apart from removing the api-keys & connection string from the appsettings.json file because CreateDefaultBuilder of the program class will handle the user secrets by default.
To validate the behaviour of secret manager, I have made slight modification to the controller class.
private readonly IConfiguration _configuration;
public WeatherForecastController(ILogger<WeatherForecastController> logger,IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
[HttpGet]
public IEnumerable<string> Get()
{
return new List<string>
{
_configuration["api-key"].ToString(),
_configuration.GetConnectionString("DefaultConnection")
};
}
Run the app and it should display the api-key and connection string in the browser.
Pingback: Secret manager and Azure Key vault Part 2 – Articles on latest .net technology