Having come over to .Net from javascript land I found myself confused when I needed to store sensitive information for
the first time. I couldn't use a .env
file and proccess.env.superSecretThing
anymore. No worries though because there
are tons of ways to store sensitive data using .Net!
What is secret manager?
From Microsoft:
The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. In this context, a piece of sensitive data is an app secret. App secrets are stored in a separate location from the project tree. The app secrets are associated with a specific project or shared across several projects. The app secrets aren't checked into source control.
Keep in mind that just because the secrets are stored outside of source control that doesn't mean it's secure. The secrets still get stored locally on your computer.
MacOS/Linux Directory
~/.microsoft/usersecrets/<user_secrets_id>/secrets.json
Windows Directory
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
How do I use it?
pro-tip: check out the resources for the guide from Microsoft which is quite a bit more complicated than mine, but also goes more in depth :)
Initializing the secret manager
Navigate to the root of your .Net project and run this command
dotnet user-secrets init
This will initialize the json file used to store your secrets.
Setting a secret
You can then set a new secret using the below command
dotnet user-secrets set "ServiceApiKey" "12345"
Accessing your secrets
When I was trying access my secrets using ASP.NET I was unable to access them using the IConfiguration class; However, I'm pretty certain that I just wasn't doing it correctly, or it's better suited for a different type .Net project type. Regardless, the way that I accessed it was fairly simple:
namespace secretManagerTutorial;
public class Secrets
{
public static string FetchSecret()
{
// Setup the config object
var config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
// Access the ServiceApiKey secret
var clientId = config["ServiceApiKey"];
// clientId could be null since we aren't sure what's in the secret manager. Make sure to check :)
return clientId ?? "secret not found :(";
}
}
I was able to do this within any C# file to quickly get access to all of my secrets. As mentioned earlier though this is only good for local development or proof of concepts. I highly recommend using Azure Key Vault 🔑 instead.
Are there any alternatives?
Default Azure Credential
If you're only trying to authenticate with something like Azure Key Vault then simply logging into azure (az login
)
will do the trick. I've included a link to how this works in the resources.
Key Vault
My personal preference for managing secrets is Azure Key Vault, but there are plenty of other options. Using the default azure credential mentioned above you can store and then access all of your environment variables through the azure key vault. The user interface is easy to use grabbing values from the key vault is quite simple as well. I've linked a great guide from Microsoft in the resources :)
appsettings.json Environment Variables
🚨 This is a quick and dirty alternative to the above that I recommend against 🚨
It's easier to set up than the others, but you run the risk of pushing your sensitive data to your version control system 😱
Given the example appsettings.json
{
"Position": {
"Title": "Editor",
"Name": "Joe Smith"
},
"MyKey": "My appsettings.json Value",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
you can access things like the position "object" which can hold variables through the IConfiguration class. Here's an example:
public class TestModel : PageModel
{
// requires using Microsoft.Extensions.Configuration;
private readonly IConfiguration Configuration;
public TestModel(IConfiguration configuration)
{
Configuration = configuration;
}
public ContentResult OnGet()
{
var myKeyValue = Configuration["MyKey"];
var title = Configuration["Position:Title"];
var name = Configuration["Position:Name"];
var defaultLogLevel = Configuration["Logging:LogLevel:Default"];
return Content($"MyKey value: {myKeyValue} \n" +
$"Title: {title} \n" +
$"Name: {name} \n" +
$"Default Log Level: {defaultLogLevel}");
}
}
There's a great Microsoft article about this right below the sentence in the resources.
Conclusion
Azure secret manager is great for quickly making a proof of concept with .Net, but falls short as soon as you need to production. It's great to know how to use this and the other tools mentioned throughout this blog post. You can find source code showcasing how I implemented the secret manager in the resources section below :)
Thank you for taking the time to read my blog post! 🎉
Resources
- What is the secret manager and how to use it
- Default Azure Credential
- How to use the Azure Key Vault in .Net
- appsettings.json / configuration environment variables
- Source code for this tutorial
Attribution
Photo by Jan Antonin Kolar on Unsplash