How to manage secrets in .NET locally and on GitHub? — Maytham Fahmi

A lot of software development requires secrets to interact with other systems, database, api keys etc.
It is ultimate important to secure these secrets, in a way that you are less concern who can access or se these secrets.
IMO, a best practice is to have different secrets for each environments. For example for Local , Test, UAT and production environment. But there could be situations that you have 2 keys, one for non-production and one for production, or even only 1 key.
In this article I will show you how to handle .NET project secret both locally and on GitHub.
Step 1: Create a new .NET project
We can use Visual Studio 2019/2022 or use command lines to create a new project.
md MySecretsApp
cd MySecretsApp
dotnet new console
Step 2: Initialize users secrets
With in project folder, we will initialize secrets as json outside our Visual Studio project, by running following command:
dotnet user-secrets init
You will see a successful message that has UserSecretsId
and Guid Id
reference:
Set UserSecretsId to 'b6b695f2-7611-4ed2-8ea9-a8a716afa697' for MSBuild project '..\MySecretsApp\MySecretsApp.csproj'.
This command will adds UserSecretsId
XML tag with Guid Id reference to the project file MySecretsApp.csproj
.
<PropertyGroup>
...
<UserSecretsId>b6b695f2-7611-4ed2-8ea9-a8a716afa697</UserSecretsId>
</PropertyGroup>
Step 3: Now lets add secret
Now lets run another command that adds secret, in our example we have a fictive apikey.
dotnet user-secrets set apikey 4f15a66c-2e17-408d-b6f6-db9dec3d8382
This will will create a plain text key and value Secret.json
file under %AppData%\Microsoft\UserSecrets
with folder name same Guid Id
reference.
%AppData%\Microsoft\UserSecrets\b6b695f2-7611-4ed2-8ea9-a8a716afa697\secret.json
Secret.json
will contain apikey like:
{ "apikey": "4f15a66c-2e17-408d-b6f6-db9dec3d8382" }
This way the Secret.json
will not be part of the project repository. That said, if we follow best practice as we mentioned previously. This test api key is for instance for local environment, it is suggested that you have another api key for test, UAT and production as mentioned previously.
Step 4: Lets consume the secret in our code locally.
Before we start, we need to add Microsoft.Extensions.Configuration.UserSecrets
NuGet to our project.
Now in our code, we add following chunk:
using Microsoft.Extensions.Configuration;var config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
string apiKey = config["apikey"];Console.WriteLine(apiKey);
apiKey will contain our given api key secret; 4f15a66c-2e17-408d-b6f6-db9dec3d8382
as we have defined earlier.
Step 5: How to consume the secret in GitHub.
Now in GitHub we can create an apikey for test environment.
In Github repo, go to Settings -> Secrets and click add New repository secret.

We will also create GitHub action yml for .net and call it mysecretsapp.yml. As we can see in mysecretsapp.yml under .github/workflows, we consume the api key we created in GitHub secrets for our test:
- name: Test
env:
apikey: ${{ secrets.APIKEY }}
run: dotnet test --no-build --verbosity normal
working-directory: MySecretsApp
Note: from my observation, it was not possible to print secret in pipeline, it can only be used in the code.
Download source code from Github.
Conclusion
This is a very simple example how isolate Secret from code base to preventing developer hard coding keys inside code and mistakenly committing it to the repository. I suggest also using tools like GitGuardian to scan the repos possible keys, password, username and etc. sensitive secrets and eventually remove them.
Originally published at https://itbackyard.com on January 2, 2022.