rajanadar / VaultSharp

A comprehensive cross-platform .NET Library for HashiCorp's Vault, a secret management tool
http://rajanadar.github.io/VaultSharp
Apache License 2.0
493 stars 134 forks source link

Getting a good wrapping token #276

Closed MB34 closed 2 years ago

MB34 commented 2 years ago

The UI version we have is 1.3.2+prem. My local CLI is v1.11.0 (ea296ccf58507b25051bc0597379c467046eb2f1), built 2022-06-17T15:48:44Z VaultSharp version is 1.7.0.4

I logged in via the CLI using my standard Token obtained from the UI. Then I ran this to get a wrapping token:

_vault write -wrap-ttl=1h -format=json auth/approle/login role_id="e309ea24-994c-771e-939f-49e24a936ef2" secretid="9597c7d0-3a88-c8f7-e43f-e8999600e38e"

that call returned:

{
  "request_id": "",
  "lease_id": "",
  "lease_duration": 0,
  "renewable": false,
  "data": null,
  "warnings": null,
  "wrap_info": {
    "token": "s.QCyDi4lFwnPtijUNxuitjFmc.dYgGw",
    "accessor": "zQuxfTpwJxaB0lULi01EgGDL.dYgGw",
    "ttl": 3600,
    "creation_time": "2022-08-22T09:47:27.6944367-05:00",
    "creation_path": "auth/approle/login",
    "wrapped_accessor": "sNpgtKybyGjf5pwWX4PlCOE8.dYgGw"
  }
}

Now, I used the token in an unwrapping call like this:

IVaultClient vaultClientForUnwrapping = new VaultClient(
    new VaultClientSettings(_settings.Address, new TokenAuthMethodInfo(vaultToken: wrappingToken))
);

string appRoleAuthSecretId
    = vaultClientForUnwrapping.V1.System
        .UnwrapWrappedResponseDataAsync<Dictionary<string, object>>(tokenId: null)
            .Result.Data["secret_id"]
                .ToString();

And when attempting to run the Unwrapping call above, I get this exception:

One or more errors occurred. ({"errors":["wrapping token is not valid or does not exist"]} Now, trying different things...

Using same wrap_info.token returned, passing it to this function:

private async Task<Secret<Dictionary<string, object>>> UnwrapToken(string? wrappingToken)
{
    // We need to create two VaultClient objects for authenticating via AppRole. The first is for
    // using the unwrap utility. We need to initialize the client with the wrapping token.
    IAuthMethodInfo wrappedTokenAuthMethod = new TokenAuthMethodInfo(wrappingToken);
    var vaultClientSettingsForUnwrapping = new VaultClientSettings(_settings.Address, wrappedTokenAuthMethod);

    IVaultClient vaultClientForUnwrapping = new VaultClient(vaultClientSettingsForUnwrapping);

    // We pass null here instead of the wrapping token to avoid depleting
    // the token's single use. This is to work around the fact that VaultSharp
    // requires a valid wrapping token to initialize the VaultClient.
    /*
    string appRoleAuthSecretId = vaultClientForUnwrapping.V1.System
        .UnwrapWrappedResponseDataAsync<Dictionary<string, object>>(tokenId: null)
            .Result.Data["secret_id"]
                .ToString();
    */
    Secret<Dictionary<string, object>> appRoleAuthSecretId = await vaultClientForUnwrapping.V1.System.UnwrapWrappedResponseDataAsync<Dictionary<string, object>>(null);
    return appRoleAuthSecretId;
}

When checking appRoleAuthSecretId, Data is null. Can't understand why...

I found another CLI that returns a good wrapping_token:

vault write -wrap-ttl=1h -force auth/approle/role/trans/secret-id where trans is the role I'm trying to authorize.

But for some reason it is single use...And when I try to make any calls on the client returned using it, I get a missing client token error.

Kind of confused as to how to get a good wrapping token. I'm doing it according to the documentation AND using the code in your samples but I cannot get anything to work correctly.

One other question, you always say that there is a file stored by a trusted orchestrator, what is the format of that file? Doe it only have the secret-id or wrapping token in it?

rajanadar commented 2 years ago

thanks @MB34 . Ack'ed.

MB34 commented 2 years ago

Acknowledged but no answers?

MB34 commented 2 years ago

Since WE AREN'T GETTING ANY help on this, we've decided to move to using the role-id and secret-id for AppRole authentication for the time being. You can view our new question here: https://github.com/rajanadar/VaultSharp/issues/277

konidev20 commented 2 years ago

Hey @MB34,

I believe that you are mistaken by the usage of the wrap functionality in Vault. You cannot use the wrapped token to login into Vault.

You have to unwrap the login token first before providing it to the Vault Client.

Wrapping Tokens are single-use. If you try to unwrap it the second time, it will return an error; precisely the one you have shared since it has been invalidated.

rajanadar commented 2 years ago

@MB34 , i meant to type ack'ed and will look at in the weekend. @konidev20 replied well. Can you please provide the unwrapped login token to vault and see if your issue still persists?

MB34 commented 2 years ago

Hey @MB34,

I believe that you are mistaken by the usage of the wrap functionality in Vault. You cannot use the wrapped token to login into Vault.

You have to unwrap the login token first before providing it to the Vault Client.

Wrapping Tokens are single-use. If you try to unwrap it the second time, it will return an error; precisely the one you have shared since it has been invalidated.

Well, that's EXACTLY how the sample code presents it. It does NOT state this fact, nor has any descriptions of how to do it in a different manner than I'm doing, per the 3 steps in this post: https://github.com/rajanadar/VaultSharp/issues/212

konidev20 commented 2 years ago

Hey @MB34,

I will checkout this issue that you have mentioned and try to reproduce the issue you're facing.

Thanks

MB34 commented 2 years ago

I'm also attempting to use the example code from here with the same results: https://github.com/hashicorp/vault-examples/blob/main/examples/auth-methods/approle/dotnet/Example.cs

I set the wrappingToken variable to the wrapping token received from the call:

vault.exe write -f wrap-ttl=2m auth/approle/role/trans/secret-id

MB34 commented 2 years ago

OK, looks like this code works, changed my mount point to remove the namespace and it began working

var roleId = ConfigurationManager.AppSettings["role-id"];
if (String.IsNullOrEmpty(roleId))
{
    throw new System.ArgumentNullException("AppRole Role Id");
}
string wrappingToken = <wrapping_token from trusted orchestrator>;

IAuthMethodInfo wrappedTokenAuthMethod = new TokenAuthMethodInfo(wrappingToken);
var vaultClientSettingsForUnwrapping = new VaultClientSettings(vaultAddr, wrappedTokenAuthMethod);

IVaultClient vaultClientForUnwrapping = new VaultClient(vaultClientSettingsForUnwrapping);

Secret<Dictionary<string, object>> secretIdData = vaultClientForUnwrapping.V1.System
    .UnwrapWrappedResponseDataAsync<Dictionary<string, object>>(null).Result;

var secretId = secretIdData.Data["secret_id"].ToString();

IAuthMethodInfo authMethod = new AppRoleAuthMethodInfo(roleId, secretId);
var vaultClientSettings = GetVaultClientSettings(authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

Secret<CallingTokenInfo> tokenData = vaultClient.V1.Auth.Token.LookupSelfAsync().Result;
Environment.SetEnvironmentVariable("VAULT_TOKEN", tokenData.Data.Id);

vaultClient.V1.Auth.PerformImmediateLogin();

var kv2Secret = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(path: "trans", mountPoint: "exp").Result;
MB34 commented 2 years ago

@rajanadar I do have one question. Is the Namespace being read from my ENV variable or is it inherent from the client used to login to the role? This might be something to add to the documentation of the ReadSecretAsync() method's mountpoint parameter.

konidev20 commented 2 years ago

Hey @MB34,

As per my understanding, the VaultSharp Library doesn't read any environment variables. The Namespace parameter has to be configured through VaultClientSettings which will set the X-Vault-Namespace header for each request being made to the Vault Server.

Vault is designed to resolve the secret location based on a relative mountPoint if the X-Vault-Namespace is set or a complete mounPoint.

For example, these three requests are equivalent:

  1. Path: ns1/ns2/secret/foo
  2. Path: secret/foo, Header: X-Vault-Namespace: ns1/ns2/
  3. Path: ns2/secret/foo, Header: X-Vault-Namespace: ns1/

Refer: https://www.vaultproject.io/docs/enterprise/namespaces

Thanks, @konidev20

Rmcelligott commented 2 years ago

Hey @MB34 Could you kindly post some more info on your resolution for this? I'm having a similar issue as this and I'm making little headway getting the unwrap method to work. Thanks