Quase que todos os projetos com os quais lidamos precisam de alguma maneira armazenar configurações que contém dados sensíveis: usuários e senhas de bancos de dados, contas de email, configurações de integrações como Facebook, etc, etc. Quando nossos projetos não são públicos, ou seja estão dentro de um repositório privado em nossa empresa, este problema pode ser apenas ignorado. Mas o que acontece quando estamos atuando em um projeto público ou mesmo em um projeto privado mas que não deve disponibilizar algumas informações para todos com acesso ao repositório?

O problema que UserSecrets resolve é bastante simples: ele permite trabalhar com estas informações sensíveis sem a necessidade de colocá-las no seu código, e consequentemente isso fica fora do controle de versões.

Instalando UserSecrets

Você faz a instalação do Secret Manager como uma tool no seu projeto, bastando para isso adicionar o seguinte pacote NuGet na seção de tools no seu project.json:

"tools": {
  "Microsoft.Extensions.SecretManager.Tools": "1.1.0-preview4-final",
}

Agora basta executar um dotnet restore para que o gerenciador seja baixado. Você terá acesso a uma ferramenta na linha de comando:

C:\projects\projeto > dotnet user-secrets -h
User Secrets Manager 1.1.0-preview4-22752
Usage: dotnet user-secrets [options] [command]
Options:
  -?|-h|--help            Show help information
  --version               Show version information
  -v|--verbose            Verbose output
  -p|--project   Path to project, default is current directory
  --id                    The user secret id to use.
Commands:
  clear   Deletes all the application secrets
  list    Lists all the application secrets
  remove  Removes the specified user secret
  set     Sets the user secret to the specified value
Use "dotnet user-secrets [command] --help" for more information about a command.

Configurando o UserSecrets

Agora é necessário que você defina um userSecretsId para o seu projeto. Este id é uma string arbitrária, mas que no seu contexto seja única, por exemplo NomeDoProjeto-123. Este valor deve ser colocado dentro do project.json como mostrado abaixo:

{
  "userSecretsId": "NomeDoMeuProjeto-123456",
  "dependencies": {
...

Feito isso você está com tudo configurado. Essa configuração só precisa ser feito uma única vez no seu projeto.

Adicionando e consumindo informações do UserSecrets

Para adicionarmos informações ao UserSecrets tudo que precisamos fazer é abrir o console na pasta do nosso projeto e executar o seguinte comando:

C:\projects\projeto > dotnet user-secrets set Chave Valor
info: Successfully saved Chave = Valor to the secret store.

Simples, né? Para ver todos os valores armazenados:

C:\projects\projeto > dotnet user-secrets list
info: OutraChave = OutroValor
info: Chave = Valor

Bem bacana!

Agora que temos nossas informações configuradas, precisamos consumí-las no nosso código. Para isso vamos adicionar um pacote NuGet que consome informações do UserSecrets. Vamos adicionar a seguinte dependência nas dependencies no project.json:

"dependencies": {
  "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
...

Verifique a versão correta para o seu projeto no gerenciador do NuGet. Feito isso salve seu arquivo ou rode dotnet restore.

Agora a coisa fica interassante: não é necessário fazer ifs para definir se a informação virá do UserSecrets em dev ou se virá de um arquivo do appsettings.json ou de variáveis de ambiente. No Startup.cs da aplicação vamos fazer o seguinte:

public Startup(IHostingEnvironment hostingEnvironment)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(hostingEnvironment.ContentRootPath)
        .AddJsonFile("appsettings.json")
        .AddJsonFile("appsettings.local.json", optional: true)
        .AddEnvironmentVariables();

    if (hostingEnvironment.IsDevelopment())
        builder.AddUserSecrets();

    Configuration = builder.Build();
    this.hostingEnvironment = hostingEnvironment;
}

Repare que nas linhas 9 e 10 estamos adicionando UserSecrets se estiver no ambiente de Desenvolvimento. Repare que não devemos usar isso em ambiente como produção, etc. Nestes ambientes você pode usar Variáveis de Ambiente ou as configurações do Azure que sobrescrevem os arquivos de configuração (web.config ou appsettings.json).

E quando quisermos consumir isso no nosso código, fazemos algo do tipo:

var emailConfig = new EmailConfiguration(Configuration["ContaDeEmail"], Configuration["SenhaDeEmail"]);

Onde ContaDeEmail e SenhaDeEmail são informações que eu armazenei no UserSecrets no ambiente de desenvolvimento, mas que no ambiente de produção podem estar nas configurações do Azure. Eu não precisarei mudar meu código pois o ASP.NET Core abstrai isso para mim.

Importante ressaltar que UserSecrets, atualmente, não criptografa as informações armazenadas localmente. Elas são gravadas em um aquivo json na máquina local e não devem ser manipuladas diretamente pois a ferramenta pode mudar. Utilize sempre a interface via linha de comando e através do NuGet para leitura dos dados.

Por hoje era isso. Abração!