-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e345915
commit c29f714
Showing
40 changed files
with
1,664 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<AssemblyName>HashiVaultCs</AssemblyName> | ||
<RootNamespace>HashiVaultCs</RootNamespace> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="FormatWith" Version="3.0.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Compile Update="Resources\HttpVaultClient\Resource.Designer.cs"> | ||
<DesignTime>True</DesignTime> | ||
<AutoGen>True</AutoGen> | ||
<DependentUpon>Resource.resx</DependentUpon> | ||
</Compile> | ||
<Compile Update="Resources\Resource.Designer.cs"> | ||
<DesignTime>True</DesignTime> | ||
<AutoGen>True</AutoGen> | ||
<DependentUpon>Resource.resx</DependentUpon> | ||
</Compile> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<EmbeddedResource Update="Resources\HttpVaultClient\Resource.resx"> | ||
<Generator>ResXFileCodeGenerator</Generator> | ||
<LastGenOutput>Resource.Designer.cs</LastGenOutput> | ||
</EmbeddedResource> | ||
<EmbeddedResource Update="Resources\Resource.resx"> | ||
<Generator>ResXFileCodeGenerator</Generator> | ||
<LastGenOutput>Resource.Designer.cs</LastGenOutput> | ||
</EmbeddedResource> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace HashiVaultCs.Clients; | ||
|
||
public static class ApiUrl | ||
{ | ||
public const string AuthUserpassLogin = "/v1/auth/userpass/login/{username}"; | ||
public const string AuthApproleRoleId = "/v1/auth/approle/role/{rolename}/role-id"; | ||
public const string AuthApproleSecretId = "/v1/auth/approle/role/{rolename}/secret-id"; | ||
public const string AuthApproleLogin = "/v1/auth/approle/login"; | ||
public const string SecretsEngineDataPath = "/v1/{engine}/data/{path}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using HashiVaultCs.Interfaces.Auth; | ||
using HashiVaultCs.Models.Requests.Auth.Approle; | ||
|
||
namespace HashiVaultCs.Clients.Auth; | ||
|
||
public sealed class ApproleClient : MustInitialiseHttpVaultHeadersAndHostAbstraction<HttpVaultHeaders>, IApproleClient | ||
{ | ||
public ApproleClient(HttpVaultHeaders vault_headers, string base_address) : base(vault_headers, base_address) { } | ||
|
||
public async Task<Secret> LoginAsync(Login data, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default) | ||
{ | ||
Uri request_uri = new(_base_uri, ApiUrl.AuthApproleLogin); | ||
HttpVaultClient http_vault_client = new(HttpMethod.Post, _vault_headers, headers, request_uri, data); | ||
JsonDocument response = await http_vault_client.SendAsync(cancellationToken); | ||
return response.Deserialize<Secret>() ?? new Secret(); | ||
} | ||
|
||
public async Task<Secret> RoleIdAsync(string rolename, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default) | ||
{ | ||
string relative_url = ApiUrl.AuthApproleRoleId.FormatWith(new | ||
{ | ||
rolename | ||
}); | ||
Uri request_uri = new(_base_uri, relative_url); | ||
|
||
HttpVaultClient http_vault_client = new(HttpMethod.Get, _vault_headers, headers, request_uri); | ||
JsonDocument response = await http_vault_client.SendAsync(cancellationToken); | ||
return response.Deserialize<Secret>() ?? new Secret(); | ||
} | ||
|
||
public async Task<Secret> SecretIdAsync(string rolename, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default) | ||
{ | ||
string relative_url = ApiUrl.AuthApproleSecretId.FormatWith(new | ||
{ | ||
rolename | ||
}); | ||
Uri request_uri = new(_base_uri, relative_url); | ||
|
||
HttpVaultClient http_vault_client = new(HttpMethod.Post, _vault_headers, headers, request_uri, new { }); | ||
JsonDocument response = await http_vault_client.SendAsync(cancellationToken); | ||
return response.Deserialize<Secret>() ?? new Secret(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using HashiVaultCs.Interfaces.Auth; | ||
using HashiVaultCs.Models.Requests.Auth.Userpass; | ||
|
||
namespace HashiVaultCs.Clients.Auth; | ||
|
||
public sealed class UserpassClient : MustInitialiseHttpVaultHeadersAndHostAbstraction<HttpVaultHeaders>, IUserpassClient | ||
{ | ||
public UserpassClient(HttpVaultHeaders vault_headers, string base_address) : base(vault_headers, base_address) { } | ||
|
||
public async Task<Secret> LoginAsync(string username, Login data, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default) | ||
{ | ||
string relative_url = ApiUrl.AuthUserpassLogin.FormatWith(new | ||
{ | ||
username | ||
}); | ||
Uri request_uri = new(_base_uri, relative_url); | ||
|
||
HttpVaultClient http_vault_client = new(HttpMethod.Post, _vault_headers, headers, request_uri, data); | ||
JsonDocument response = await http_vault_client.SendAsync(cancellationToken); | ||
return response.Deserialize<Secret>() ?? new Secret(); // todo (2022-05-23|kibble): What to return when Deserialize() fails, this method shouldn't return empty secrets... | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Client/Clients/MustInitialiseHttpVaultHeadersAndHostAbstraction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using HashiVaultCs.Interfaces; | ||
|
||
namespace HashiVaultCs.Clients; | ||
|
||
public abstract class MustInitialiseHttpVaultHeadersAndHostAbstraction<T> where T : IHttpVaultHeaders | ||
{ | ||
protected readonly T _vault_headers; | ||
protected readonly Uri _base_uri; | ||
public MustInitialiseHttpVaultHeadersAndHostAbstraction(T vault_headers, string base_address) | ||
{ | ||
_vault_headers = vault_headers; | ||
_base_uri = new Uri(base_address); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using HashiVaultCs.Interfaces.Secrets; | ||
|
||
namespace HashiVaultCs.Clients.Secrets; | ||
|
||
public sealed class DataClient : MustInitialiseHttpVaultHeadersAndHostAbstraction<HttpVaultHeaders>, IDataClient | ||
{ | ||
public DataClient(HttpVaultHeaders vault_headers, string base_address) : base(vault_headers, base_address) { } | ||
|
||
public async Task<Secret> GetAsync(string engine, string path, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default) | ||
{ | ||
string relative_url = ApiUrl.SecretsEngineDataPath.FormatWith(new | ||
{ | ||
engine, | ||
path | ||
}); | ||
Uri request_uri = new(_base_uri, relative_url); | ||
|
||
HttpVaultClient http_vault_client = new(HttpMethod.Get, _vault_headers, headers, request_uri); | ||
JsonDocument response = await http_vault_client.SendAsync(cancellationToken); | ||
return response.Deserialize<Secret>() ?? new Secret(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using HashiVaultCs; | ||
|
||
namespace HashiVaultCs.Extentions; | ||
|
||
public static class HttpRequestMessageExtentions | ||
{ | ||
public static void AddVaultHttpHeaders(this HttpRequestMessage http_request_message, HttpVaultHeaders vault_headers) | ||
{ | ||
ArgumentNullException.ThrowIfNull(vault_headers); | ||
|
||
if (vault_headers.RequestHeaderPresent is true) | ||
{ | ||
http_request_message.Headers.Remove(vault_headers.Request.Key); | ||
http_request_message.Headers.Add(vault_headers.Request.Key, vault_headers.Request.Value); | ||
} | ||
|
||
if (vault_headers.TokenHeaderPresent is true) | ||
{ | ||
http_request_message.Headers.Remove(vault_headers.Token.Key); | ||
http_request_message.Headers.Add(vault_headers.Token.Key, vault_headers.Token.Value); | ||
} | ||
|
||
if (vault_headers.NamespaceHeaderPresent is true) | ||
{ | ||
http_request_message.Headers.Remove(vault_headers.Namespace.Key); | ||
http_request_message.Headers.Add(vault_headers.Namespace.Key, vault_headers.Namespace.Value); | ||
} | ||
|
||
if (vault_headers.WrapTimeToLiveHeaderPresent is true) | ||
{ | ||
http_request_message.Headers.Remove(vault_headers.WrapTimeToLive.Key); | ||
http_request_message.Headers.Add(vault_headers.WrapTimeToLive.Key, vault_headers.WrapTimeToLive.Value); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using HashiVaultCs.Interfaces; | ||
|
||
namespace HashiVaultCs; | ||
|
||
public sealed class HttpVaultClient : IHttpVaultClient | ||
{ | ||
private const string _media_type = "application/json"; | ||
private readonly TimeSpan _http_client_timeout = TimeSpan.FromSeconds(6); | ||
private readonly HttpClient _http_client; | ||
private readonly HttpRequestMessage _http_request_message; | ||
private readonly List<HttpMethod> _supported_http_methods_list = new() { HttpMethod.Get, HttpMethod.Post }; | ||
|
||
public HttpVaultClient(HttpMethod method, HttpVaultHeaders vault_headers, IReadOnlyDictionary<string, string> headers, Uri request_uri, object? content = null) | ||
{ | ||
// Currently only HTTP Methods GET & POST is supported. | ||
if (_supported_http_methods_list.Contains(method) is false) | ||
{ | ||
throw new NotSupportedException($"{Resources.HttpVaultClient.Resource.MethodNotSupportedException}. {Resources.HttpVaultClient.Resource.SupportedHttpMethodsAre}: {string.Join(", ", _supported_http_methods_list)}"); | ||
} | ||
|
||
// HTTP Headers should not be null, but can be empty (ImmutableDictionary<string, string>.Empty). | ||
if (headers?.Any() is null) | ||
{ | ||
throw new ArgumentNullException(nameof(headers), Resources.HttpVaultClient.Resource.HeadersArgumentNullException); | ||
} | ||
|
||
// Generate HTTP Request Message and set content | ||
_http_request_message = new(method, request_uri) | ||
{ | ||
Content = content is null | ||
? null | ||
: new StringContent(JsonSerializer.Serialize(content), Encoding.UTF8, _media_type) | ||
}; | ||
|
||
// Build the HTTP Headers, both custom and Vault Specific HTTP Headers. | ||
_http_request_message.AddVaultHttpHeaders(vault_headers); | ||
foreach (KeyValuePair<string, string> kvp in headers) | ||
{ | ||
_http_request_message.Headers.Remove(kvp.Key); | ||
_http_request_message.Headers.Add(kvp.Key, kvp.Value); | ||
} | ||
|
||
HttpClientHandler handler = new(); | ||
_http_client = new(handler) | ||
{ | ||
Timeout = _http_client_timeout | ||
}; | ||
|
||
_http_client.DefaultRequestHeaders.Accept.Clear(); | ||
_http_client.DefaultRequestHeaders.Accept.Add(new(_media_type)); | ||
} | ||
|
||
/// <summary> | ||
/// This method will throw an exception if the HTTP response status is anything but a success. | ||
/// </summary> | ||
/// <remarks>Only valid JSON is returned from this method through the return of JsonDocument values.</remarks> | ||
/// <returns></returns> | ||
public async Task<JsonDocument> SendAsync(CancellationToken cancellationToken = default) | ||
{ | ||
HttpResponseMessage http_response_message = await _http_client.SendAsync(_http_request_message, cancellationToken); | ||
http_response_message.EnsureSuccessStatusCode(); | ||
string response_json = await http_response_message.Content.ReadAsStringAsync(cancellationToken); | ||
JsonDocumentOptions jdo = new() | ||
{ | ||
AllowTrailingCommas = false, | ||
CommentHandling = JsonCommentHandling.Disallow, | ||
MaxDepth = 32 | ||
}; | ||
JsonDocument document = JsonDocument.Parse(response_json, jdo); | ||
return document; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace HashiVaultCs; | ||
|
||
public static class HttpVaultHeaderKey | ||
{ | ||
public const string Request = "X-Vault-Request"; | ||
public const string Token = "X-Vault-Token"; | ||
public const string Namespace = "X-Vault-Namespace"; | ||
public const string WrapTimeToLive = "X-Vault-Wrap-TTL"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using HashiVaultCs.Interfaces; | ||
|
||
namespace HashiVaultCs; | ||
|
||
public sealed class HttpVaultHeaders : IHttpVaultHeaders | ||
{ | ||
public bool RequestHeaderPresent { get; private set; } | ||
private KeyValuePair<string, string>? _request; | ||
public KeyValuePair<string, string> Request => RequestHeaderPresent is false || _request is null | ||
? throw new InvalidOperationException($"{Resources.Resource.VaultHttpHeadersInvalidOperationException}: {nameof(Request)}") | ||
: _request ?? throw new NullReferenceException(); | ||
|
||
public bool TokenHeaderPresent { get; private set; } | ||
private KeyValuePair<string, string>? _token; | ||
public KeyValuePair<string, string> Token => TokenHeaderPresent is false || _token is null | ||
? throw new InvalidOperationException($"{Resources.Resource.VaultHttpHeadersInvalidOperationException}: {nameof(Token)}") | ||
: _token ?? throw new NullReferenceException(); | ||
|
||
public bool NamespaceHeaderPresent { get; private set; } | ||
private KeyValuePair<string, string>? _namespace; | ||
public KeyValuePair<string, string> Namespace => NamespaceHeaderPresent is false || _namespace is null | ||
? throw new InvalidOperationException($"{Resources.Resource.VaultHttpHeadersInvalidOperationException}: {nameof(Namespace)}") | ||
: _namespace ?? throw new NullReferenceException(); | ||
|
||
public bool WrapTimeToLiveHeaderPresent { get; private set; } | ||
private KeyValuePair<string, string>? _wrapttl; | ||
public KeyValuePair<string, string> WrapTimeToLive => WrapTimeToLiveHeaderPresent is false || _wrapttl is null | ||
? throw new InvalidOperationException($"{Resources.Resource.VaultHttpHeadersInvalidOperationException}: {nameof(WrapTimeToLive)}") | ||
: _wrapttl ?? throw new NullReferenceException(); | ||
|
||
HttpVaultHeaders IHttpVaultHeaders.Build(IReadOnlyDictionary<string, string> headers) => Build(headers); | ||
|
||
public static HttpVaultHeaders Build(IReadOnlyDictionary<string, string> headers) | ||
{ | ||
HttpVaultHeaders vault_http_headers = new(); | ||
foreach (KeyValuePair<string, string> kvp in headers) | ||
{ | ||
switch (kvp.Key) | ||
{ | ||
case HttpVaultHeaderKey.Request: | ||
{ | ||
vault_http_headers._request = new KeyValuePair<string, string>(HttpVaultHeaderKey.Request, kvp.Value); | ||
vault_http_headers.RequestHeaderPresent = true; | ||
break; | ||
} | ||
case HttpVaultHeaderKey.Token: | ||
{ | ||
vault_http_headers._token = new KeyValuePair<string, string>(HttpVaultHeaderKey.Token, kvp.Value); | ||
vault_http_headers.TokenHeaderPresent = true; | ||
break; | ||
} | ||
case HttpVaultHeaderKey.Namespace: | ||
{ | ||
vault_http_headers._namespace = new KeyValuePair<string, string>(HttpVaultHeaderKey.Namespace, kvp.Value); | ||
vault_http_headers.NamespaceHeaderPresent = true; | ||
break; | ||
} | ||
case HttpVaultHeaderKey.WrapTimeToLive: | ||
{ | ||
vault_http_headers._wrapttl = new KeyValuePair<string, string>(HttpVaultHeaderKey.WrapTimeToLive, kvp.Value); | ||
vault_http_headers.WrapTimeToLiveHeaderPresent = true; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return vault_http_headers; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using HashiVaultCs.Models.Requests.Auth.Approle; | ||
|
||
namespace HashiVaultCs.Interfaces.Auth; | ||
|
||
public interface IApproleClient : IVaultClient | ||
{ | ||
Task<Secret> LoginAsync(Login data, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default); | ||
Task<Secret> RoleIdAsync(string rolename, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default); | ||
Task<Secret> SecretIdAsync(string rolename, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using HashiVaultCs.Models.Requests.Auth.Userpass; | ||
|
||
namespace HashiVaultCs.Interfaces.Auth; | ||
|
||
public interface IUserpassClient : IVaultClient | ||
{ | ||
Task<Secret> LoginAsync(string username, Login data, IImmutableDictionary<string, string> headers, CancellationToken cancellationToken = default); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace HashiVaultCs.Interfaces; | ||
|
||
public interface IHttpVaultClient | ||
{ | ||
Task<JsonDocument> SendAsync(CancellationToken cancellationToken = default); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using HashiVaultCs; | ||
|
||
namespace HashiVaultCs.Interfaces; | ||
|
||
public interface IHttpVaultHeaders | ||
{ | ||
bool RequestHeaderPresent { get; } | ||
KeyValuePair<string, string> Request { get; } | ||
|
||
bool TokenHeaderPresent { get; } | ||
KeyValuePair<string, string> Token { get; } | ||
|
||
bool NamespaceHeaderPresent { get; } | ||
KeyValuePair<string, string> Namespace { get; } | ||
|
||
bool WrapTimeToLiveHeaderPresent { get; } | ||
KeyValuePair<string, string> WrapTimeToLive { get; } | ||
|
||
HttpVaultHeaders Build(IReadOnlyDictionary<string, string> headers); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace HashiVaultCs.Interfaces; | ||
|
||
public interface IVaultClient { } |
Oops, something went wrong.