IMHO, it is "best" to use a dedicated secret-engine.
Most of the secret engines:
Hashicorp Vault << probably the most flexible..some call it the "swiss army knife" of secrets
Thycotic Secret Store
Azure KeyVault (azure cloud)
AKS (AWS) (amazon cloud)
(and your buddy, Google)
are similar.
If you are using Kubernetes, you can code up a concrete that will read values from the Kubernetes "mounted secrets". (I prefer the virtual file mounted secrets).
What I do is create an abstraction, and then code up a concrete(s) to my implmentation choice.
For development environment, you can also code a concrete to this : https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows
But for production, I use the below abstraction, and code up my concrete to one of the solutions above.
https://pbhadani.com/posts/google-secret-manager/
using System.Threading;
using System.Threading.Tasks;
public interface ISecretRetriever
{
Task<SecretModel> GetSecret(string secretName);
Task<SecretModel> GetSecret(string secretName, CancellationToken ct);
}
..
using System.Collections.Generic;
using System.Linq;
[System.Diagnostics.DebuggerDisplay("SecretName='{SecretName}', SubSecretsCount='{SubSecrets.Count}'")]
public class SecretModel
{
public SecretModel()
{
this.SubSecrets = new List<SubSecret>();
}
public string SecretName { get; set; }
public ICollection<SubSecret> SubSecrets { get; set; }
}
..
using System.Security;
[System.Diagnostics.DebuggerDisplay("KeyName = '{KeyName}', SecretValueLength='{null == SecretValue ? 0 : SecretValue.Length}'")]
public class SubSecret
{
public string KeyName { get; set; }
public SecureString SecretValue { get; set; }
}
Then your IoC registrations will look something like this:
if (hostingEnvironment.IsDevelopment()) /* https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.hostingenvironmentextensions.isdevelopment?view=aspnetcore-3.1 */
{
/* code your LowerEnvironmentsInsecureSecretRetriever to https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows */
services.AddSingleton<ISecretRetriever, LowerEnvironmentsInsecureSecretRetriever>();
}
else
{
/* code your HashicorpVaultSecretRetriever to HashicorpVault (or use a different one */
services.AddSingleton<ISecretRetriever, HashicorpVaultSecretRetriever>();
}