Skip to content

tablesmit/VaultSharp

 
 

Repository files navigation

VaultSharp 0.6.2 is in progress and expected to be done by end of month. i.e. October 30, 2016

VaultSharp 0.6.1 is now released and available via NuGet.

VaultSharp 0.6.1 supports all backends (auth + secret) of Vault 0.6.1

VaultSharp

A .NET Library for HashiCorp's Vault - A Secret Management System.

Table of Contents

What is VaultSharp?

  • VaultSharp is a C# Library that can be used in any .NET application to interact with Hashicorp's Vault Service.
  • The Vault system is a secret management system built as an Http Service by Hashicorp.
  • This library supports all the Vault Service Apis documented here: https://www.vaultproject.io/docs/http/

VaultSharp 0.6.1 completely supports Hashicorp's Vault 0.6.1

What is the deal with the Versioning of VaultSharp? (Y U NO 1.0.0)

  • This library is written for Hashicorp's Vault Service
  • The Vault service is evolving constantly and the Hashicorp team is rapidly working on it.
  • Pretty soon, they should have an 1.0.0 version of the Vault Service from Hashicorp.
  • 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.6.1 denotes that this library will completely support the Vault 0.6.1 Service Apis.
  • Tomorrow when Vault Service gets upgraded to 0.6.2, this library will be modified accordingly and versioned as 0.6.2

How do I use VaultSharp? Give me a code example

// instantiate VaultClient with one of the various authentication options available.
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, authenticationInfo);

// use it for operations.
var consulCredentials = await vaultClient.ConsulGenerateDynamicCredentialsAsync(consulRoleName, consulMountPoint);
var consulToken = consulCredentials.Data.Token;

Does VaultSharp support all the Authentication, Secret and Audit Backends?

  • YES
  • All Authentication, Secret and Audit backends are supported by this library.
  • All administrative (seal, unseal, write policy), end-user (generate credentials) and unauthenticated methods (get status, get root CA) are supported by this client.

VaultSharp and 100% Consul Support

  • VaultSharp supports all the secret backends supported by the Vault 0.6.1 Service.
  • This includes 100% support for a Consul Secret backend, which is the recommended secret backend for Vault.
  • Please look at the API usage in the 'Consul' section of 'Secret Backends' below, to see all the Consul related methods in action.

The fundamental READ and WRITE operations on a Vault

  • The generic READ/WRITE Apis of vault allow you to do a variety of operations.
  • A lot or almost all of these operations are supported in a strongly typed manner with dedicated methods for them in this library.
  • However, for some reason, if you want to use the generic READ and WRITE methods of Vault, you can use them as follows:
var path = "cubbyhole/foo/test";

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

await vaultClient.WriteSecretAsync(path, secretData);

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

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 you guys. (Task.Run etc.)
  • But please note that as much as possible, use it in an async manner.
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, authenticationInfo, continueAsyncTasksOnCapturedContext: true);

var consulSecret = vaultClient.ConsulGenerateDynamicCredentialsAsync(consulRole).Result;

Authentication Backends (All of them are supported)

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

App Id Authentication Backend

  • Please note that the app-id auth backend has been deprecated by Vault. They recommend us to use the AppRole backend.
  • VaultSharp still lets you use the app-id Apis, for backward compatibility.
  • You can use the strongly typed api's to configure the appid and userid as follows.
// Configure app-id roles and users as follows.
await AdminVaultClient.AppIdAuthenticationConfigureAppId(appId, policy.Name, appId, path);
await AdminVaultClient.AppIdAuthenticationConfigureUserId(userId, appId, authenticationPath: path);

// now, setup the app-id based auth to get the right token.

IAuthenticationInfo appIdAuthenticationInfo = new AppIdAuthenticationInfo(mountPoint, appId, userId);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, appIdAuthenticationInfo);

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

App Role Authentication Backend

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

IAuthenticationInfo appRoleAuthenticationInfo = new AppRoleAuthenticationInfo(mountPoint, roleId, secretId);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, appRoleAuthenticationInfo);

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

AWS-EC2 Authentication Backend

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

IAuthenticationInfo awsEc2AuthenticationInfo = new AwcEc2AuthenticationInfo(mountPoint, pkcs7, nonce, roleName);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, awsEc2AuthenticationInfo);

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

GitHub Authentication Backend

IAuthenticationInfo gitHubAuthenticationInfo = new GitHubAuthenticationInfo(mountPoint, personalAccessToken);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, gitHubAuthenticationInfo);

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

LDAP Authentication Backend

IAuthenticationInfo ldapAuthenticationInfo = new LDAPAuthenticationInfo(mountPoint, username, password);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, ldapAuthenticationInfo);

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

Certificate (TLS) Authentication Backend

var clientCertificate = new X509Certificate2(certificatePath, certificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

IAuthenticationInfo certificateAuthenticationInfo = new CertificateAuthenticationInfo(mountPoint, clientCertificate);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, certificateAuthenticationInfo);

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

Token Authentication Backend

IAuthenticationInfo tokenAuthenticationInfo = new TokenAuthenticationInfo(mountPoint, vaultToken);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, tokenAuthenticationInfo);

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

Username and Password Authentication Backend

IAuthenticationInfo usernamePasswordAuthenticationInfo = new UsernamePasswordAuthenticationInfo(mountPoint, username, password);
IVaultClient vaultClient = VaultClientFactory.CreateVaultClient(vaultUriWithPort, usernamePasswordAuthenticationInfo);

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

Secret Backends (All of them are supported)

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

AWS Secret Backend

Configuring an AWS Backend
// mount the backend
await vaultClient.MountSecretBackendAsync(new SecretBackend
{
    BackendType = SecretBackendType.AWS
});

// configure root credentials to create/manage roles and generate credentials
await vaultClient.AWSConfigureRootCredentialsAsync(new AWSRootCredentials
{
    AccessKey = "access-key",
    SecretKey = "secret-key",
    Region = "region"
});

// create a named role with the IAM policy
await vaultClient.AWSWriteNamedRoleAsync("myAwsRole", new AWSRoleDefinition
{
    Policy = "iam-policy-contents"
});
Generate AWS Credentials
var awsCredentials = await vaultClient.AWSGenerateDynamicCredentialsAsync("myAwsRole");
var awsAccessKey = awsCredentials.Data.AccessKey;
var awsSecretKey = awsCredentials.Data.SecretKey;

Cassandra Secret Backend

Configuring a Cassandra Backend
// mount the backend
await vaultClient.MountSecretBackendAsync(new SecretBackend
{
    BackendType = SecretBackendType.Cassandra
});

// configure root connection info to create/manage roles and generate credentials
await vaultClient.CassandraConfigureConnectionAsync(new CassandraConnectionInfo
{
    Hosts = "hosts",
    Username = "username",
    Password = "password"
});

// create a named role
await vaultClient.CassandraWriteNamedRoleAsync("myCassandraRole", new CassandraRoleDefinition
{
    CreationCql = "csql"
});
Generate Cassandra Credentials
var cassandraCredentials = await vaultClient.CassandraGenerateDynamicCredentialsAsync("myCassandraRole");
var cassandraUsername = cassandraCredentials.Data.Username;
var cassandraPassword = cassandraCredentials.Data.Password;

Consul Secret Backend

Configuring a Consul Backend
// mount the backend
var consulAddress = "127.0.0.1:8500";
var consulAclMasterToken = "raja";

var backend = new SecretBackend
{
    BackendType = SecretBackendType.Consul,
};

await vaultClient.MountSecretBackendAsync(backend);

// configure access to Consul and create roles
var consulRole = "consulRole";

await vaultClient.ConsulConfigureAccessAsync(new ConsulAccessInfo()
{
    AddressWithPort = consulAddress,
    ManagementToken = consulAclMasterToken
});

// create a named role
await vaultClient.ConsulWriteNamedRoleAsync(consulRole, new ConsulRoleDefinition()
{
    TokenType = ConsulTokenType.management,
});

var readRole = await vaultClient.ConsulReadNamedRoleAsync(consulRole);
Assert.Equal(ConsulTokenType.management, readRole.Data.TokenType);
Generate Consul Credentials
var consulCredentials = await vaultClient.ConsulGenerateDynamicCredentialsAsync(consulRole);
var consulToken = consulCredentials.Data.Token;
Deleting Role and Unmounting the Consul backend
await vaultClient.ConsulDeleteNamedRoleAsync(consulRole);
await vaultClient.UnmountSecretBackendAsync(SecretBackendType.Consul.Type);

Cubbyhole Secret Backend

var path = "cubbyhole/foo1/foo2";
var values = new Dictionary<string, object>
{
    {"foo", "bar"},
    {"foo2", 345 }
};

await vaultClient.CubbyholeWriteSecretAsync(path, values);

var readValues = await vaultClient.CubbyholeReadSecretAsync(path);
var data = readValues.Data; // gives back the dictionary

await vaultClient.CubbyholeDeleteSecretAsync(path);

Generic Secret Backend

var mountpoint = "secret" + Guid.NewGuid();

var path = mountpoint + "/foo1/blah2";
var values = new Dictionary<string, object>
{
    {"foo", "bar"},
    {"foo2", 345 }
};

await
    vaultClient.MountSecretBackendAsync(new SecretBackend()
    {
        BackendType = SecretBackendType.Generic,
        MountPoint = mountpoint
    });

await vaultClient.GenericWriteSecretAsync(path, values);

var readValues = await vaultClient.GenericReadSecretAsync(path);
var data = readValues.Data; // gives back the dictionary

await vaultClient.GenericDeleteSecretAsync(path);

MongoDB Secret Backend

Configuring a MongoDB Backend
// mount the backend
var mountPoint = "mongodb" + Guid.NewGuid();
var backend = new SecretBackend
{
    MountPoint = mountPoint,
    BackendType = SecretBackendType.MongoDB,
};

await vaultClient.MountSecretBackendAsync(backend);

// configure root connection info to create/manage roles and generate credentials

var mongoDbConnectionInfo = new MongoDbConnectionInfo
{
 ConnectionStringUri = "mongodb://root:password@127.0.0.1:27017/admin?ssl=false"
};

await vaultClient.MongoDbConfigureConnectionAsync(mongoDbConnectionInfo, mountPoint);

var lease = new CredentialTimeToLiveSettings
{
    TimeToLive = "1m1s",
    MaximumTimeToLive = "2m1s"
};

await vaultClient.MongoDbConfigureCredentialLeaseSettingsAsync(lease);

// create a named role
var roleName = "mongodb-role";

var role = new MongoDbRoleDefinition
{
    Database = "admin",
    Roles = JsonConvert.SerializeObject(new object[] { "readWrite", new { role = "read", db = "bar" } })
};

await vaultClient.MongoDbWriteNamedRoleAsync(roleName, role);

var queriedRole = await vaultClient.MongoDbReadNamedRoleAsync(roleName);
Generate MongoDB Credentials
var generatedCreds = await vaultClient.MongoDbGenerateDynamicCredentialsAsync(roleName, mountPoint);

var username = generatedCreds.Data.Username;
var password = generatedCreds.Data.Password;

MSSQL Secret Backend

Configuring a MSSQL Backend
// mount the backend
var mountPoint = "mssql" + Guid.NewGuid();
var backend = new SecretBackend
{
    MountPoint = mountPoint,
    BackendType = SecretBackendType.MicrosoftSql,
};

await vaultClient.MountSecretBackendAsync(backend);

// configure root connection info to create/manage roles and generate credentials
var microsoftSqlConnectionInfo = new MicrosoftSqlConnectionInfo
{
    ConnectionString = "server=localhost\sqlexpress;port=1433;user id=sa;password=****;database=master;app name=vault",
    MaximumOpenConnections = 5,
    VerifyConnection = true
};

await vaultClient.MicrosoftSqlConfigureConnectionAsync(microsoftSqlConnectionInfo, mountPoint);

var lease = new CredentialTtlSettings()
{
    TimeToLive = "1m1s",
    MaximumTimeToLive = "2m1s"
};

await vaultClient.MicrosoftSqlConfigureCredentialLeaseSettingsAsync(lease, mountPoint);

// create a named role
var roleName = "msssqlrole";

var role = new MicrosoftSqlRoleDefinition
{
    Sql = "CREATE LOGIN '[{{name}}]' WITH PASSWORD = '{{password}}'; USE master; CREATE USER '[{{name}}]' FOR LOGIN '[{{name}}]'; GRANT SELECT ON SCHEMA::dbo TO '[{{name}}]'"
};

await vaultClient.MicrosoftSqlWriteNamedRoleAsync(roleName, role, mountPoint);

var queriedRole = await vaultClient.MicrosoftSqlReadNamedRoleAsync(roleName, mountPoint);
Generate MSSQL Credentials
var msSqlCredentials = await vaultClient.MicrosoftSqlGenerateDynamicCredentialsAsync(roleName, backend.MountPoint);

var msSqlUsername = msSqlCredentials.Data.Username;
var msSqlPassword = msSqlCredentials.Data.Password;

MySql Secret Backend

Configuring a MySql Backend
// mount the backend
var mountPoint = "mysql" + Guid.NewGuid();
var backend = new SecretBackend
{
    MountPoint = mountPoint,
    BackendType = SecretBackendType.MySql,
};

await vaultClient.MountSecretBackendAsync(backend);

// configure root connection info to create/manage roles and generate credentials
await vaultClient.MySqlConfigureConnectionAsync(new MySqlConnectionInfo()
{
    DataSourceName = "root:root@tcp(127.0.0.1:3306)/"
}, mountPoint);

var sql = "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON *.* TO '{{name}}'@'%';";

await vaultClient.MySqlConfigureCredentialLeaseSettingsAsync(new CredentialLeaseSettings()
{
    LeaseDuration = "1h",
    MaximumLeaseDuration = "2h"
}, mountPoint);

// create a named role
var mySqlRole = "mysql-readonly-role";

await vaultClient.MySqlWriteNamedRoleAsync(mySqlRole, new MySqlRoleDefinition()
{
    Sql = sql
}, mountPoint);

var readRole = await vaultClient.MySqlReadNamedRoleAsync(mySqlRole, mountPoint);
var roleSql = readRole.Data.Sql;
Generate MySql Credentials
var mySqlCredentials = await vaultClient.MySqlGenerateDynamicCredentialsAsync(mySqlRole, backend.MountPoint);

var mySqlUsername = mySqlCredentials.Data.Username;
var mySqlPassword = mySqlCredentials.Data.Password;

PKI (Certificates) Secret Backend

Configuring a PKI Backend
// mount the backend
var mountpoint = "pki" + Guid.NewGuid();
var backend = new SecretBackend
{
    BackendType = SecretBackendType.PKI,
    MountPoint = mountpoint
};

await vaultClient.MountSecretBackendAsync(backend);

// write expiry
var expiry = "124h";
var commonName = "blah.example.com";

await vaultClient.PKIWriteCRLExpirationAsync(expiry, mountpoint);

var readExpiry = await vaultClient.PKIReadCRLExpirationAsync(mountpoint);
Assert.Equal(expiry, readExpiry.Data.Expiry);

// read certificate in various ways
var nocaCert = await vaultClient.PKIReadCACertificateAsync(CertificateFormat.pem, mountpoint);
Assert.Null(nocaCert.CertificateContent);

// generate root certificate
var rootCertificateWithoutPrivateKey =
    await vaultClient.PKIGenerateRootCACertificateAsync(new RootCertificateRequestOptions
    {
        CommonName = commonName,
        ExportPrivateKey = false
    }, mountpoint);

Assert.Null(rootCertificateWithoutPrivateKey.Data.PrivateKey);

var rootCertificate =
    await vaultClient.PKIGenerateRootCACertificateAsync(new RootCertificateRequestOptions
    {
        CommonName = commonName,
        ExportPrivateKey = true
    }, mountpoint);

Assert.NotNull(rootCertificate.Data.PrivateKey);

// read certificate in various ways
var caCert = await vaultClient.PKIReadCACertificateAsync(CertificateFormat.pem, mountpoint);
Assert.NotNull(caCert.CertificateContent);

var caReadCert = await vaultClient.PKIReadCertificateAsync("ca", mountpoint);
Assert.Equal(caCert.CertificateContent, caReadCert.Data.CertificateContent);

var caSerialNumberReadCert = await vaultClient.PKIReadCertificateAsync(rootCertificate.Data.SerialNumber, mountpoint);
Assert.Equal(caCert.CertificateContent, caSerialNumberReadCert.Data.CertificateContent);

var crlCert = await vaultClient.PKIReadCertificateAsync("crl", mountpoint);
Assert.NotNull(crlCert.Data.CertificateContent);

var crlCert2 = await vaultClient.PKIReadCRLCertificateAsync(CertificateFormat.pem, mountpoint);
Assert.NotNull(crlCert2.CertificateContent);

// write and read certificate endpoints

var crlEndpoint = _vaultUri.AbsoluteUri + "/v1/" + mountpoint + "/crl";
var issuingEndpoint = _vaultUri.AbsoluteUri + "/v1/" + mountpoint + "/ca";

var endpoints = new CertificateEndpointOptions
{
    CRLDistributionPointEndpoints = string.Join(",", new List<string> { crlEndpoint }),
    IssuingCertificateEndpoints = string.Join(",", new List<string> { issuingEndpoint }),
};

await vaultClient.PKIWriteCertificateEndpointsAsync(endpoints, mountpoint);

var readEndpoints = await vaultClient.PKIReadCertificateEndpointsAsync(mountpoint);

Assert.Equal(crlEndpoint, readEndpoints.Data.CRLDistributionPointEndpoints.First());
Assert.Equal(issuingEndpoint, readEndpoints.Data.IssuingCertificateEndpoints.First());

// rotate CRL
var rotate = await vaultClient.PKIRotateCRLAsync(mountpoint);
Assert.True(rotate);

await vaultClient.RevokeSecretAsync(rootCertificateWithoutPrivateKey.LeaseId);
Write/Read PKI Role
// Create new Role
var roleName = Guid.NewGuid().ToString();

var role = new CertificateRoleDefinition
{
    AllowedDomains = "example.com",
    AllowSubdomains = true,
    MaximumTimeToLive = "72h",
};

await vaultClient.PKIWriteNamedRoleAsync(roleName, role, mountpoint);

var readRole = await vaultClient.PKIReadNamedRoleAsync(roleName, mountpoint);
Assert.Equal(role.AllowedDomains, readRole.Data.AllowedDomains);
Generate PKI Credentials
var certificateCredentials =
    await
        vaultClient.PKIGenerateDynamicCredentialsAsync(roleName,
            new CertificateCredentialsRequestOptions
            {
                CommonName = commonName,
                CertificateFormat = CertificateFormat.pem
            }, mountpoint);

var privateKey = certificateCredentials.Data.PrivateKey;

PostgreSql Secret Backend

Configuring a PostgreSql Backend
// mount the backend
var mountPoint = "postgresql" + Guid.NewGuid();
var backend = new SecretBackend
{
    MountPoint = mountPoint,
    BackendType = SecretBackendType.PostgreSql,
};

await vaultClient.MountSecretBackendAsync(backend);

await vaultClient.PostgreSqlConfigureCredentialLeaseSettingsAsync(new CredentialLeaseSettings()
{
    LeaseDuration = "1h",
    MaximumLeaseDuration = "2h"
}, mountPoint);

// configure root connection info to create/manage roles and generate credentials
await vaultClient.PostgreSqlConfigureConnectionAsync(new PostgreSqlConnectionInfo
{
    ConnectionString = "con_string",
    MaximumOpenConnections = 5
}, mountPoint);

var sql = "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";";

// create a named role
var postgreSqlRole = "postgresql-readonly-role";

await vaultClient.PostgreSqlWriteNamedRoleAsync(postgreSqlRole, new PostgreSqlRoleDefinition()
{
    Sql = sql
}, mountPoint);

var readRole = await vaultClient.PostgreSqlReadNamedRoleAsync(postgreSqlRole, mountPoint);
Assert.Equal(sql, readRole.Data.Sql);
Generate PostgreSql Credentials
var postgreSqlCredentials = await vaultClient.PostgreSqlGenerateDynamicCredentialsAsync(postgreSqlRole, backend.MountPoint);

Assert.NotNull(postgreSqlCredentials.LeaseId);
Assert.NotNull(postgreSqlCredentials.Data.Username);
Assert.NotNull(postgreSqlCredentials.Data.Password);

RabbitMQ Secret Backend

Configuring a RabbitMQ Backend
// mount the backend
await vaultClient.QuickMountSecretBackendAsync(SecretBackendType.RabbitMQ);

// configure root connection info to create/manage roles and generate credentials
var connectionInfo = new RabbitMQConnectionInfo
{
    ConnectionUri = "http://localhost:15672",
    Username = "guest",
    Password = "guest",
    VerifyConnection = true
};

await vaultClient.RabbitMQConfigureConnectionAsync(connectionInfo);

var lease = new CredentialTimeToLiveSettings
{
    TimeToLive = "1m1s",
    MaximumTimeToLive = "2m1s"
};

await vaultClient.RabbitMQConfigureCredentialLeaseSettingsAsync(lease);
var queriedLease = await vaultClient.RabbitMQReadCredentialLeaseSettingsAsync();

var roleName = "rabbitmqrole";

var role = new RabbitMQRoleDefinition
{
    VirtualHostPermissions = "{\"/\":{\"write\": \".*\", \"read\": \".*\"}}"
};

await vaultClient.RabbitMQWriteNamedRoleAsync(roleName, role);

var queriedRole = await vaultClient.RabbitMQReadNamedRoleAsync(roleName);
Generate RabbitMQ Credentials
var generatedCreds = await vaultClient.RabbitMQGenerateDynamicCredentialsAsync(roleName);

Assert.NotNull(generatedCreds.Data.Username);
Assert.NotNull(generatedCreds.Data.Password);

SSH Secret Backend

Configuring a SSH Backend
// mount the backend
var sshKeyName = Guid.NewGuid().ToString();
var sshRoleName = Guid.NewGuid().ToString();

var mountPoint = "ssh" + Guid.NewGuid();
var backend = new SecretBackend
{
    BackendType = SecretBackendType.SSH,
    MountPoint = mountPoint,
};

await vaultClient.MountSecretBackendAsync(backend);

// configure key and role
var privateKey = @"-----BEGIN RSA PRIVATE KEY----- key ---";

var ip = "127.0.0.1";
var user = "rajan";

await vaultClient.SSHWriteNamedKeyAsync(sshKeyName, privateKey, mountPoint);
await vaultClient.SSHWriteNamedRoleAsync(sshRoleName, new SSHOTPRoleDefinition
{
    RoleDefaultUser = user,
    CIDRValues = "127.0.0.1/10",
}, mountPoint);

var role = await vaultClient.SSHReadNamedRoleAsync(sshRoleName, mountPoint);
Assert.True(role.Data.KeyTypeToGenerate == SSHKeyType.otp);
Generate SSH Credentials
var credentials = await
    vaultClient.SSHGenerateDynamicCredentialsAsync(sshRoleName, ip,
        sshBackendMountPoint: mountPoint);

Assert.Equal(user, credentials.Data.Username);

Transit Secret Backend

Configuring a Transit Backend
// mount the backend
var backend = new SecretBackend
{
    BackendType = SecretBackendType.Transit,
    MountPoint = "transit" + Guid.NewGuid(),
};

await vaultClient.MountSecretBackendAsync(backend);

// create encryption key
var keyName = "test_key" + Guid.NewGuid();
var context = "context1";

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

await vaultClient.TransitCreateEncryptionKeyAsync(keyName, true, backend.MountPoint);
var keyInfo = await vaultClient.TransitGetEncryptionKeyInfoAsync(keyName, backend.MountPoint);

Assert.Equal(keyName, keyInfo.Data.Name);
Assert.True(keyInfo.Data.MustUseKeyDerivation);
Assert.False(keyInfo.Data.IsDeletionAllowed);

// configure the key
await vaultClient.TransitConfigureEncryptionKeyAsync(keyName, isDeletionAllowed: true, transitBackendMountPoint: backend.MountPoint);

keyInfo = await vaultClient.TransitGetEncryptionKeyInfoAsync(keyName, backend.MountPoint);
Assert.True(keyInfo.Data.IsDeletionAllowed);
Encrypt/Decrypt text
var cipherText = await vaultClient.TransitEncryptAsync(keyName, encodedPlainText, context, transitBackendMountPoint: backend.MountPoint);

var plainText2 = Encoding.UTF8.GetString(Convert.FromBase64String((await vaultClient.TransitDecryptAsync(keyName, cipherText.Data.CipherText, context, backend.MountPoint)).Data.PlainText));

Assert.Equal(plainText, plainText2);
Other Transit Operations
await vaultClient.TransitRotateEncryptionKeyAsync(keyName, backend.MountPoint);
var cipherText2 = await vaultClient.TransitEncryptAsync(keyName, encodedPlainText, context, transitBackendMountPoint: backend.MountPoint);

Assert.NotEqual(cipherText.Data.CipherText, cipherText2.Data.CipherText);

var cipherText3 = await vaultClient.TransitRewrapWithLatestEncryptionKeyAsync(keyName, cipherText.Data.CipherText, context, backend.MountPoint);

var newKey1 = await vaultClient.TransitCreateDataKeyAsync(keyName, false, context, 128, backend.MountPoint);
Assert.Null(newKey1.Data.PlainTextKey);

newKey1 = await vaultClient.TransitCreateDataKeyAsync(keyName, true, context, 128, backend.MountPoint);
Assert.NotNull(newKey1.Data.PlainTextKey);

await vaultClient.TransitDeleteEncryptionKeyAsync(keyName, backend.MountPoint);

Audit Backends (All of them are supported)

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

File Audit Backend

var audits = (await vaultClient.GetAllEnabledAuditBackendsAsync()).ToList();

// enable new file audit
var newFileAudit = new FileAuditBackend
{
    BackendType = AuditBackendType.File,
    Description = "store logs in a file - test cases",
    Options = new FileAuditBackendOptions
    {
        FilePath = "/var/log/file"
    }
};

await vaultClient.EnableAuditBackendAsync(newFileAudit);

// get audits
var newAudits = (await vaultClient.GetAllEnabledAuditBackendsAsync()).ToList();
Assert.Equal(audits.Count + 1, newAudits.Count);

// hash with audit
var hash = await vaultClient.HashWithAuditBackendAsync(newFileAudit.MountPoint, "testinput");
Assert.NotNull(hash);

// disabled audit
await vaultClient.DisableAuditBackendAsync(newFileAudit.MountPoint);

Syslog Audit Backend

// enable new syslog audit
var newSyslogAudit = new SyslogAuditBackend
{
    BackendType = AuditBackendType.Syslog,
    Description = "syslog audit - test cases",
    Options = new SyslogAuditBackendOptions()
};

await vaultClient.EnableAuditBackendAsync(newSyslogAudit);

// get audits
var newAudits2 = (await vaultClient.GetAllEnabledAuditBackendsAsync()).ToList();
Assert.Equal(1, newAudits2.Count);

// disabled audit
await vaultClient.DisableAuditBackendAsync(newSyslogAudit.MountPoint);

// get audits
var oldAudits2 = (await vaultClient.GetAllEnabledAuditBackendsAsync()).ToList();
Assert.Equal(audits.Count, oldAudits2.Count);

More Administrative & Other operations

  • VaultSharp supports all the operations supported by the Service.
  • These include administrative ones like Inititalize, Unseal, Seal etc.
  • Here are some samples.
await noAuthInfoClient.InitializeAsync(5, 3, null);
await vaultClient.SealAsync();

await vaultClient.UnsealAsync(masterKey); // need to run this in a loop for all master keys
await vaultClient.UnsealQuickAsync(allMasterKeys);  // unseals the Vault in 1 shot.

await vaultClient.GetSealStatusAsync();

// all policy operations

// write a new policy
var newPolicy = new Policy
{
    Name = "gubdu",
    Rules = "path \"sys/*\" {  policy = \"deny\" }"
};

await vaultClient.WritePolicyAsync(newPolicy);

// get new policy
var newPolicyGet = await vaultClient.GetPolicyAsync(newPolicy.Name);
Assert.Equal(newPolicy.Rules, newPolicyGet.Rules);

// write updates to a new policy
newPolicy.Rules = "path \"sys/*\" {  policy = \"read\" }";

await vaultClient.WritePolicyAsync(newPolicy);

// get new policy
newPolicyGet = await vaultClient.GetPolicyAsync(newPolicy.Name);
Assert.Equal(newPolicy.Rules, newPolicyGet.Rules);

// delete policy
await vaultClient.DeletePolicyAsync(newPolicy.Name);

Miscellaneous Features

  • VaultSharp supports some awesome features like quick mount, quick unseal, quick rekey etc.
  • It also supports setting Proxy settings, custom message handlers for the HttpClient.

Quick mount, unseal and rekey methods

// quickly mount a secret backend
await vaultClient.QuickMountSecretBackendAsync(SecretBackendType.AWS);

// quickly mount an auth backend
await vaultClient.QuickEnableAuthenticationBackendAsync(AuthenticationBackendType.GitHub);

// quickly unseal Vault with a single call.
var sealStatus = await UnauthenticatedVaultClient.QuickUnsealAsync(AllMasterKeys);

// quickly rekey Vault with a single call.
var quick = await UnauthenticatedVaultClient.QuickRekeyAsync(AllMasterKeys, rekeyStatus.Nonce);

Setting Proxy Settings, custom Message Handlers etc.

var vaultClient = VaultClientFactory.CreateVaultClient(VaultUriWithPort, new TokenAuthenticationInfo(someToken), postHttpClientInitializeAction:
    httpClient =>
    {
        // set proxy or custom handlers here.
    });

In Conclusion

Happy Coding folks!

About

A .NET Library for HashiCorp's Vault Service - http://rajanadar.github.io/VaultSharp/

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%