How do you encrypt a password within appsettings.json for ASP.net Core 2?

梦想与她 提交于 2020-05-26 06:00:28

问题


I'd like to use my appsettings.json to store a "master password".

This master password would then be used to open up a private key (and its subsequent password store) generated by this excellent password store package: https://github.com/neosmart/SecureStore

The problem is, I can't think of any way to encrypt the master password. I know in .NET 4.5, it was possible to do the following:

1) Place your password into the web.config file

2) Run this script: aspnet_regiis.exe -pef appSettings "C:\myfolder"

3) Your password would end up being encrypted - but read securely by your program.

https://www.codeproject.com/Articles/599416/Encrypting-ASP-NET-Application-Settings

Am I going about this the right way or is there a better practice?


回答1:


Remember do not store secrets in the main appsettings.json that is in the web site and usually held in source control. Use a file provider to locate the file in some other location elsewhere on the server.

If you have access to Azure, you could store the secret in Azure Key Vault instead of appsettings.json.

With that in mind, if your want to use a JSON file, you can use a bridge or a proxy class to handle the decryption of values.

First you will need a class to decrypt the values. For brevity, I won't go into the details of the decryption class here and will just assume that a class called SettingsDecryptor has been written and implements an interface called ISettingsDecryptor with a single method Decrypt which decrypts a string value.

The bridge class takes two constructor parameters.

  • The first is an IOptions<T> or IOptionsSnapshot<T> where T is that class that the section in appsettings.json is bound to via the services.Configure method (E.g. MyAppSettings). Alternatively, if you do not want to bind to a class, you could use IConfiguration instead and read directly from the configuration.
  • The second is the decryption class that implements ISettingsDecryptor.

In the bridge class, each property that requires decrypting should use the decryption class to decrypt the encrypted value in the configuration.

public class MyAppSettingsBridge : IAppSettings
{
    private readonly IOptions<MyAppSettings> _appSettings;

    private readonly ISettingsDecrypt _decryptor;

    public MyAppSettingsBridge(IOptionsSnapshot<MyAppSettings> appSettings, ISettingsDecrypt decryptor) {
        _appSettings = appSettings ?? throw new ArgumentNullException(nameof(appSettings));
        _decryptor = decryptor ?? throw new ArgumentException(nameof(decryptor));
    }

    public string ApplicationName => _appSettings.Value.ApplicationName;

    public string SqlConnectionSting => _decryptor.Decrypt(_appSettings.Value.Sql);

    public string OracleConnectionSting => _decryptor.Decrypt(_appSettings.Value.Oracle);
}

The DI container should be set up something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddOptions();            
    services.Configure<MyAppSettings>(Configuration.GetSection("MyAppSettings"));
    services.AddSingleton(Configuration);        
    services.AddSingleton<ISettingsDecrypt, SettingsDecryptor>();
    services.AddScoped<IAppSettings, MyAppSettingsBridge>();
}

The controller can then have a constructor that takes the bridge as an IAppSettings to access the decrypted settings.

The above answer is a brief summary of the overall solution as there is quite a bit of code required.

The full detailed explanation can be seen at my blog post Hiding Secrets in appsettings.json – Using a Bridge in your ASP.Net Core Configuration (Part 4) where I describe using a bridge pattern in detail. There is also a full example (including a decryption class) on Github at https://github.com/configureappio/ConfiguarationBridgeCrypto




回答2:


The JSON configuration provider does not support encryption. Currently, the only out of the box provider that does support encrypted configuration is Azure KeyVault. You can use KeyVault whether or not your application is actually hosted on Azure, and although it's not free, the allowances are such that it would likely only cost pennies in most scenarios.

That said, part of the beauty of Core is that it's completely modular. You can always create your own configuration provider(s) and implement whatever you want. For example, you could write a JSON provider that actually does support encryption, if that's how you want to go.




回答3:


For ASP.NET Core the best solution is to do any transformations of the configuration values, like decryption or string replacements, when the application starts. This is why configuration provider exists.

The configuration providers can be chained. In the source code of the Microsoft.Extensions.Configuration there is class called ChainedConfigurationProvider that can be used as an example.

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return new HostBuilder()
    .ConfigureAppConfiguration((host, config) => {

        var jsonFile = new ConfigurationBuilder();
        jsonFile.AddJsonFile("appsettings.json");
        // the json file is the source for the new configuration provider.
        config.AddConfiguration(jsonFile.Build());
    });
}

If you are using Docker Swarm or Kubernetes you don't have to encrypt the password in the appsettings.json file. You can use the build-in Key-per-file Configuration Provider or custom configuration provider to read the password from a docker secret and map it to a configuration value.

On my blog post How to manage passwords in ASP.NET Core configuration files I explain in detail how to create a custom configuration provider that allows you to keep only the password as a secret and update the configuration string at runtime. Also the the full source code of this article is hosted on github.com/gabihodoroaga/blog-app-secrets.




回答4:


Instead of storing sensitive data in json files which you can't encrypt you can use Secret Manager tool. Here is the full documentation.

EDIT: from security perspective it is viable only for development purposes.



来源:https://stackoverflow.com/questions/48159233/how-do-you-encrypt-a-password-within-appsettings-json-for-asp-net-core-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!