Adding an application in Hashicorp Vault

Date: 2019-10-09

Enabling AppRole authentication method

First you should enable new Authentication Method in Vault web application.

add_app_role.PNG

Then you type name. Let’s leave it ‘as is’.

add_app_role_2.PNG

Then you should generate RoleId and SecretId for your application. This values are some kind of login and password for application which allow the application to get an access token. We may use any string. I will generate GUIDs using Online GUID Generator.

guid_generator.PNG

Then we write this two GUIDs as RoleId and SecretId in our application.

app_settings.png

We use this values to get Vault token for our application.

Setting up a .NET application

To use Vault secrets, you should add a provider for reading Auth Token and also a provider for getting keys.

internal class AuthResponse : IAuthResponse
{
    public string Accessor { get; }

    public string ClientToken { get; }

    public bool Renewable { get; }

    public int LeaseDuration { get; }

    [JsonConstructor]
    public AuthResponse(
        [JsonProperty("accessor")] string accessor,
        [JsonProperty("client_token")] string clientToken,
        [JsonProperty("renewable")] bool renewable,
        [JsonProperty("lease_duration")] int leaseDuration)
    {
        Accessor = accessor;
        ClientToken = clientToken;
        Renewable = renewable;
        LeaseDuration = leaseDuration;
    }
}

public async Task<IAuthResponse> GetTokenAsync(CancellationToken cancellationToken)
{
    // Server Uri and LoginPath you may find in your settings.
    var requestUrl = new Uri(new Uri(_config.ServerUri), _config.LoginPath);
    var requestPayload = new
    {
        role_id = _config.AppRoleId, // Role Id (login)
        secret_id = _config.AppSecretId // secret Id (password)
    };

    var request = new HttpRequestMessage(HttpMethod.Post, requestUrl)
    {
        Content = new ObjectContent<dynamic>(requestPayload, new JsonMediaTypeFormatter())
    };

    // If you have namespace, you should add it via http headers
    if (!string.IsNullOrWhiteSpace(_config.Namespace))
    {
        request.Headers.Add("X-Vault-Namespace", _config.Namespace);
    }

    var response = await _httpProvider.SendAsync(request, cancellationToken);
    response.EnsureSuccessStatusCode();

    var responseJson = await response.Content.ReadAsAsync<JObject>(cancellationToken);
    return responseJson["auth"].ToObject<AuthResponse>();
}

Now we have a token that allows us to get secrets from the Vault storage.

// using section start
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Eds.KeyVault.Contracts.Interfaces;
using VaultSharp;
using VaultSharp.V1.AuthMethods.Token;
// using section end

public class KeyVaultSecretClient : IKeyVaultSecretClient
{
    // client from VaultSharp namespace.
    private readonly IVaultClient _vaultClient;

    public KeyVaultSecretClient(IVaultClient vaultClient)
    {
        _vaultClient = vaultClient ?? throw new ArgumentNullException(nameof(vaultClient));
    }

    public KeyVaultSecretClient(KeyVaultSecretClientConfig config, string clientToken)
    {
        if (config == null)
        {
            throw new ArgumentNullException(nameof(config));
        }

        var settings = new VaultClientSettings(config.ServerUri, new TokenAuthMethodInfo(clientToken));
        if (!string.IsNullOrWhiteSpace(config.Namespace))
        {
            settings.BeforeApiRequestAction = (httpClient, message) => { message.Headers.Add("X-Vault-Namespace", config.Namespace); };
        }

        _vaultClient = new VaultClient(settings);
    }

    public async Task<IDictionary<string, object>> GetSecretsAsync(string secretPath, CancellationToken cancellationToken)
    {
        var secret = await _vaultClient.V1.Secrets.KeyValue.V1.ReadSecretAsync(secretPath);

        return secret.Data;
    }
}

Now you may use a dictionary of all key-values from the Vault.

Add new AppRole auth record in Vault

AN official documentation is available here. We are going to add new AppRole record via Vault console.