Store Secrets on .NET Core with Azure during development
.NET Core includes the “Secret Manager Tool” to store sensitive data during development.
It allows storing a secret in a separate file from those included in the project and shares them between different projects without checking them in source control. It does not provide encryption so it cannot be considered a trusted store.
The values are stored on a system-protected folder on the local machine that for Windows machines is:
%APPDATA%\Microsoft\UserSecret\<secretId>\secrets.json
Starting point
I created a razor page that is rendering the secret:
I set the secret in the appsettings.json:
This is how the page renders:
Enable Secret Storage
In order to enable secret’s storage, it is required to include the “UserSecretId” into the .csproj file.
The tag content should be unique and may be taken from:
An alternative way to repeat the same steps straight from Visual Studio would be by selecting the “Manage User Secrets” option:
It would automatically create and prepopulate with a GUID the “UserSecretId” element.
From the package manager console inside Visual Studio, I then run
dotnet user-secrets set "Settings:Secret" "Hidden Secret"
This created a new secret inside the secret.json file:
The DefaultBuilder automatically goes and looks for a secret inside the “secrets.json” file.
Deploy to Azure
I will create an Azure Resource Group project called “Azure Key Vault”.
The “Azure Development” features will be needed in order to have the template available:
The project template will be:
I will choose the Web App template:
I will then deploy it:
This is the deployment log:
08:27:16 - The following parameter values will be used for this operation:08:27:16 - hostingPlanName: Basic08:27:16 - skuName: F108:27:16 - skuCapacity: 108:27:16 - Build started.08:27:16 - Project "AzureKeyVaultInfrastructure.deployproj" (StageArtifacts target(s)):08:27:16 - Project "AzureKeyVaultInfrastructure.deployproj" (ContentFilesProjectOutputGroup target(s)):08:27:16 - Done building project "AzureKeyVaultInfrastructure.deployproj".08:27:16 - Done building project "AzureKeyVaultInfrastructure.deployproj".08:27:16 - Build succeeded.08:27:17 - Launching PowerShell script with the following command:08:27:17 - 'C:\Users\alberto.de.natale\source\repos\AzureKeyVault\AzureKeyVaultInfrastructure\bin\Debug\staging\AzureKeyVaultInfrastructure\Deploy-AzureResourceGroup.ps1' -StorageAccountName '' -ResourceGroupName 'AzureKeyVault' -ResourceGroupLocation 'northeurope' -TemplateFile 'C:\Users\alberto.de.natale\source\repos\AzureKeyVault\AzureKeyVaultInfrastructure\bin\Debug\staging\AzureKeyVaultInfrastructure\website.json' -TemplateParametersFile 'C:\Users\alberto.de.natale\source\repos\AzureKeyVault\AzureKeyVaultInfrastructure\bin\Debug\staging\AzureKeyVaultInfrastructure\website.parameters.json' -ArtifactStagingDirectory '.' -DSCSourceFolder '.\DSC'08:27:22 -08:27:22 -08:27:22 - Account : Alberto De Natale08:27:22 - SubscriptionName : Visual Studio Professional08:27:22 - SubscriptionId : 08:27:22 - TenantId : 08:27:22 - Environment : AzureCloud08:27:22 -08:27:24 - VERBOSE: Performing the operation "Creating Deployment" on target "AzureKeyVault".08:27:24 - VERBOSE: 08:27:24 - Template is valid.08:27:25 - VERBOSE: 08:27:25 - Create template deployment 'website-0605-0627'08:27:25 - VERBOSE: 08:27:25 - Checking deployment status in 5 seconds08:27:31 - VERBOSE: 08:27:31 - Checking deployment status in 5 seconds08:27:36 - VERBOSE: 08:27:36 - Resource Microsoft.Web/serverfarms 'Basic' provisioning status is succeeded08:27:36 - VERBOSE: 08:27:36 - Checking deployment status in 5 seconds08:27:41 - VERBOSE: 08:27:41 - Checking deployment status in 5 seconds08:27:47 - VERBOSE: 08:27:47 - Checking deployment status in 5 seconds08:27:52 - VERBOSE: 08:27:52 - Checking deployment status in 5 seconds08:27:57 - VERBOSE: 08:27:57 - Resource Microsoft.Web/sites 'webSitej6bqsndcwral6' provisioning status is succeeded08:27:57 - VERBOSE: 08:27:57 - Checking deployment status in 5 seconds08:28:03 - VERBOSE: 08:28:03 - Checking deployment status in 5 seconds08:28:08 - VERBOSE: 08:28:08 - Checking deployment status in 5 seconds08:28:13 - VERBOSE: 08:28:13 - Checking deployment status in 5 seconds08:28:19 - VERBOSE: 08:28:19 - Checking deployment status in 5 seconds08:28:24 - VERBOSE: 08:28:24 - Checking deployment status in 5 seconds08:28:29 - VERBOSE: 08:28:29 - Checking deployment status in 5 seconds08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/autoscalesettings 'Basic-AzureKeyVault' provisioning status is08:28:34 - succeeded08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/components 'webSitej6bqsndcwral6' provisioning status is succeeded08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/alertrules 'LongHttpQueue Basic' provisioning status is succeeded08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/alertrules 'CPUHigh Basic' provisioning status is succeeded08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/alertrules 'ServerErrors webSitej6bqsndcwral6' provisioning status is08:28:34 - succeeded08:28:34 - VERBOSE: 08:28:34 - Resource Microsoft.Insights/alertrules 'ForbiddenRequests webSitej6bqsndcwral6' provisioning status08:28:34 - is succeeded08:28:35 -08:28:35 - DeploymentName : website-0605-062708:28:35 - CorrelationId : bc6e5f70-068b-464e-9028-203fe2629b0a08:28:35 - ResourceGroupName : AzureKeyVault08:28:35 - ProvisioningState : Succeeded08:28:35 - Timestamp : 05/06/2019 06:28:3408:28:35 - Mode : Incremental08:28:35 - TemplateLink :08:28:35 - TemplateLinkString :08:28:35 - DeploymentDebugLogLevel :08:28:35 - Parameters : {[hostingPlanName,08:28:35 - Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable], [skuName,08:28:35 - Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable],08:28:35 - [skuCapacity, Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.DeploymentVariable]}08:28:35 - ParametersString :08:28:35 - Name Type Value08:28:35 - =============== ========================= ==========08:28:35 - hostingPlanName String Basic08:28:35 - skuName String F108:28:35 - skuCapacity Int 108:28:35 -08:28:35 - Outputs :08:28:35 - OutputsString :08:28:35 -08:28:35 -08:28:35 -08:28:35 - Successfully deployed template 'website.json' to resource group 'AzureKeyVault'.
The result is:
Where are the secrets?
I will deploy the application on the newly created web app:
And the secret won’t display:
This is because the secret.json is local to the machine where it is used and does not get published.
In the configuration tab of Azure I will create the setting:
And will result in the secret being safely stored on Azure:
Conclusion
The secret manager is a very useful tool in development in order to avoid having passwords stored in source control. My next step will be looking at how to store secrets in production by using AzureKeyVaults.