Code Monkey home page Code Monkey logo

vaultsharp's Introduction

VaultSharp

The most comprehensive cross-platform .NET Library for HashiCorp's Vault - A Secret Management System.

VaultSharp NuGet: NuGet

VaultSharp Latest Documentation: Inline Below and also at: https://rajanadar.github.io/VaultSharp/

VaultSharp Questions/Clarifications: Ask on Stack Overflow with the tag vaultsharp

VaultSharp Gitter Lobby: Gitter Lobby

Report Issues/Feedback: Create a VaultSharp GitHub issue

Contributing Guidlines: VaultSharp Contribution Guidelines

NuGet Join the chat at https://gitter.im/rajanadar-VaultSharp/Lobby License Build status

What is VaultSharp?

  • VaultSharp is a .NET Standard 1.3, .NET Standard 2.0, .NET Standard 2.1, .NET Framework 4.5, .NET Framework 4.6.x, .NET Framework 4.7.x, .NET Framework 4.8, .NET 5.0 and .NET 6.0 based cross-platform C# Library that can be used in any .NET application to interact with Hashicorp's Vault.
  • The Vault system is a secret management system built as an Http Service by Hashicorp.

VaultSharp has been re-designed ground up, to give a structured user experience across the various auth methods, secrets engines & system apis. Also, the Intellisense on IVaultClient class should help. I have tried to add a lot of documentation.

Give me a quick snippet for use!

  • Add a Nuget reference to VaultSharp as follows Install-Package VaultSharp -Version <latest_version>
  • Instantiate a IVaultClient as follows:
// Initialize one of the several auth methods.
IAuthMethodInfo authMethod = new TokenAuthMethodInfo("MY_VAULT_TOKEN");

// Initialize settings. You can also set proxies, custom delegates etc. here.
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// Use client to read a key-value secret.

// Very important to provide mountpath and secret name as two separate parameters. Don't provide a single combined string.
// Please use named parameters for 100% clarity of code. (the method also takes version and wrapTimeToLive as params)

Secret<SecretData> kv2Secret = await vaultClient.V1.Secrets.KeyValue.V2
                               .ReadSecretAsync(path: "secretPath", mountPoint: "mountPointIfNotDefault");

// Generate a dynamic Consul credential
Secret<ConsulCredentials> consulCreds = await vaultClient.V1.Secrets.Consul.GetCredentialsAsync(consulRole, consulMount);
string consulToken = consulCredentials.Data.Token;

Gist of the features

  • VaultSharp supports
    • All the Auth Methods for Logging into Vault. (AppRole, AWS, Azure, GitHub, Google Cloud, JWT/OIDC, Kubernetes, LDAP, Okta, RADIUS, TLS, Tokens & UserPass)
    • All the secret engines to get dynamic credentials. (AD, AWS EC2 and IAM, Consul, Cubbyhole, Databases, Google Cloud, Key-Value, Nomad, PKI, RabbitMQ, SSH and TOTP)
    • Several system APIs including enterprise vault apis
  • You can also bring your own "Auth Method" by providing a custom delegate to fetch a token from anywhere.
  • VaultSharp has first class support for Consul engine.
  • KeyValue engine supports both v1 and v2 apis.
  • Abundant intellisense.
  • Provides hooks into http-clients to set custom proxy settings etc.

VaultSharp - Supported .NET Platforms and Implementations

VaultSharp is built on .NET Standard 1.3 & .NET Standard 2.0 & .NET Standard 2.1 & .NET Frameworks 4.5, 4.6.x, 4.7.x, 4.8 & .NET 5, .NET 6. This makes it highly compatible and cross-platform.

The following implementations are supported due to that.

  • .NET Core 1.x, 2.x, 3.x
  • .NET Framework 4.5, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2 and 4.8
  • .NET 5.0
  • .NET 6.0
  • Mono 4.x and above
  • Xamarin.iOS 10.x and above
  • Xamarin Mac 3.x and above
  • Xamarin.Android 7.x and above
  • UWP 10.x and above

Source: https://github.com/dotnet/standard/blob/master/docs/versions.md

VaultSharp and Consul Support

  • VaultSharp supports dynamic Consul credential generation.
  • Please look at the API usage in the 'Consul' section of 'Secrets Engines' below, to see all the Consul related methods in action.

VaultSharp and Automatic Token Refresh

  • VaultSharp DOES NOT support automatic token refresh.
  • It is the responsibility of the host application to refresh the login token as per its expiry.
  • The host app is free to use the vaultClient.V1.Auth.ResetVaultToken(); method to refresh the token from time to time.
  • The host app is also free to re-initialize the entire VaultClient instance. This is helpful when you use AWS Signatures etc. where even if you try to just reset the vault token, it may fail because the signature time is pretty old. In those cases, feel free to re-initialize the whole vaultclient instance

VaultSharp and VaultClient Dependency Injection Lifetime

  • If the vault login token expiry is way more than the deployment cadence of your application, then the recommended lifetime scope for VaultSharp's IVaultClient is Singleton. This is because, it will login only once to Vault to get the auth token and use it for the rest of all the vault calls you make.
  • The only use-case when the Singleton lifetime will fail you is if your login token expiry is less than your application's deployment cadence. In that case, you have to either write your automatic token renewal logic OR use a RequestScoped lifetime for DI. Renewal logic is more performant than request scoping. This is because, you wouldn't want vaultsharp to request a login token for every web request of yours.

VaultSharp and Automatic Built-in Client Side failover

  • VaultSharp DOES NOT support built-in client-side failover either by supporting multiple endpoint URI's or by supporting roundrobin DNS.
  • I repeat, it DOES NOT.
  • It works off a single URL that you provide. Any sort of fail-over etc. needs to be done by you.
  • You are free to instantiate a new instance of VaultClient with a different URI.

VaultSharp and Immediate Login Failure Detection

  • By DEFAULT, VaultSharp performs a lazy login to Vault.
  • What this means is that, once you initialize VaultSharp with AuthInfo, VaultSharp will not try to immediately login into Vault.
  • It'll attempt to login to Vault, only when the first real functional operation is requested. E.g. ReadSecretAsync etc.
  • This has the pro that the acquired token can live as long as possible.
  • The downside to this is that, any login issues will be a non-app startup discovery (assuming VaultClient is initialized at app startup) which may be not desirable at all. Folks may want to know that Vault Login failed as early as possible.
  • VaultSharp now supports this feature starting version 1.6.0.3
  • Imemdiately after initializing vault client, invoke the login method to force a login.
IVaultClient vaultClient = new VaultClient(vaultClientSettings);
vaultClient.V1.Auth.PerformImmediateLogin();
  • Please note that this will not work for Token Authentication since you already have a vault token.

Auth Methods

  • VaultSharp supports all authentication methods supported by the Vault Service
  • Here is a sample to instantiate the vault client with each of the authentication backends.

AliCloud Auth Method

// setup the AliCloud based auth to get the right token.

IAuthMethodInfo authMethod = new AliCloudAuthMethodInfo(roleName, base64EncodedIdentityRequestUrl, base64EncodedIdentityRequestHeaders);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the AliCloud jwt

App Role Auth Method

// setup the AppRole based auth to get the right token.

IAuthMethodInfo authMethod = new AppRoleAuthMethodInfo(roleId, secretId);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the app role and secret id.

AWS Auth Method

AWS Auth method has 2 flavors. An EC2 way and an IAM way. Here are examples for both.

AWS Auth Method - EC2
// setup the AWS-EC2 based auth to get the right token.

IAuthMethodInfo authMethod = new EC2AWSAuthMethodInfo(pkcs7, null, null, nonce, roleName);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the aws-ec2 role
// setup the AWS-EC2 based auth to get the right token.

IAuthMethodInfo authMethod = new EC2AWSAuthMethodInfo(null, identity, signature, nonce, roleName);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the aws-ec2 role
AWS Auth Method - IAM
// setup the AWS-IAM based auth to get the right token.

// Step 1: Pull the following NuGet Packages

// 1. AWSSDK.Core
// 2. AWSSDK.SecurityToken

// Step 2: Boiler-plate code to generate the Signed AWS STS Headers.

var amazonSecurityTokenServiceConfig = new AmazonSecurityTokenServiceConfig();

// If you are running VaultSharp on a real EC2 instance, use the following line of code.
// var awsCredentials = new InstanceProfileAWSCredentials();

// If you are running VaultSharp on a non-EC2 instance like local dev boxes or non-AWS environment, use the following line of code.

AWSCredentials awsCredentials = new StoredProfileAWSCredentials(); // picks up the credentials from your profile.
// AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey: "YOUR_ACCESS_KEY", secretKey: "YOUR_SECRET_KEY"); // explicit credentials

var iamRequest = GetCallerIdentityRequestMarshaller.Instance.Marshall(new GetCallerIdentityRequest());

iamRequest.Endpoint = new Uri(amazonSecurityTokenServiceConfig.DetermineServiceURL());
iamRequest.ResourcePath = "/";

iamRequest.Headers.Add("User-Agent", "https://github.com/rajanadar/vaultsharp/0.11.1000");
iamRequest.Headers.Add("X-Amz-Security-Token", awsCredentials.GetCredentials().Token);
iamRequest.Headers.Add("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");

new AWS4Signer().Sign(iamRequest, amazonSecurityTokenServiceConfig, new RequestMetrics(), awsCredentials.GetCredentials().AccessKey, awsCredentials.GetCredentials().SecretKey);

// This is the point, when you have the final set of required Headers.
var iamSTSRequestHeaders = iamRequest.Headers;

// Step 3: Convert the headers into a base64 value needed by Vault.

var base64EncodedIamRequestHeaders = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(iamSTSRequestHeaders)));

// Step 4: Setup the IAM AWS Auth Info.

IAuthMethodInfo authMethod = new IAMAWSAuthMethodInfo(nonce: nonce, roleName: roleName, requestHeaders: base64EncodedIamRequestHeaders);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the aws-iam role

Azure Auth Method

// setup the Azure based auth to get the right token.

IAuthMethodInfo authMethod = new AzureAuthMethodInfo(roleName, jwt);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the azure jwt

CloudFoundry Auth Method

// setup the CloudFoundry based auth to get the right token.

IAuthMethodInfo authMethod = new CloudFoundryAuthMethodInfo(roleName, instanceCertContent, instanceKeyContent);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the CloudFoundry jwt
CloudFoundry Signature Creation
var signing_time = CloudFoundrySignatureProvider.GetFormattedSigningTime(DateTime.UtcNow);
var signature = CloudFoundrySignatureProvider.GetSignature(signingTime, cfInstanceCertContent, roleName, cfInstanceKeyContent);

GitHub Auth Method

IAuthMethodInfo authMethod = new GitHubAuthMethodInfo(personalAccessToken);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the github token.

Google Cloud Auth Method

// setup the Google Cloud based auth to get the right token.

IAuthMethodInfo authMethod = new GoogleCloudAuthMethodInfo(roleName, jwt);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the Google Cloud jwt

JWT/OIDC Auth Method

// setup the JWT/OIDC based auth to get the right token.

IAuthMethodInfo authMethod = new JWTAuthMethodInfo(roleName, jwt);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the jwt

Kubernetes Auth Method

// setup the Kubernetes based auth to get the right token.

IAuthMethodInfo authMethod = new KubernetesAuthMethodInfo(roleName, jwt);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the Kubernetes jwt

LDAP Authentication Backend

LDAP Authentication Login Method
IAuthMethodInfo authMethod = new LDAPAuthMethodInfo(userName, password);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the LDAP username and password.
LDAP Auth Backend - Groups and User management
  • You can use the methods to CRUD LDAP groups and users now.
await _authenticatedVaultClient.V1.Auth.LDAP.WriteGroupAsync(groupName, policies);
await _authenticatedVaultClient.V1.Auth.LDAP.ReadGroupAsync(groupName);
await _authenticatedVaultClient.V1.Auth.LDAP.ReadAllGroupsAsync();
await _authenticatedVaultClient.V1.Auth.LDAP.DeleteGroupAsync(groupName);

await _authenticatedVaultClient.V1.Auth.LDAP.WriteUserAsync(username, policies, groups);
await _authenticatedVaultClient.V1.Auth.LDAP.ReadUserAsync(username);
await _authenticatedVaultClient.V1.Auth.LDAP.ReadAllUsersAsync();
await _authenticatedVaultClient.V1.Auth.LDAP.DeleteUserAsync(username);

Kerberos Authentication Backend

Requires https://github.com/wintoncode/vault-plugin-auth-kerberos .

IAuthMethodInfo authMethod = new KerberosAuthMethodInfo(); // uses network credential by default.
// IAuthMethodInfo authMethod = new KerberosAuthMethodInfo(credentials); // use your own ICredentials
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the 
// vault token/policies mapped to the current ActiveDirectory/Kerberos identity.

OCI Auth Method

var requestHeaders = new Dictionary<string, object>
{
     {"date", new List<string> { "Fri, 22 Aug 2019 21:02:19 GMT" } },
     {"(request-target)", new List<string> { "get /v1/auth/oci/login/devrole" } },
     {"host", new List<string> { "127.0.0.1" } },
     {"content-type", new List<string> { "application/json" } },
     {"authorization", new List<string> { 
          "Signature algorithm=\"rsa-sha256\",headers=\"date (request-target) host\",keyId=\"ocid1.tenancy.oc1..aaaaaaaaba3pv6wkcr4jqae5f15p2b2m2yt2j6rx32uzr4h25vqstifsfdsq/ocid1.user.oc1..aaaaaaaat5nvwcna5j6aqzjcaty5eqbb6qt2jvpkanghtgdaqedqw3rynjq/73:61:a2:21:67:e0:df:be:7e:4b:93:1e:15:98:a5:b7\",signature=\"GBas7grhyrhSKHP6AVIj/h5/Vp8bd/peM79H9Wv8kjoaCivujVXlpbKLjMPeDUhxkFIWtTtLBj3sUzaFj34XE6YZAHc9r2DmE4pMwOAy/kiITcZxa1oHPOeRheC0jP2dqbTll8fmTZVwKZOKHYPtrLJIJQHJjNvxFWeHQjMaR7M=\",version=\"1\""
        } }
};

IAuthMethodInfo authMethod = new OCIAuthMethodInfo(roleName, requestHeaders);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the OCI entity.

Okta Auth Method

IAuthMethodInfo authMethod = new OktaAuthMethodInfo(userName, password);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the Okta username and password.
Okta Verify
string nonce = "<nonce>";
var challengeResponse = await vaultClient.V1.Auth.Okta.VerifyPushChallengeAsync(nonce);
var answer = challengeResponse.Data.CorrectAnswer;

// verify this answer

RADIUS Auth Method

IAuthMethodInfo authMethod = new RADIUSAuthMethodInfo(userName, password);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the RADIUS username and password.

Certificate (TLS) Auth Method

// Please note that the certificate needs to be in pkcs12 format with a private key.
// Turn your cert + key into pkcs12 format with the following command:

// openssl pkcs12 -export -out Cert.p12 -in your-cert.pem -inkey your-key.pem

var certificate = new X509Certificate2(your-p12-bytes, your-pass);

IAuthMethodInfo authMethod = new CertAuthMethodInfo(certificate);

// Optionally, you can also provide a Certificate Role Name during Auth.
// IAuthMethodInfo authMethod = new CertAuthMethodInfo(certificate, certificateRoleName);

// And if you want to use the full chain of client-certificates, then use this overload
// X509Certificate2Collection x509Certificate2Collection = <load the full chain of certs>;
// IAuthMethodInfo authMethod = new CertAuthMethodInfo(x509Certificate2Collection);

var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the client certificate.

Token Auth Method

Token Auth Login Method
IAuthMethodInfo authMethod = new TokenAuthMethodInfo(vaultToken);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the vault token.
Token Creation
  • You can use the CreateTokenAsync method to create various types of tokens.
CreateTokenRequest request = new CreateTokenRequest();

// CreateTokenRequest has options to create orphaned tokens, role based tokens etc. with attached policies.
Secret<object> tokenData = await _authenticatedVaultClient.V1.Auth.Token.CreateTokenAsync(request);
Token Lookup (any Token)
  • You can use the LookupAsync method to lookup information about any Vault Token.
string token = "token-for-which-you-need-info";

Secret<ClientTokenInfo> tokenData = await _authenticatedVaultClient.V1.Auth.Token.LookupAsync(token);
Token Lookup (Calling Token)
  • You can use the LookupSelfAsync method to lookup information about your current Vault Token.
Secret<CallingTokenInfo> tokenData = await _authenticatedVaultClient.V1.Auth.Token.LookupSelfAsync();

Username and Password Auth Method

IAuthMethodInfo authMethod = new UserPassAuthMethodInfo(username, password);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// any operations done using the vaultClient will use the
// vault token/policies mapped to the username/password.

Custom Auth Method - Bring your own Vault Token

  • In cases where the Vault Server has a supported Auth backend, not YET supported by VaultSharp, you can use the CustomAuthMethodInfo
  • In this approach, you write the delegate logic that gets the token from Vault along with lease renewal info etc.
// Func<Task<CustomAuthMethodInfo>> getCustomAuthMethodInfoAsync = a custom async method to return the vault token.
IAuthMethodInfo authMethod = new CustomAuthMethodInfo("vault-server-auth-method", getCustomAuthMethodInfoAsync);
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

// Once VaultSharp evaluates the delegate, VaultSharp can now provide you with the associated lease info for the Token as well.
// authMethod.ReturnedLoginAuthInfo has all the info including the token and renewal info.

App Id Auth Method (DEPRECATED)

  • Please note that the app-id auth backend has been deprecated by Vault. They recommend us to use the AppRole backend.
  • So VaultSharp doesn't support App Id natively.
  • If you are in dire need of the App Id support, please raise an issue.

MFA (LEGACY/UNSUPPORTED)

  • Please note that this legacy Auth Method is not supported by Vault anymore.
  • Instead Vault Enterprise contains a fully-supported MFA system.
  • It is significantly more complete and flexible and which can be used throughout Vault's API.
  • Please see the System Backend section of the docs for the Enterprise MFA apis.

Force re-fetch of Vault Login

  • Whenever you initialize VaultSharp with an appropriate AuthMethod, VaultSharp fetches the vault token on the first authenticated Vault operation requested by the host app.
  • Once VaultSharp has this token, it never re-fetches the token.
  • This means, when the token expires, Vault calls will start failing.
  • The older way to solve for this is for the host app to keep track of the token's TTL and re-initialize VaultClient. This ensures that VaultSharp will fetch the vault-token again.
  • However, a lot of our clients don't want to mess with the singleton nature of VaultClient.
  • So VaultSharp now supports the ability to set a flag that tells VaultSharp to refetch the vault token during the next Vault operation.
  • As a client, whenever you determine that the token needs to be re-fetched, call this method.
  • It'll make VaultSharp fetch the vault token again before the next operation.
// when it is time to re-fetch the login token, just set this flag.
vaultClient.V1.Auth.ResetVaultToken();

Secrets Engines

  • VaultSharp supports all secrets engines supported by the Vault Service
  • Here is a sample to instantiate the vault client with each of the secrets engine

All of the below examples assume that you have a vault client instance ready. e.g.

// Initialize one of the several auth methods.
IAuthMethodInfo authMethod = new TokenAuthMethodInfo("MY_VAULT_TOKEN");

// Initialize settings. You can also set proxies, custom delegates etc. here.
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

Active Directory Secrets Engine

Retrieving Passwords (offering credentials)
  • This method offers the credential information for a given role.
Secret<ActiveDirectoryCredentials> adCreds = await vaultClient.V1.Secrets.ActiveDirectory.GetCredentialsAsync(role);
string currentPassword = adCreds.Data.CurrentPassword;

AliCloud Secrets Engine

Generate RAM Credentials
  • This endpoint generates dynamic RAM credentials based on the named role.
Secret<AliCloudCredentials> aliCloudCreds = await vaultClient.V1.Secrets.AliCloud.GetCredentialsAsync(role);

string accessKey = aliCloudCreds.Data.AccessKey;
string secretKey = aliCloudCreds.Data.SecretKey;
string securityToken = aliCloudCreds.Data.SecurityToken;
string expiration = aliCloudCreds.Data.Expiration;

AWS Secrets Engine

Configure Root IAM Credential
  • This endpoint configures the root IAM credentials to communicate with AWS.
var configureRootIAMCredentialsModel = new ConfigureRootIAMCredentialsModel
{
   AccessKey = "<>",
   SecretKey = "<>",
   Region = "<>"
};

await vaultClient.V1.Secrets.AWS.ConfigureRootIAMCredentialsAsync(configureRootIAMCredentialsModel);
Read Root IAM Credential
  • This endpoint allows you to read non-secure values that have been configured in the config/root endpoint.
  • In particular, the secret_key parameter is never returned.
Secret<RootIAMCredentialsConfigModel> config = await vaultClient.V1.Secrets.AWS.GetRootIAMCredentialsConfigAsync();
Rotate Root IAM Credential
  • When you have configured Vault with static credentials, you can use this endpoint to have Vault rotate the access key it used.
Secret<RotateRootIAMCredentialsResponseModel> response = await vaultClient.V1.Secrets.AWS.RotateRootIAMCredentialsAsync();

string newAccessKey = response.Data.NewAccessKey;
Configure Lease
  • This endpoint configures lease settings for the AWS secrets engine.
var leaseConfigModel = new AWSLeaseConfigModel
{
   Lease = "36h",
   MaximumLease = "72h"
};

await vaultClient.V1.Secrets.AWS.ConfigureLeaseAsync(leaseConfigModel);
Read Lease
  • This endpoint returns the current lease settings for the AWS secrets engine.
Secret<AWSLeaseConfigModel> lease = await vaultClient.V1.Secrets.AWS.GetLeaseConfigAsync();
Write Role
  • This endpoint creates or updates the role with the given name.
var role = new CreateAWSRoleModel
{
   CredentialType = AWSCredentialsType.federation_token,
   PolicyDocument = "{\"Version\": \"...\"}"
};

await vaultClient.V1.Secrets.AWS.WriteRoleAsync("my-role-name", role);
Read Role
  • This endpoint reads details of one AWS Role.
Secret<AWSRoleModel> role = await vaultClient.V1.Secrets.AWS.ReadRoleAsync(roleName);
List<AWSCredentialsType> credTypes = role.Data.CredentialTypes;
Read All Roles
  • This endpoint reads all the AWS Roles
Secret<ListInfo> roles = await vaultClient.V1.Secrets.AWS.ReadAllRolesAsync();
List<string> names = roles.Data;
Generate IAM Credentials
  • This endpoint generates dynamic IAM credentials based on the named role.
Secret<AWSCredentials> awsCreds = await vaultClient.V1.Secrets.AWS.GetCredentialsAsync(role);

string accessKey = awsCreds.Data.AccessKey;
string secretKey = awsCreds.Data.SecretKey;
string securityToken = awsCreds.Data.SecurityToken;
Generate IAM Credentials with STS
  • This generates a dynamic IAM credential with an STS token based on the named role.
Secret<AWSCredentials> awsCreds = await vaultClient.V1.Secrets.AWS.GenerateSTSCredentialsAsync(role, ttl);

string accessKey = awsCreds.Data.AccessKey;
string secretKey = awsCreds.Data.SecretKey;
string securityToken = awsCreds.Data.SecurityToken;

Azure Secrets Engine

Generate dynamic Azure credentials
  • This endpoint generates a new service principal based on the named role.
Secret<AzureCredentials> azureCredentials = await vaultClient.V1.Secrets.Azure.GetCredentialsAsync(roleName);
string clientId = azureCredentials.Data.ClientId;
string clientSecret = azureCredentials.Data.ClientSecret;

Consul Secrets Engine

  • This endpoint generates a dynamic Consul token based on the given role definition.
// Generate a dynamic Consul credential
Secret<ConsulCredentials> consulCreds = await vaultClient.V1.Secrets.Consul.GetCredentialsAsync(consulRole);
string consulToken = consulCredentials.Data.Token;

Cubbyhole Secrets Engine

Read Secret
  • This endpoint retrieves the secret at the specified location.
Secret<Dictionary<string, object>> secret = await vaultClient.V1.Secrets.Cubbyhole.ReadSecretAsync(secretPath);
Dictionary<string, object> secretValues = secret.Data;
List Secrets
  • This endpoint returns a list of secret entries at the specified location.
  • Folders are suffixed with /. The input must be a folder; list on a file will not return a value.
  • The values themselves are not accessible via this command.
Secret<ListInfo> secret = await vaultClient.V1.Secrets.Cubbyhole.ReadSecretPathsAsync(folderPath);
ListInfo paths = secret.Data;
Create/Update Secret
  • This endpoint stores a secret at the specified location.
var value = new Dictionary<string, object> { { "key1", "val1" }, { "key2", 2 } };
await vaultClient.V1.Secrets.Cubbyhole.WriteSecretAsync(secretPath, value);
Delete Secret
  • This endpoint deletes the secret at the specified location.
await vaultClient.V1.Secrets.Cubbyhole.DeleteSecretAsync(secretPath);

Databases Secrets Engine

Generate dynamic DB credentials
  • This endpoint generates a new set of dynamic credentials based on the named role.
Secret<UsernamePasswordCredentials> dbCreds = await vaultClient.V1.Secrets.Database.GetCredentialsAsync(role);
string username = dbCreds.Data.Username;
string password = dbCreds.Data.Password;
Create, Read and Delete Database Roles (please see next section for static db roles)
  • These endpoints manage the creation, reading and deletion of DB roles.
await vaultClient.V1.Secrets.Database.CreateRoleAsync(roleName, roleRequest);

await vaultClient.V1.Secrets.Database.ReadRoleAsync(roleName);

await vaultClient.V1.Secrets.Database.ReadAllRolesAsync();

await vaultClient.V1.Secrets.Database.DeleteRoleAsync(roleName);
Create, Read and Delete Static Database Roles
  • These endpoints manage the creation, reading and deletion of static DB roles.
await vaultClient.V1.Secrets.Database.CreateStaticRoleAsync(roleName, roleRequest);

await vaultClient.V1.Secrets.Database.ReadStaticRoleAsync(roleName);

await vaultClient.V1.Secrets.Database.ReadAllStaticRolesAsync();

await vaultClient.V1.Secrets.Database.DeleteStaticRoleAsync(roleName);
Generate Static DB credentials
  • This endpoint generates a new set of static credentials based on the named role.
Secret<StaticCredentials> dbCreds = await vaultClient.V1.Secrets.Database.GetStaticCredentialsAsync(role);
Rotate static DB credentials
  • This endpoint rotates the static credentials on demand.
await vaultClient.V1.Secrets.Database.RotateStaticCredentialsAsync(role);

Google Cloud Secrets Engine

Generate Secret (IAM Service Account Creds): OAuth2 Access Token
  • Generates an OAuth2 token with the scopes defined on the roleset. This OAuth access token can be used in GCP API calls
Secret<GoogleCloudOAuth2Token> oauthSecret = await vaultClient.V1.Secrets.GoogleCloud.GetOAuth2TokenAsync(roleset);
string token = oauthSecret.Data.Token;
Generate Secret (IAM Service Account Creds): Service Account Key
  • Generates a service account key.
Secret<GoogleCloudServiceAccountKey> privateKeySecret = await vaultClient.V1.Secrets.GoogleCloud.GenerateServiceAccountKeyAsync(roleset, keyAlgorithm, privateKeyType);
string privateKeyData = privateKeySecret.Data.Base64EncodedPrivateKeyData;

Google Cloud KMS Secrets Engine

Encrypt, Decrypt, ReEncrypt, Sign & Verify
await vaultClient.V1.Secrets.GoogleCloudKMS.EncryptAsync(keyName, requestOptions);
await vaultClient.V1.Secrets.GoogleCloudKMS.DecryptAsync(keyName, requestOptions);
await vaultClient.V1.Secrets.GoogleCloudKMS.ReEncryptAsync(keyName, requestOptions);
await vaultClient.V1.Secrets.GoogleCloudKMS.SignAsync(keyName, requestOptions);
await vaultClient.V1.Secrets.GoogleCloudKMS.VerifyAsync(keyName, requestOptions);

Key Value Secrets Engine

  • VaultSharp supports both v1 and v2 of the Key Value Secrets Engine.
  • Here are examples for both.
Key Value Secrets Engine - V1
Create/Update Secret
  • This endpoint stores a secret at the specified location.
  • If the value does not yet exist, the calling token must have an ACL policy granting the create capability.
  • If the value already exists, the calling token must have an ACL policy granting the update capability.
var value = new Dictionary<string, object> { { "key1", "val1" }, { "key2", 2 } };
var writtenValue = await vaultClient.V1.Secrets.KeyValue.V1.WriteSecretAsync(secretPath, value);
Read Secret
  • Reads the secret at the specified location returning data.
// Use client to read a v1 key-value secret.
Secret<Dictionary<string, object>> kv1Secret = await vaultClient.V1.Secrets.KeyValue.V1.ReadSecretAsync("v1-secret-name");
Dictionary<string, object> dataDictionary = kv1Secret.Data;
List Secrets
  • This endpoint returns a list of key names at the specified location.
  • Folders are suffixed with /. The input must be a folder; list on a file will not return a value.
  • Note that no policy-based filtering is performed on keys; do not encode sensitive information in key names.
  • The values themselves are not accessible via this command.
Secret<ListInfo> secret = await vaultClient.V1.Secrets.KeyValue.V1.ReadSecretPathsAsync(path);
ListInfo paths = secret.Data;
Delete Secret
  • This endpoint deletes the secret at the specified location.
await vaultClient.V1.Secrets.KeyValue.V1.DeleteSecretAsync(secretPath);
Key Value Secrets Engine - V2
Create/Update Secret
  • This endpoint stores a secret at the specified location.
  • If the value does not yet exist, the calling token must have an ACL policy granting the create capability.
  • If the value already exists, the calling token must have an ACL policy granting the update capability.
var value = new Dictionary<string, object> { { "key1", "val1" }, { "key2", 2 } };
var writtenValue = await vaultClient.V1.Secrets.KeyValue.V2.WriteSecretAsync(secretPath, value, checkAndSet);
Patch Secret
  • You can also patch a secret that already exists.
  • Patching means, replacing/adding new key-values to an existing map of secrets.
var valueToBeCombined = new Dictionary<string, object> { { "key2", "new-val2" }, { "key3", "val3" } };

var patchSecretDataRequest = new PatchSecretDataRequest() { Data = valueToBeCombined };

var metadata = await vaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(secretPath, valueToBeCombined);
Read Secret
  • Reads the secret at the specified location returning data and metadata.
// Use client to read a v2 key-value secret.

// Very important to provide mountpath and secret name as two separate parameters. Don't provide a single combined string.
// Please use named parameters for 100% clarity of code. (the method also takes version and wrapTimeToLive as params)

Secret<Dictionary<string, object>> kv2Secret = await vaultClient.V1.Secrets.KeyValue.V2
                               .ReadSecretAsync(path: "v2-secret-name", mountPoint: "mountPointIfNotDefault");

Dictionary<string, object> dataDictionary = kv2Secret.Data;
Write Metadata
  • Creates or updates the metadata of a secret at the specified location in the K/V v2 secrets engine.
var writeCustomMetadataRequest = new CustomMetadataRequest
            {
                CustomMetadata = new Dictionary<string, string>
                {
                    { "owner", "system"},
                    { "expired_in", "20331010"}
                }
            };

 await _authenticatedVaultClient.V1.Secrets.KeyValue.V2.WriteSecretMetadataAsync(path, writeCustomMetadataRequest, mountPoint: kv2SecretsEngine.Path);
       
Patch Metadata
  • Patch the metadata of a secret at specified location in the K/V v2 secrets engine.
 var patchCustomMetadataRequest = new CustomMetadataRequest
            {
                CustomMetadata = new Dictionary<string, string>
                {
                    { "locale", "EN"},
                    { "expired_in", "20341010"}
                }
            };

 await _authenticatedVaultClient.V1.Secrets.KeyValue.V2.PatchSecretMetadataAsync(path, patchCustomMetadataRequest, mountPoint: kv2SecretsEngine.Path)
            
Read Metadata
  • Reads the secret metadata at the specified location returning.
Secret<FullSecretMetadata> kv2SecretMetadata = await vaultClient.V1.Secrets.KeyValue.V2.ReadSecretMetadataAsync("v1-secret-name");
List Secrets
  • This endpoint returns a list of key names at the specified location.
  • Folders are suffixed with /. The input must be a folder; list on a file will not return a value.
  • Note that no policy-based filtering is performed on keys; do not encode sensitive information in key names.
  • The values themselves are not accessible via this command.
Secret<ListInfo> secret = await vaultClient.V1.Secrets.KeyValue.V2.ReadSecretPathsAsync(path);
ListInfo paths = secret.Data;
Read Secret Subkeys
  • This endpoint provides the subkeys within a secret entry that exists at the requested path.
  • The secret entry at this path will be retrieved and stripped of all data by replacing underlying values of leaf keys (i.e. non-map keys or map keys with no underlying subkeys) with null.
Secret<SecretSubkeysInfo> secret = await vaultClient.V1.Secrets.KeyValue.V2.ReadSecretSubkeysAsync(path)
SecretSubkeysInfo subkeys = secret.Data;
Delete Secret
  • This endpoint issues a soft delete of the secret's latest version at the specified location.
  • This marks the version as deleted and will stop it from being returned from reads, but the underlying data will not be removed.
  • A delete can be undone using the undelete method.
await vaultClient.V1.Secrets.KeyValue.V2.DeleteSecretAsync(secretPath);
Delete Secret Versions
  • This endpoint issues a soft delete of the specified versions of the secret.
  • This marks the versions as deleted and will stop them from being returned from reads, but the underlying data will not be removed.
  • A delete can be undone using the undelete method.
await vaultClient.V1.Secrets.KeyValue.V2.DeleteSecretVersionsAsync(secretPath, versions);
Undelete Secret Versions
  • Undeletes the data for the provided version and path in the key-value store.
  • This restores the data, allowing it to be returned on get requests.
await vaultClient.V1.Secrets.KeyValue.V2.UndeleteSecretVersionsAsync(secretPath, versions);
Destroy Secret
  • This endpoint destroys the secret at the specified location for the given versions.
await vaultClient.V1.Secrets.KeyValue.V2.DestroySecretAsync(secretPath, new List<int> { 1, 2 });
Delete Secret Metadata and all versions
  • This endpoint permanently deletes the key metadata and all version data for the specified key.
  • All version history will be removed.
await vaultClient.V1.Secrets.KeyValue.V2.DeleteMetadataAsync(secretPath);

Identity Secrets Engine

Generate a Signed ID Token
  • Use this endpoint to generate a signed ID (OIDC) token.
Secret<IdentityToken> token = await vaultClient.V1.Secrets.Identity.GetTokenAsync(roleName);
string clientId = token.Data.ClientId;
string token = token.Data.Token;
Introspect a signed ID Token
  • This endpoint can verify the authenticity and active state of a signed ID token.
Secret<bool> activeResponse = await vaultClient.V1.Secrets.Identity.IntrospectTokenAsync(token, clientId);
bool active = activeResponse.Data;

KeyManagement Secrets Engine (Enterprise)

Read Key
  • Returns information about a named key.
  • The keys object will hold information regarding each key version.
  • Different information will be returned depending on the key type.
  • For example, an asymmetric key will return its public key in a standard format for the type.
Secret<KeyManagementKey> keyManagementKey = await vaultClient.V1.Secrets.Enterprise.KeyManagement.ReadKeyAsync(keyName);
var keys = keyManagementKey.Data.Keys;
Read Key in KMS
  • Returns information about a named key in KMS.
Secret<KeyManagementKMSKey> keyManagementKMSKey = await vaultClient.V1.Secrets.Enterprise.KeyManagement.ReadKeyInKMSAsync(kmsName, keyName);
var name = keyManagementKMSKey.Data.Name;
var purpose = keyManagementKMSKey.Data.Purpose;
var protection = keyManagementKMSKey.Data.Protection;

KMIP Secrets Engine (Enterprise)

Generate dynamic credentials
  • Create a new client certificate tied to the given role and scope.
Secret<KMIPCredentials> kmipCredentials = await vaultClient.V1.Secrets.Enterprise.KMIP.GetCredentialsAsync(scopeName, roleName);
string certificateContent = kmipCredentials.Data.CertificateContent;
string privateKeyContent = kmipCredentials.Data.PrivateKeyContent;

Kubernetes Secrets Engine

Generate dynamic credentials
Secret<KubernetesCredentials> kubernetesCredentials = await vaultClient.V1.Secrets.Kubernetes.GetCredentialsAsync(ksRoleName, ksNamespace);
string serviceAccountToken = kubernetesCredentials.Data.ServiceAccountToken;

MongoDBAtlas Secrets Engine

Generate dynamic credentials
  • Generates a dynamic MongoDBAtlas creds based on the given role definition.
Secret<MongoDBAtlasCredentials> creds = await vaultClient.V1.Secrets.MongoDBAtlas.GetCredentialsAsync(name);
string privateKey = creds.Data.PrivateKey;
string publicKey = creds.Data.PublicKey;

Nomad Secrets Engine

Generate dynamic credentials
  • Generates a dynamic Nomad token based on the given role definition.
Secret<NomadCredentials> nomadCredentials = await vaultClient.V1.Secrets.Nomad.GetCredentialsAsync(roleName);
string accessorId = nomadCredentials.Data.AccessorId;
string secretId = nomadCredentials.Data.SecretId;

OpenLDAP Secrets Engine

Generate static credentials
  • This endpoint offers the credential information for a given static-role.
Secret<StaticCredentials> credentials = await vaultClient.V1.Secrets.OpenLDAP.GetStaticCredentialsAsync(roleName);
string username = credentials.Data.Username;
string password = credentials.Data.Password;

PKI (Certificates) Secrets Engine

Generate credentials
var certificateCredentialsRequestOptions = new CertificateCredentialsRequestOptions { // initialize };
Secret<CertificateCredentials> certSecret = await vaultClient.V1.Secrets.PKI.GetCredentialsAsync(pkiRoleName, certificateCredentialsRequestOptions);

string privateKeyContent = certSecret.Data.PrivateKeyContent;
Sign Certificate
var signCertificateRequestOptions = new SignCertificateRequestOptions { // initialize };
Secret<SignedCertificateData> certSecret = await vaultClient.V1.Secrets.PKI.SignCertificateAsync(pkiRoleName, signCertificateRequestOptions);

string certificateContent = certSecret.Data.CertificateContent;
Revoke Certificate
Secret<RevokeCertificateResponse> revoke = await vaultClient.V1.Secrets.PKI.RevokeCertificateAsync(serialNumber);
long revocationTime = revoke.Data.RevocationTime;
Tidy up Certificate Storage
var request = new CertificateTidyRequest { TidyCertStore = false, TidyRevokedCerts = true };
await vaultClient.V1.Secrets.PKI.TidyAsync(request);
Configure Automatic Tidying up of Certificate Storage
var request = new CertificateAutoTidyRequest { TidyCertStore = false, TidyRevokedCerts = true };
await vaultClient.V1.Secrets.PKI.AutoTidyAsync(request);
Get Status of Certificate Tidying Process
var tidyStatus = await vaultClient.V1.Secrets.PKI.GetTidyStatusAsync();
CertificateTidyState state = tidyStatus.Data.TidyState;
Cancel Certificate Tidying Process
var tidyStatus = await vaultClient.V1.Secrets.PKI.CancelTidyAsync();
CertificateTidyState state = tidyStatus.Data.TidyState;
List certificates
  • This endpoint retrieves a list of certificate keys (serial numbers)
var keys = await vaultClient.V1.Secrets.PKI.ListCertificatesAsync(mountpoint);
Assert.IsTrue(keys.Any(k => k == "17:67:16:b0:b9:45:58:c0:3a:29:e3:cb:d6:98:33:7a:a6:3b:66:c1"));
List revoked certificates
  • This endpoint retrieves a list of revoked certificate keys (serial numbers)
var keys = await vaultClient.V1.Secrets.PKI.ListRevokedCertificatesAsync(mountpoint);
Assert.IsTrue(keys.Any(k => k == "17:67:16:b0:b9:45:58:c0:3a:29:e3:cb:d6:98:33:7a:a6:3b:66:c1"));
Read certificate
  • This endpoint retrieves a certificate by key (serial number)
  • The certificate format is always PEM.
  • This is an unauthenticated endpoint.
var cert = await vaultClient.V1.Secrets.PKI.ReadCertificateAsync("17:67:16:b0:b9:45:58:c0:3a:29:e3:cb:d6:98:33:7a:a6:3b:66:c1", mountpoint);
Assert.NotNull(cert.CertificateContent);
Read CA Certificate
  • This endpoint retrieves the CA certificate in raw DER-encoded form.
  • The CA certificate can be returned in PEM or DER format.
  • This is an unauthenticated endpoint.
var caCert = await vaultClient.V1.Secrets.PKI.ReadCACertificateAsync(CertificateFormat.pem, mountpoint);
Assert.NotNull(caCert.CertificateContent);

RabbitMQ Secrets Engine

Generate dynamic DB credentials
  • This endpoint generates a new set of dynamic credentials based on the named role.
Secret<UsernamePasswordCredentials> secret = await vaultClient.V1.Secrets.RabbitMQ.GetCredentialsAsync(roleName);
string username = secret.Data.Username;
string password = secret.Data.Password;
Create, Read and Delete RabbitMQ Roles
  • These endpoints manage the creation, reading and deletion of RabbitMQ roles.
var virtualHostName = "/";
var virtualHostPermission = new { write = ".*", read = ".*" };
var virtualHosts = new Dictionary<string, object>() { { virtualHostName, virtualHostPermission } };
var virtualHostsJson = JsonSerializer.Serialize(virtualHosts);
var role = new RabbitMQRole() { VHosts = virtualHostsJson }        
await vaultClient.V1.Secrets.RabbitMQ.CreateRoleAsync(roleName, role, mountPoint);

await vaultClient.V1.Secrets.RabbitMQ.ReadRoleAsync(roleName, mountPoint);

await vaultClient.V1.Secrets.RabbitMQ.DeleteRoleAsync(roleName, mountPoint);

SSH Secrets Engine

Generate SSH credentials
  • This endpoint creates credentials for a specific username and IP with the parameters defined in the given role.
Secret<SSHCredentials> sshCreds = await vaultClient.V1.Secrets.SSH.GetCredentialsAsync(role, ipAddress, username);
string sshKey = sshCreds.Data.Key;
SSH key signing
  • This endpoint signs an SSH public key based on the supplied parameters, subject to the restrictions contained in the role named in the endpoint.
SignKeyRequest request = new SignKeyRequest { PublicKey = "ipsem" };
Secret<SignedKeyResponse> signedKey = await vaultClient.V1.Secrets.SSH.SignKeyAsync(roleName, request);
string signedKey = signedKey.Data.SignedKey;

Terraform Cloud Secrets Engine

Generate credentials
  • This endpoint returns a Terraform Cloud token based on the given role definition.
  • For Organization and Team roles, the same API token is returned until the token is rotated with rotate-role.
  • For User roles, a new token is generated with each request.
Secret<TerraformCredentials> secret = await vaultClient.V1.Secrets.Terraform.GetCredentialsAsync(role);
string token = secret.Data.Token;
string tokenId = secret.Data.TokenId;

TOTP Secrets Engine

Generate Code

This endpoint generates a new time-based one-time use password based on the named key.

Secret<TOTPCode> totpSecret = await vaultClient.V1.Secrets.TOTP.GetCodeAsync(keyName);
string code = totpSecret.Data.Code;
Validate Code

This endpoint validates a time-based one-time use password generated from the named key.

Secret<TOTPCodeValidity> totpValidity = await vaultClient.V1.Secrets.TOTP.ValidateCodeAsync(keyName, code);
bool valid = totpValidity.Data.Valid;
Create TOTP Key

This endpoint creates or updates a key definition. You can create both Vault based or non-vault based keys.

TOTPCreateKeyRequest request = new TOTPCreateKeyRequest
{
 Issuer = "Google",
 AccountName = "[email protected]",
 KeyGenerationOption = new TOTPVaultBasedKeyGeneration { // specific stuff }
 // for non-vault based, use new TOTPNonVaultBasedKeyGeneration { // specific stuff }
};

Secret<TOTPCreateKeyResponse> response = await vaultClient.V1.Secrets.TOTP.CreateKeyAsync(keyName, request);
var barcode = response.Data.Barcode;
Read Key

This endpoint queries the key definition.

Secret<TOTPKey> key = await vaultClient.V1.Secrets.TOTP.ReadKeyAsync(keyName);
Read all Keys

This endpoint returns a list of available keys. Only the key names are returned, not any values.

Secret<ListInfo> keys = await vaultClient.V1.Secrets.TOTP.ReadAllKeysAsync();
Delete Key

This endpoint deletes the key definition.

await vaultClient.V1.Secrets.TOTP.DeleteKeyAsync(keyName);

Transform Secrets Engine (Enterprise)

Encode Method
Encode Single Item
var encodeOptions = new EncodeRequestOptions { Value = "ipsem" };
Secret<EncodedResponse> response = await _authenticatedVaultClient.V1.Secrets.Enterprise.Transform.EncodeAsync(roleName, encodeOptions);
response.Data.EncodedValue;
Encode Batched Items
var encodeOptions = new EncodeRequestOptions 
{ 
  BatchItems = new List<EncodingItem> { new EncodingItem { Value = "ipsem1" }, new EncodingItem { Value = "ipsem2" } }
};

Secret<EncodedResponse> response = await _authenticatedVaultClient.V1.Secrets.Enterprise.Transform.EncodeAsync(roleName, encodeOptions);
response.Data.EncodedItems;
Decode Method
Decode Single Item
var decodeOptions = new DecodeRequestOptions { Value = "ipsem" };
Secret<DecodedResponse> response = await _authenticatedVaultClient.V1.Secrets.Enterprise.Transform.DecodeAsync(roleName, decodeOptions);
response.Data.DecodedValue;
Decode Batched Item
var decodeOptions = new DecodeRequestOptions 
{ 
  BatchItems = new List<DecodingItem> { new DecodingItem { Value = "ipsem1" }, new DecodingItem { Value = "ipsem2" } }
};

Secret<DecodedResponse> response = await _authenticatedVaultClient.V1.Secrets.Enterprise.Transform.DecodeAsync(roleName, decodeOptions);
response.Data.DecodedItems;

Transit Secrets Engine

Encrypt Method
Encrypt Single Item
var keyName = "test_key";

var context = "context1";
var plainText = "raja";
var encodedPlainText = Convert.ToBase64String(Encoding.UTF8.GetBytes(plainText));
var encodedContext = Convert.ToBase64String(Encoding.UTF8.GetBytes(context));

var encryptOptions = new EncryptRequestOptions
{
    Base64EncodedPlainText = encodedPlainText,
    Base64EncodedContext = encodedContext,
};

Secret<EncryptionResponse> encryptionResponse = await _authenticatedVaultClient.V1.Secrets.Transit.EncryptAsync(keyName, encryptOptions);
string cipherText = encryptionResponse.Data.CipherText;
Encrypt Batched Items
var encryptOptions = new EncryptRequestOptions
{
    BatchedEncryptionItems = new List<EncryptionItem>
    {
        new EncryptionItem { Base64EncodedContext = encodedContext1, Base64EncodedPlainText = encodedPlainText1 },
        new EncryptionItem { Base64EncodedContext = encodedContext2, Base64EncodedPlainText = encodedPlainText2 },
        new EncryptionItem { Base64EncodedContext = encodedContext3, Base64EncodedPlainText = encodedPlainText3 },
    }
};

Secret<EncryptionResponse> encryptionResponse = await _authenticatedVaultClient.V1.Secrets.Transit.EncryptAsync(keyName, encryptOptions);
string firstCipherText = encryptionResponse.Data.BatchedResults.First().CipherText;
Decrypt Method
Decrypt Single Item
var decryptOptions = new DecryptRequestOptions
{
    CipherText = cipherText,
    Base64EncodedContext = encodedContext,
};

Secret<DecryptionResponse> decryptionResponse = await _authenticatedVaultClient.V1.Secrets.Transit.DecryptAsync(keyName, decryptOptions);
string encodedPlainText = decryptionResponse.Data.Base64EncodedPlainText;
Decrypt Batched Item
var decryptOptions = new DecryptRequestOptions
{
    BatchedDecryptionItems = new List<DecryptionItem>
    {
        new DecryptionItem { Base64EncodedContext = encodedContext1, CipherText = cipherText1 },
        new DecryptionItem { Base64EncodedContext = encodedContext2, CipherText = cipherText2 },
        new DecryptionItem { Base64EncodedContext = encodedContext3, CipherText = cipherText3 },
    }
};

Secret<DecryptionResponse> decryptionResponse = await _authenticatedVaultClient.V1.Secrets.Transit.DecryptAsync(keyName, decryptOptions);
string firstEncodedPlainText = decryptionResponse.Data.BatchedResults.First().Base64EncodedPlainText;
Generate Data Key
// Generate Data Key
var dataKeyOptions = new DataKeyRequestOptions
{
    Base64EncodedContext = encodedContext,
    Nonce = nonce
};

Secret<DataKeyResponse> dataKeyResponse = await _authenticatedVaultClient.V1.Secrets.Transit.GenerateDataKeyAsync(keyType, keyName, dataKeyOptions);

var encodedDataKeyPlainText = dataKeyResponse.Data.Base64EncodedPlainText;
var dataKeyCipherText = dataKeyResponse.Data.Base64EncodedCipherText;
Read all Encryption Keys
var allKeys = await _authenticatedVaultClient.V1.Secrets.Transit.ReadAllEncryptionKeysAsync();
Trim Key
var trimOptions = new TrimKeyRequestOptions { MinimumAvailableVersion = 2 };

await _authenticatedVaultClient.V1.Secrets.Transit.TrimKeyAsync(keyName, trimOptions);
Export Key
string version = "latest";

Secret<ExportedKeyInfo> exportedKeyInfo = await _authenticatedVaultClient.V1.Secrets.Transit.ExportKeyAsync(TransitKeyCategory.encryption_key, keyName, version);
Backup Key
  • In order for this call to work, the key must have been created with allow_plaintext_backup set to true.
var backup = await _authenticatedVaultClient.V1.Secrets.Transit.BackupKeyAsync(keyName);
string backupData = backup.Data.BackupData;
Restore Key
var restoreData = new RestoreKeyRequestOptions 
{
    BackupData = previouslyBackedUpData, 
    Force = true 
};
await _authenticatedVaultClient.V1.Secrets.Transit.RestoreKeyAsync(keyName, restoreData);
Generate Random Bytes
var byteCountRequested = 64;
var randomOpts = new RandomBytesRequestOptions 
{
    Format = OutputEncodingFormat.base64
};
var base64Response = await _authenticatedVaultClient.V1.Secrets.Transit.GenerateRandomBytesAsync(byteCountRequested, randomOpts);
var base64EncodedRandomData = base64Response.Data.EncodedRandomBytes;
Hash Data String
var hashOpts = new HashRequestOptions
{
    Format = OutputEncodingFormat.base64, 
    Base64EncodedInput = encodedStringToHash
};
var hashResponse = await _authenticatedVaultClient.V1.Secrets.Transit.HashDataAsync(HashAlgorithm.sha2_256, hashOpts);
var hashString = hashResponse.Data.HashSum;
Generate HMAC Single Item
var hmacOptions = new HmacRequestOptions 
{
    Base64EncodedInput = encodedPlainText
};
var hmacResponse = await _authenticatedVaultClient.V1.Secrets.Transit.GenerateHmacAsync(HashAlgorithm.sha2_256, keyName, hmacOptions);
Generate HMAC Batch Item
var hmacList = new HmacRequestOptions
{
    BatchInput = new List<HmacSingleInput>
    {
        new HmacSingleInput {Base64EncodedInput = encodedText},
        new HmacSingleInput {Base64EncodedInput = encodedText2},
        new HmacSingleInput {Base64EncodedInput = encodedText3}
    }
};
var hmacResponse = await _authenticatedVaultClient.V1.Secrets.Transit.GenerateHmacAsync(HashAlgorithm.sha2_256, keyName, hmacList);
Sign Single Item
var signOptions = new SignRequestOptions
{
    Base64EncodedInput = encodedText,
    SignatureAlgorithm = SignatureAlgorithm.Pkcs1v15,
    MarshalingAlgorithm = MarshalingAlgorithm.Asn1
};
var signResponse = await _authenticatedVaultClient.V1.Secrets.Transit.SignDataAsync(HashAlgorithm.sha2_256, keyName, signOptions);
Sign Batched Item
 var signList = new SignRequestOptions
{
    BatchInput = new List<SignSingleInput>
    {
        new SignSingleInput {Base64EncodedInput = encodedText},
        new SignSingleInput {Base64EncodedInput = encodedText2},
        new SignSingleInput {Base64EncodedInput = encodedText3}
    },
    SignatureAlgorithm = SignatureAlgorithm.Pkcs1v15,
    MarshalingAlgorithm = MarshalingAlgorithm.Asn1
};
var signResponse = await _authenticatedVaultClient.V1.Secrets.Transit.SignDataAsync(HashAlgorithm.sha2_256, keyName, signList);
Verify HMAC Single Item
var verifyOptions = new VerifyRequestOptions
{
    Base64EncodedInput = base64Input,
    Hmac = hmacToVerify,
    MarshalingAlgorithm = MarshalingAlgorithm.Asn1
};
var verifyResponse = await _authenticatedVaultClient.V1.Secrets.Transit.VerifySignedDataAsync(HashAlgorithm.sha2_256, keyName, verifyOptions);
var isValid = verifyResponse.Data.Valid;
Verify Signature Single Item
var verifyOptions = new VerifyRequestOptions
{
    Base64EncodedInput = base64Input,
    Signature = signResponse.Data.Signature,
    SignatureAlgorithm = SignatureAlgorithm.Pkcs1v15,
    MarshalingAlgorithm = MarshalingAlgorithm.Asn1
};
var verifyResponse = await _authenticatedVaultClient.V1.Secrets.Transit.VerifySignedDataAsync(HashAlgorithm.sha2_256, keyname, verifyOptions);
var isValid = verifyResponse.Data.Valid;
Read Transit Cache Configuration
var cacheResult = await _authenticatedVaultClient.V1.Secrets.Transit.ReadCacheConfigAsync();
var cacheSize = cacheResult.Data.Size;
Configure Cache
  • Configuration changes will not be applied until the transit plugin is reloaded which can be achieved using the /sys/plugins/reload/backend endpoint.
var cacheOptions = new CacheConfigRequestOptions 
{
    Size = cacheResult.Data.Size + 1 
};
await transit.SetCacheConfigAsync(cacheOptions);

System Backend

  • The system backend is a default backend in Vault that is mounted at the /sys endpoint.
  • This endpoint cannot be disabled or moved, and is used to configure Vault and interact with many of Vault's internal features.

VaultSharp already supports several of the System backend features.

vaultClient.V1.System.<method> // The method you are looking for.

Can I inject my own HttpClient into VaultSharp?

  • Yes you can.
  • The VaultClientSettings object takes a MyHttpClientProviderFunc delegate that can be as follows.
  • Don't worry about setting any vault specific URL, timeout etc. on this http client. VaultSharp will do that.
var settings = new VaultClientSettings("http://localhost:8200", authMethodInfo)
           {
               Namespace = "mynamespace",
               MyHttpClientProviderFunc = handler => new HttpClient(handler)
           };

What is the deal with the Versioning of VaultSharp?

  • This library is written for Hashicorp's Vault Service
  • The Vault service is evolving constantly and the Hashicorp team is rapidly working on it.
  • Because this client library is intended to facilititate the Vault Service operations, this library makes it easier for its consumers to relate to the Vault service it supports.
  • Hence a version of 0.11.x denotes that this library will support the Vault 0.11.x Service Apis.
  • Tomorrow when Vault Service gets upgraded to x.0.0, this library will be modified accordingly and versioned as x.0.0
  • VaultSharp starts at e.g. 2.3.0 matching the Vault Server exactly, and then can go 2.3.0001, 2.3.0002 etc. for bug fixes etc. within 2.3.0 of Vault.
  • Another thing to note is that, empirically, VaultSharp and Vault have been amazingly compatible even with great versioning differences. Kudos to the Vault team.

Can I use it in my PowerShell Automation?

  • Absolutely. VaultSharp is a .NET Library.
  • This means, apart from using it in your C#, VB.NET, J#.NET and any .NET application, you can use it in PowerShell automation as well.
  • Load up the DLL in your PowerShell code and execute the methods. PowerShell can totally work with .NET Dlls.

All the methods are async. How do I use them synchronously?

  • The methods are async as the defacto implementation. The recommended usage.
  • However, there are innumerable scenarios where you would continue to want to use it synchronously.
  • For all those cases, there are various options available to you.
  • There is a lot of discussion around the right usage, avoiding deadlocks etc.
  • This library allows you to set the 'continueAsyncTasksOnCapturedContext' option when you initialize the client.
  • It is an optional parameter and defaults to 'false'
  • Setting it to false, allows you to access the .Result property of the task with reduced/zero deadlock issues.
  • There are other ways as well to invoke it synchronously, and I leave it to the users of the library. (Task.Run etc.)
  • But please note that as much as possible, use it in an async manner.

In Conclusion

Happy Coding folks!

vaultsharp's People

Contributors

annerajb avatar anthonylangsworth avatar brentdp avatar bymse avatar codecooper avatar dependabot[bot] avatar digitaldirk avatar dimedroll2211 avatar exavian avatar friedkiwi avatar ginja avatar gitter-badger avatar hoerup avatar icanhasjonas avatar irvingd avatar jcpreston26 avatar konidev20 avatar marusyk avatar mcpride avatar mrzoidberg avatar niventc avatar rafaelmontegordofelix avatar rajanadar avatar seif avatar sj-lt avatar thepill avatar zitcomdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vaultsharp's Issues

Write to KV v1 secrets engine?

Greetings..

I'm experimenting with the library and noticing that it seems like the only place I've found with any secrets engine, seems to be calling WriteAsync on the cubbyhole secrets engine. If I attempt to get intellisense with the v1 kv secrets engine, there are only two methods, both of which are read.

Am I missing something?

Refactor client usage to make use of extension methods for strongly-typed access to backends

Thank you for this useful client!

I wanted to open this up to discussion -- how would you feel about refactoring the client library so that the main client entry point (the IVaultClient interface and implementation(s)) gets reduced to a slim, basic interface to the general-purpose Vault primitives (reading, writing, admin), and all of the strongly-typed methods get re-implemented as extension methods?

This way the interface becomes cleaner and user only needs to import the backend-specific namespaces that they care about, which minimally extends the client for just the types specific to those backends.

How to write a TOTP ?

Hello i would like to store a new a TOTP, is it possible with this library ?

thanks

having some syntax issues creating a web method.

Hello, i've been trying to create a web method to pull account configuration from our vault configuration.

This is a sample secret
$ vault read VSMapi/auth
Key Value
lease_duration 2592000
account $[email protected]
dn DC=auth,DC=hpicorp,DC=net
domain auth.hpicorp.net
path OU=SRPA,OU=Groups,OU=Enclave,DC=auth,DC=hpicorp,DC=net

my C# code

how i Instantiate the object

            IVaultClient administrativeVaultClient = VaultClientFactory.CreateVaultClient(new Uri("http://0.0.0.0:8200"), 
                new VaultSharp.Backends.Authentication.Models.Token.TokenAuthenticationInfo(token: "root token"));

This is the web method
public string TestReadVault(string path)
{

           ArrayList data;

           var secret = administrativeVaultClient.ReadSecretAsync(path);
           data = secret.Data; // this is the original dictionary back.

           string result = string.Join(",", data.ToArray());

           return result;

        }

I am getting the error on the data = secret.Data

It doesn't like the .Data

Also I am a perl guy C# isn't my friend. My goal is a proof a concept if we can pull the domain configurations for our .NET web service from the VAULT. If I can get this working i will switch it from the root token to an application role token. I'm just trying to see if this will work for us at all. Any guidance or help would be much appreciated.

'System.Threading.Tasks.Task<VaultSharp.Backends.System.Models.Secret<System.Collections.Generic.Dictionary<string,object>>>' does not contain a definition for 'Data' and no extension method 'Data' accepting a first argument of type 'System.Threading.Tasks.Task<VaultSharp.Backends.System.Models.Secret<System.Collections.Generic.Dictionary<string,object>>>' could be found (are you missing a using directive or an assembly reference?) C:\data\vsm_sandbox\VSM\home\vsm_win\VSMapi_csharp\VSMapiCore\VSMapiCore\VSMapiCore.cs 128 30 VSMapiCore

DataAccessManager is not available to CustomAuthenticationProvider

I need Kubernetes authentication and it doesn't look like VaultSharp supports it yet. So, I thought of using CustomAuthenticationInfo and pass in a delegate. The problem is the delegate has no access to HttpDataAccessManager and I can't create it because it's internal class. Can you make HttpDataAccessManager available to the delegate?

So,

  1. the delegate definition should be:
    Func<IDataAccessManager, Task<string>> authenticationTokenAsyncDelegate

2.CustomAuthenticationProvider constructor should have a dependency on HttpDataAccessManager and pass it to the delegate when invoking it.

Constructor
public CustomAuthenticationProvider(CustomAuthenticationInfo customAuthenticationInfo, IDataAccessManager dataAccessManager, bool continueAsyncTasksOnCapturedContext = false)

GetTokenAsync
var token = await _customAuthenticationInfo.AuthenticationTokenAsyncDelegate(_dataAccessManager).ConfigureAwait(_continueAsyncTasksOnCapturedContext);

3.AuthenticationProviderFactory should create and pass the DataAccessManager to CustomAuthenticationProvider

return new CustomAuthenticationProvider(customAuthenticationInfo, new HttpDataAccessManager(baseAddress, serviceTimeout: serviceTimeout, postHttpClientInitializeAction: postHttpClientInitializeAction), continueAsyncTasksOnCapturedContext);

No way to control proxy settings in client

Hi, thanks for an awesome library! Unfortunately, I can't use it in my environment as we need to specifically disable the proxy to access our Vault server, but it looks like there is no way to control the proxy settings of the HttpClient used by the HttpDataAccessManager. And since VaultClient is internal, there is no easy way to craft our own IDataAccessManager either.

Is there any possibility we will see some way of controlling the IDataAccessManager that our VaultClient uses?

Default Microsoft SQL port

The MicrosoftSqlConfigureConnectionAsync seem to default to the default SQL port of 1433. Using this connection string:
"server=127.0.0.1;port=1402;user id=sa.....
I get this error:
Unable to open tcp connection with host localhost:1433

I've tried a few different versions of the connection string but always the same error.

Token Renewal

Does VaultSharp have any means of monitoring the TTL of a token, and renewing the token before the TTL expires? I did not see that in the documentation, although I may have missed it.

AppRole Token Info

Hi, very nice library. Thanks for all your work.

I am working with AppRoles right now and trying to retrieve the current token's lease duration and lifetime so I can schedule a renew. I have tried the following, but nothing returns any of the required information.

`
IAuthenticationInfo appRoleAuthenticationInfo = new AppRoleAuthenticationInfo(roleID, secretID);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(x, appRoleAuthenticationInfo);

        var xx = vaultClient.GetCallingTokenInfoAsync();
        var yy = vaultClient.GetTokenRoleInfoAsync("abc-role");
        var zz = vaultClient.GetTokenRoleInfoAsync("def-role");
        
        var z1 = vaultClient.AppRoleAuthenticationGetRolesAsync();`

The variable xx has the following in it after the call.

  •   xx	Id = 21, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"	System.Threading.Tasks.Task<VaultSharp.Backends.System.Models.Secret<VaultSharp.Backends.Authentication.Models.Token.CallingTokenInfo>>
    

It seems from another prior issue that this should be returning a data variable and a bunch of other information...

Thanks for your assistance.

Add support for .NET Standard 1.x

Currently VaultSharp 0.10.4000 is .NET standard 2.0 which cannot support .NET Framework 4.5
Reduce the .NET Standard support to support older .NET framework versions.

Use vault with TLS enabled

Hi rajanadar,
I have vault on remote server and vault TLS is enable. So when I want communicate with vault i need apply certificate. However in vault sharp i cannot find tool how i say it 'use this certificate'. I'm beginner with vault and with SSL comunication so it's possible that I forgot something.

Thank you

Strongly name the release builds

Hi, would it be possible to sign the assembly with a strong name?
We have internal guidelines in the company that our assemblies need to be signed which also requires all referenced assemblies to have a strong name.

Exception Message in C# Code : 404 NotFound. {"errors":[]} USING AppRoleAuthentication

Hi I am receiving 404 NotFound. {"errors":[]} while using AppRoleAutherntication backend, please find the info below. I am passing valide approle id and secret id. I have tried this with multiple policy options its not working. Let me know if anywhere i am doing it worngly.

I am running this against my local vault installation

Setting Vault Dev Server

#Setting VAULT_ADDR
set VAULT_ADDR=http://127.0.0.1:8200

vault secrets disable secret
vault secrets enable -version=1 -path=secret kv

#Enable AppRole auth method
vault auth enable approle

#Create new policy [jenkins]
vault policy write jenkins "C:\Manager\Suming\2018\App1 Cloud Migration\Vault Policies\jenkins-pol.hcl"

#Create a new AppRole [jenkins]
vault write auth/approle/role/jenkins secret_id_ttl=10m token_num_uses=10 token_ttl=20m token_max_ttl=30m secret_id_num_uses=40

#Attach policy [jenkins] to [jenkins] AppRole
vault write auth/approle/role/jenkins policies="jenkins"

#Read the [jenkins] AppRole to verify if [jenkins] policy is attached
vault read auth/approle/role/jenkins

#Get Role ID for [jenkins] approle
vault read auth/approle/role/jenkins/role-id

#Get Secret ID for [jenkins] approle
vault write -f auth/approle/role/jenkins/secret-id

#Creating Secret [TestKey=TestValue] at secret/aws/us-east-1/cd/servicing/sandbox
vault kv put secret/aws/us-east-1/rcd/servicing/sandbox TestKey=TestValue

Vault Policy : jenkins-pol.hcl (just for testing, not relation to Jenkins at all)

path "secret/*" {
capabilities = ["create","read"]
}

path "auth/approle/login" {
capabilities = [ "create", "read" ]
}

path "secret/aws/us-east-1/cd/servicing/sandbox/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}

path "sys/auth/approle" {
capabilities = [ "create", "read", "update", "delete", "sudo" ]
}

path "sys/auth/approle/*" {
capabilities = [ "create", "read", "update", "delete" ]
}

path "auth/approle/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}

path "sys/policy/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}

Exception Message in C# Code : 404 NotFound. {"errors":[]}

Code

try
{
secret =
VaultClient
.ReadSecretAsync(fullSecretPath)
.GetAwaiter()
.GetResult();
}
catch(Exception exception)
{
throw
new InvalidOperationException
(
string.Format
(
CultureInfo.InvariantCulture,
"Unable to read secret {0} from vault store",
fullSecretPath
), 
exception
);
}
SecretCache.Add(fullSecretPath, secret);

Stack Trace
at VaultSharp.DataAccess.HttpDataAccessManager.d__31.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at VaultSharp.VaultClient.<MakeVaultApiRequest>d__2251.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at VaultSharp.VaultClient.d__207.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at LLB.Secrets.HashicorpVaultStore.ReadSecretFromStore(SecretMappingElement secretMappingElement) in C:\Projects\LLB\Cloud\Core Libraries\Secrets\Vault\Secrets\1.0\LLB.Secrets\HashicorpVaultStore.cs:line 107

Upgrade VaultSharp to latest JSON Nuget Package 10

Currently receiving the following exception when attempting to read and write with NewtonSoft.Json 10 installed:
Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. Invalid pointer (Exception from HRESULT: 0x80004003 (E_POINTER))

Upon downgrading to 9.0.1 the issue is resolved.

EDIT: is there a way to specify a minimum installation / range? From the previous upgrade's commit it looks like all that was done was changing the numbers...

Allow skipping certificate validation

In my dev environment I've been using self-signed certificates, which has caused problems with the HttpClient when it goes to do certificate validation. In this dotnet core project I've been able to circumvent this by modifying the HttpClient to skip certificate validation by setting
ServerCertificateCustomValidationCallback = delegate { return true; }

Note that in dotnet core setting System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; has no effect, so I have to modify the HttpClient creation directly.

This is the first library I've encountered in the project where the HttpClient construction is completely hidden, thus I can't give the HttpClient an HttpClientHandler which has that ServerCertificateCustomValidationCallback set.

If this is agreeable then I could even do the work and create a PR, just let me know your thoughts.

Was having a deadlock problem with MVC web application and using AppID Auth

Hi,
Thanks for your library. I have attached a patch of the changes I needed to make to workaround a problem I was having when trying to load a secret from an MVC web application. Our application would experience a deadlock after receiving the response to the /v1/auth/app-id/login request.

All I did was to propagate the continueAsyncTasksOnCapturedContext parameter down through the Auth. I only made changes needed to fix the AppIdAuthentication. I expect you will want to propagate that parameter to all the other auth providers as well.

Thanks again and Have fun!
patch.zip

[email protected]

Getting token TimeToLive

Hi, I'm trying to figure out how to obtain the TTL (after renewal) . i'm using the GetTokenInfoAsync
method, it returns all data expect for WrappedInformation (null). i saw that TTL can be obtained from WrapInfo class.

I also tried to use LookupTokenWrapInfoAsync to get the WrappedInformation . but than got an exception indicating the token invalid or does not exists...

Can you help me to figure it out please?

Best.
David Dahan.

GitHubAuthMethod ReturnedLoginAuthInfo returns null value due to async nature

Trying to access the returned Vault Client Token to be cached so no need to request new tokens until it is expired. Basic call the get secrets from Vault works fine.

Tried the following code snippet but seems ReturnedLoginAuthInfo is null:

 // As per example
 IAuthMethodInfo authMethod = new GitHubAuthMethodInfo(personalAccessToken);
 // var token = authMethod.ReturnedLoginAuthInfo.ClientToken; -->null!

After further investigation; looks as though it is due to the async nature (docs should be updated with a clear example):

 // As per example
 IAuthMethodInfo authMethod = new GitHubAuthMethodInfo(personalAccessToken);
 ... // do stuff
 ... // get secrets data from Vault
 // now returns a valid result; can be cached
 var token = authMethod.ReturnedLoginAuthInfo.ClientToken; 

Should the be ReturnedLoginAuthInfo method be marked as async so I can use await until the data returns?

Do suggest the correct way if my observation above is not using it correctly. Thanks!

Documentation Tweak

Hi.

This is great library, and is really helping my team implement Hashicorp Vault

My one comment is that using the "var" shortcut word for variables in the documentation makes reading the documentation harder to pickup easily.

https://github.com/rajanadar/VaultSharp

Example:

var azureCredentials = await vaultClient.V1.Secrets.Azure.GetCredentialsAsync(roleName);
var clientId = azureCredentials.Data.ClientId;
var clientSecret = azureCredentials.Data.ClientSecret;

MUCH MORE PREFERRED FOR DOCUMENTATION

Secret<AzureCredentials> azureCredentials = await ivc.V1.Secrets.Azure.GetCredentialsAsync("myRoleName");
string currentPassword = adCreds.Data.CurrentPassword;
string clientSecret = azureCredentials.Data.ClientSecret;

This really helps a new user (like me) "see" the api documentation much more quickly, then having to actually write example code to see what the real return is.

Like here in the below, I clearly see that TokenAuthMethodInfo is an implementation of IAuthMethodInfo.
And the var word that points to "new VaultClientSettings" isn't hard to discern.

// Initialize one of the several auth methods.
IAuthMethodInfo authMethod = new TokenAuthMethodInfo("MY_VAULT_TOKEN");

// Initialize settings. You can also set proxies, custom delegates etc. here.
var vaultClientSettings = new VaultClientSettings("https://MY_VAULT_SERVER:8200", authMethod);

IVaultClient vaultClient = new VaultClient(vaultClientSettings);

My team's "rule" for the use of var is
"When its clearly a 'new Something', then ok". But when its a result of a method call that isn't easily seen, use the real object type." We do this for code reviews. I'm just looking at code, not necessarily running it, so var in code reviews make it harder to see what is happening, IMHO.

I'm not trying to change your personal preference. However, with documentation and examples, the use of "var" makes learning the API slower, IMHO.

It's a small thing in regards to the overall great library. But would be helpful, IMHO.

Thank you for your consideration.

Allow authentication with a wrapped token

Given that Vault allows creating wrapped tokens it should be possible to use a wrapped token for the initial authentication methods like AppRole and Token. That way it is easier and safer to provide the token to the consuming application.

In order to use a wrapped token as the authentication token the library would have to unwrap the token before using it to authenticate. According to the documentation this can be done by sending a POST request to the /v1/sys/wrapping/unwrap path with the token to be unwrapped in the x-vault-token header and nothing in the body. Unfortunately the VaultClient always creates a body at the moment even if no token is provided:

var requestData = new { token = tokenId };

In this case Vault will return an error indicating that it was expecting a token in the body.

"400 BadRequest. {\"errors\":[\"unknown role: mssqlrole\"]}\n"

@rajanadar
Regarding issue #43
Yes .. while configuring role called mssqlrole i am getting below error...

400 BadRequest. {"errors":["Error validating connection info: failed to send SQL Batch: write tcp [::1]:*******:1433: wsasend: An existing connection was forcibly closed by the remote host."]}

How to fix this issue?

Null reference exception

Hi Rajanadar,

I was trying to work on the sample code provided by downloading the nuget package for c#,
Below is the code.

IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(new Uri("http://127.0.0.1:8200"),
authenticationInfo: null);

        var path = "cubbyhole/foo/Test4321";

        var secretData = new Dictionary<string, object>
        {
            {"1", "1"},
            {"2", 2},
            {"3", false},
        };

        await vaultClient.WriteSecretAsync(path, secretData);

I am getting an issue at line where we try to write the data to the path await vaultClient.WriteSecretAsync(path, secretData);

as below.

at VaultSharp.VaultClient.d__1291.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at VaultSharp.VaultClient.d__128.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at VaultSharp.VaultClient.d__47.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Vault.Program.d__4.MoveNext() in c:\Users\kkumar\Documents\Visual Studio 2013\Projects\Vault\Vault\Program.cs:line 35

Can you please suggest if Iam missing something here? We would want to use Vault to hold the AWS credentials. Can you please help?

If the client is initialized with a null Authentication, give a better error message when a non-anonymous API is invoked.

Currently due to lazy loading, and some APIs needing anonymous access, the authentication info can be initialized to null, when you setup your Vault client. But then if you try invoking a secure API, the code will throw a null reference exception, instead of an exception with a good error message, "This API needs a client token, and hence an AuthenticationInfo needs to be associated with the Vault Client."

Missing information from lookup-self (part 2)

It looks like Vault adds another field once you renew a token for the first time (last_renewal_time):

Before renewal:

$ vault token-lookup REDACTED
Key             	Value
---             	-----
accessor        	REDACTED
creation_time   	1487739401
creation_ttl    	600
display_name    	approle
explicit_max_ttl	0
id              	REDACTED
meta            	map[]
num_uses        	0
orphan          	true
path            	auth/approle/login
policies        	[default]
renewable       	true
ttl             	539

After renewal:

$ vault token-lookup REDACTED
Key              	Value
---              	-----
accessor         	REDACTED
creation_time    	1487739401
creation_ttl     	600
display_name     	approle
explicit_max_ttl 	0
id               	REDACTED
last_renewal_time	1487739573
meta             	map[]
num_uses         	0
orphan           	true
path             	auth/approle/login
policies         	[default]
renewable        	true
ttl              	493
``

Calling token information and renewal

Is there a way to determine when the calling token (as created by a VaultClient instance) needs to be renewed? As far as I can tell there is a IVaultClient.RenewCallingTokenAsync method which allows you to renew the token but I can't seem to figure out how to get information about the token so that I can determine what the lease time is etc. Without having the lease time it will be hard to determine when the lease should be renewed.

TLS1.2 support?

Hi,

Is it possible to get support for TLS1.2 enabled?

You can do this by adding this line somewhere in your initialization code:

System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Best regards,
Russ.

I am not able to install this package in Visual Studio Professional 2015 with .NET 4.6X version

Severity Code Description Project File Line Suppression State
Error Could not install package 'VaultSharp 0.6.4'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author. 0

.NET Core support

Hi, are you planning to add the support for .NET Core? Since the VaultSharp references only Newtonsoft.Json I guess that would be quite straightforward :).

Expose 'ca_chain' in CertificateData

When calling PKIGenerateDynamicCredentialsAsync, I need to access data.ca_chain, but this is not exposed in CertificateCredentials.

Is it possible to add this to CertificateData?

Question: How to retrieve a secret_id for an AppRole.

What's your recommended method for retrieving the a secret_id from an AppRole? I have created an AppRole at auth/approle/role/test and using the Vault CLI, I'd retrieve the secret_id via:

    vault write -f auth/approle/role/test/secret-id

which returns:

    Key Value
    --- -----
    secret_id 306790f6-9ee0-3d7a-9af5-f87913ecb269
    secret_id_accessor dc47aaa4-fd39-5dff-476a-dddaf97d2d16

IVaultClient.WriteSecretAsync() returns a void Task so there's no way I can see to obtain the results from the API. I poked around the source and didn't see another method to do this, but maybe I missed it.

Missing information from lookup-self

From my testing it appears the data returned from running await this.Client.GetCallingTokenInfoAsync(); should include the token's accessor, ttl, & creation time underneath its Data field:

What's available now:

image

What's returned via the lookup-self API:

curl --tlsv1.2 -X GET -H "X-Vault-Token:REDACTED" "https://x.x.x.x/v1/auth/token/lookup-self"
{
  "request_id": "REDACTED",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "accessor": "REDACTED",
    "creation_time": 1484093665,
    "creation_ttl": 3600,
    "display_name": "approle",
    "explicit_max_ttl": 0,
    "id": "REDACTED",
    "meta": {
      "key": "value"
    },
    "num_uses": 0,
    "orphan": true,
    "path": "auth/approle/login",
    "policies": [
      "default"
    ],
    "renewable": true,
    "ttl": 3655
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}

Vault 0.6.x support?

@rajanadar I saw you changed the README, but I see zero code change on any branch since February.

Are you confident 0.6.x is really coming soon ?

Is it purely incompatible or just not able to use newer features ?

Call back events from Hahsi Corp vault

Hi,
I have a few secrets stored in hashi Corp vault. I'm on cloud foundry platform. I use the secrets stored in Hashi corp vault to make external calls. Now If I invoke the Vault every time before I make a call it degrades the performance. But however it is possible that the secrets change over time and it is possible for me to do a local storage eternally. So if these entries change in Hashi Corp vault will it be possible to make a call back in PCF app. On receiving such an event we can reload the content from Vault. Is that possible.

Deadlock when using TransitDecryptAsync from synchronous code

Hi
I have an asp.net web api where I want to add some encryption using Vault Transit functionality.

Here is the wrapper method I've written

public string TransitDecrypt(string encryptedValue)
{
    var value = CreateTransitClient().TransitDecryptAsync(TransitKeyName, encryptedValue).Result;

    return Encoding.UTF8.GetString(Convert.FromBase64String(value.Data.PlainText));
}

When calling this from synchronous api code the Result method never returns, and the api eventually times out. I tested the same code in a command line application and it works fine. I assume this is a deadlock situation. Rewriting the entire api to support aync all the way up is not something I want to do...

The vault client is initialized with continueAsyncTasksOnCapturedContext: false

Then I downloaded the source code for VaultSharp and debugged it. Then I got as far as the following line:

headers.Add(VaultTokenHeaderKey, await _lazyVaultToken.Value);

I added ConfigureAwait(_continueAsyncTasksOnCapturedContext) to this await, and also to the other await in this method (see below), and suddenly everything works

return await _dataAccessManager.MakeRequestAsync<TResponse>(resourcePath, httpMethod, requestData, headers, rawResponse, customProcessor);

Is there a reason configureAwait is not used here, or is this a bug?

Update to 0.7.0

It looks like there are a couple of additions to account for.

https://github.com/hashicorp/vault/blob/master/CHANGELOG.md#070-early-access-final-release-march-21th-2017

0.7.0 (Early Access; final release March 21th, 2017)

SECURITY:

  • Common name not being validated when exclude_cn_from_sans option used in
    pki backend: When using a role in the pki backend that specified the
    exclude_cn_from_sans option, the common name would not then be properly
    validated against the role's constraints. This has been fixed. We recommend
    any users of this feature to upgrade to 0.7 as soon as feasible.

DEPRECATIONS/CHANGES:

  • List Operations Always Use Trailing Slash: Any list operation, whether via
    the GET or LIST HTTP verb, will now internally canonicalize the path to
    have a trailing slash. This makes policy writing more predictable, as it
    means clients will no longer work or fail based on which client they're
    using or which HTTP verb they're using. However, it also means that policies
    allowing list capability must be carefully checked to ensure that they
    contain a trailing slash; some policies may need to be split into multiple
    stanzas to accommodate.
  • PKI Defaults to Unleased Certificates: When issuing certificates from the
    PKI backend, by default, no leases will be issued. If you want to manually
    revoke a certificate, its serial number can be used with the pki/revoke
    endpoint. Issuing leases is still possible by enabling the generate_lease
    toggle in PKI role entries (this will default to true for upgrades, to
    keep existing behavior), which will allow using lease IDs to revoke
    certificates. For installations issuing large numbers of certificates (tens
    to hundreds of thousands, or millions), this will significantly improve
    Vault startup time since leases associated with these certificates will not
    have to be loaded; however note that it also means that revocation of a
    token used to issue certificates will no longer add these certificates to a
    CRL. If this behavior is desired or needed, consider keeping leases enabled
    and ensuring lifetimes are reasonable, and issue long-lived certificates via
    a different role with leases disabled.

FEATURES:

  • Replication (Enterprise): Vault Enterprise now has support for creating
    a multi-datacenter replication set between clusters. The current replication
    offering is based on an asynchronous primary/secondary (1:N) model that
    replicates static data while keeping dynamic data (leases, tokens)
    cluster-local, focusing on horizontal scaling for high-throughput and
    high-fanout deployments.
  • Response Wrapping & Replication in the Vault Enterprise UI: Vault
    Enterprise UI now supports looking up and rotating response wrapping tokens,
    as well as creating tokens with arbitrary values inside. It also now
    supports replication functionality, enabling the configuration of a
    replication set in the UI.
  • Expanded Access Control Policies: Access control policies can now
    specify allowed and denied parameters -- and, optionally, their values -- to
    control what a client can and cannot submit during an API call. Policies can
    also specify minimum/maximum response wrapping TTLs to both enforce the use
    of response wrapping and control the duration of resultant wrapping tokens.
    See the policies concepts
    page
    for more
    information.
  • SSH Backend As Certificate Authority: The SSH backend can now be
    configured to sign host and user certificates. Each mount of the backend
    acts as an independent signing authority. The CA key pair can be configured
    for each mount and the public key is accessible via an unauthenticated API
    call; additionally, the backend can generate a public/private key pair for
    you. We recommend using separate mounts for signing host and user
    certificates.

IMPROVEMENTS:

  • api/request: Passing username and password information in API request
    [GH-2469]
  • audit: Logging the token's use count with authentication response and
    logging the remaining uses of the client token with request [GH-2437]
  • auth/approle: Support for restricting the number of uses on the tokens
    issued [GH-2435]
  • auth/aws-ec2: AWS EC2 auth backend now supports constraints for VPC ID,
    Subnet ID and Region [GH-2407]
  • auth/ldap: Use the value of the LOGNAME or USER env vars for the
    username if not explicitly set on the command line when authenticating
    [GH-2154]
  • audit: Support adding a configurable prefix (such as @cee) before each
    line [GH-2359]
  • core: Canonicalize list operations to use a trailing slash [GH-2390]
  • core: Add option to disable caching on a per-mount level [GH-2455]
  • core: Add ability to require valid client certs in listener config [GH-2457]
  • physical/dynamodb: Implement a session timeout to avoid having to use
    recovery mode in the case of an unclean shutdown, which makes HA much safer
    [GH-2141]
  • secret/pki: O (Organization) values can now be set to role-defined values
    for issued/signed certificates [GH-2369]
  • secret/pki: Certificates issued/signed from PKI backend do not generate
    leases by default [GH-2403]
  • secret/pki: When using DER format, still return the private key type
    [GH-2405]
  • secret/pki: Add an intermediate to the CA chain even if it lacks an
    authority key ID [GH-2465]
  • secret/pki: Add role option to use CSR SANs [GH-2489]
  • secret/ssh: SSH backend as CA to sign user and host certificates [GH-2208]
  • secret/ssh: Support reading of SSH CA public key from config/ca endpoint
    and also return it when CA key pair is generated [GH-2483]

BUG FIXES:

  • audit: When auditing headers use case-insensitive comparisons [GH-2362]
  • auth/aws-ec2: Return role period in seconds and not nanoseconds [GH-2374]
  • auth/okta: Fix panic if user had no local groups and/or policies set
    [GH-2367]
  • command/server: Fix parsing of redirect address when port is not mentioned
    [GH-2354]
  • physical/postgresql: Fix listing returning incorrect results if there were
    multiple levels of children [GH-2393]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.