diff options
author | vman <public@vaughnnugent.com> | 2022-12-28 14:15:04 -0500 |
---|---|---|
committer | vman <public@vaughnnugent.com> | 2022-12-28 14:15:04 -0500 |
commit | 0c2fa662f60cf8b6b771fef3ff4c740eae17a83d (patch) | |
tree | 91495d460ceb12fba8cc274e77a8cbf4019c028d /VNLib.Plugins.Extensions.Loading/VaultSecrets.cs | |
parent | 8b5f3eebb9f8d9bd55e922a809ffa3bd52e33401 (diff) |
Global cache client, asm loading, plugin local cache, and event managment
Diffstat (limited to 'VNLib.Plugins.Extensions.Loading/VaultSecrets.cs')
-rw-r--r-- | VNLib.Plugins.Extensions.Loading/VaultSecrets.cs | 100 |
1 files changed, 59 insertions, 41 deletions
diff --git a/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs b/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs index 468600f..cd67903 100644 --- a/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs +++ b/VNLib.Plugins.Extensions.Loading/VaultSecrets.cs @@ -26,10 +26,8 @@ using System; using System.Linq; using System.Text; using System.Text.Json; -using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; -using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using VaultSharp; @@ -64,8 +62,6 @@ namespace VNLib.Plugins.Extensions.Loading public const string VAULT_URL_SCHEME = "vault://"; - private static readonly ConditionalWeakTable<PluginBase, Lazy<IVaultClient?>> _vaults = new(); - /// <summary> /// <para> /// Gets a secret from the "secrets" element. @@ -135,7 +131,7 @@ namespace VNLib.Plugins.Extensions.Loading async Task<SecretResult?> execute() { //Try load client - IVaultClient? client = _vaults.GetValue(plugin, TryGetVaultLoader).Value; + IVaultClient? client = plugin.GetVault(); _ = client ?? throw new KeyNotFoundException("Vault client not found"); //run read async @@ -209,7 +205,7 @@ namespace VNLib.Plugins.Extensions.Loading async Task<X509Certificate?> execute() { //Try load client - IVaultClient? client = _vaults.GetValue(plugin, TryGetVaultLoader).Value; + IVaultClient? client = plugin.GetVault(); _ = client ?? throw new KeyNotFoundException("Vault client not found"); @@ -239,7 +235,7 @@ namespace VNLib.Plugins.Extensions.Loading /// <returns>The ambient <see cref="IVaultClient"/> if loaded, null otherwise</returns> /// <exception cref="KeyNotFoundException"></exception> /// <exception cref="ObjectDisposedException"></exception> - public static IVaultClient? GetVault(this PluginBase plugin) => _vaults.GetValue(plugin, TryGetVaultLoader).Value; + public static IVaultClient? GetVault(this PluginBase plugin) => LoadingExtensions.GetOrCreateSingleton(plugin, TryGetVaultLoader); private static string? TryGetSecretInternal(PluginBase plugin, string secretName) { @@ -283,47 +279,41 @@ namespace VNLib.Plugins.Extensions.Loading return conf != null && conf.TryGetValue(secretName, out JsonElement el) ? el.GetString() : null; } - private static Lazy<IVaultClient?> TryGetVaultLoader(PluginBase pbase) + private static IVaultClient? TryGetVaultLoader(PluginBase pbase) { - //Local func to load the vault client - IVaultClient? LoadVault() + //Get vault config + IReadOnlyDictionary<string, JsonElement>? conf = pbase.TryGetConfig(VAULT_OBJECT_NAME); + + if (conf == null) { - //Get vault config - IReadOnlyDictionary<string, JsonElement>? conf = pbase.TryGetConfig(VAULT_OBJECT_NAME); + return null; + } - if(conf == null) - { - return null; - } + //try get servre address creds from config + string? serverAddress = conf[VAULT_URL_KEY].GetString() ?? throw new KeyNotFoundException($"Failed to load the key {VAULT_URL_KEY} from object {VAULT_OBJECT_NAME}"); - //try get servre address creds from config - string? serverAddress = conf[VAULT_URL_KEY].GetString() ?? throw new KeyNotFoundException($"Failed to load the key {VAULT_URL_KEY} from object {VAULT_OBJECT_NAME}"); + IAuthMethodInfo authMethod; - IAuthMethodInfo authMethod; + //Get authentication method from config + if (conf.TryGetValue(VAULT_TOKEN_KEY, out JsonElement tokenEl)) + { + //Init token + authMethod = new TokenAuthMethodInfo(tokenEl.GetString()); + } + else if (conf.TryGetValue(VAULT_ROLE_KEY, out JsonElement roleEl) && conf.TryGetValue(VAULT_SECRET_KEY, out JsonElement secretEl)) + { + authMethod = new AppRoleAuthMethodInfo(roleEl.GetString(), secretEl.GetString()); + } + else + { + throw new KeyNotFoundException($"Failed to load the vault authentication method from {VAULT_OBJECT_NAME}"); + } - //Get authentication method from config - if (conf.TryGetValue(VAULT_TOKEN_KEY, out JsonElement tokenEl)) - { - //Init token - authMethod = new TokenAuthMethodInfo(tokenEl.GetString()); - } - else if(conf.TryGetValue(VAULT_ROLE_KEY, out JsonElement roleEl) && conf.TryGetValue(VAULT_SECRET_KEY, out JsonElement secretEl)) - { - authMethod = new AppRoleAuthMethodInfo(roleEl.GetString(), secretEl.GetString()); - } - else - { - throw new KeyNotFoundException($"Failed to load the vault authentication method from {VAULT_OBJECT_NAME}"); - } + //Settings + VaultClientSettings settings = new(serverAddress, authMethod); - //Settings - VaultClientSettings settings = new(serverAddress, authMethod); - - //create vault client - return new VaultClient(settings); - } - //init lazy - return new (LoadVault, LazyThreadSafetyMode.PublicationOnly); + //create vault client + return new VaultClient(settings); } /// <summary> @@ -355,6 +345,20 @@ namespace VNLib.Plugins.Extensions.Loading } /// <summary> + /// Converts the secret recovery task to + /// </summary> + /// <param name="secret"></param> + /// <returns>A task whos result the base64 decoded secret as a byte[]</returns> + /// <exception cref="ArgumentNullException"></exception> + /// <exception cref="InternalBufferTooSmallException"></exception> + public static async Task<byte[]?> ToBase64Bytes(this Task<SecretResult?> secret) + { + _ = secret ?? throw new ArgumentNullException(nameof(secret)); + using SecretResult? sec = await secret.ConfigureAwait(false); + return sec?.GetFromBase64(); + } + + /// <summary> /// Recovers a certificate from a PEM encoded secret /// </summary> /// <param name="secret"></param> @@ -431,5 +435,19 @@ namespace VNLib.Plugins.Extensions.Loading int count = Encoding.UTF8.GetBytes(secret.Result, buffer.Span); return new ReadOnlyJsonWebKey(buffer.Span[..count]); } + + /// <summary> + /// Gets a task that resolves a <see cref="ReadOnlyJsonWebKey"/> + /// from a <see cref="SecretResult"/> task + /// </summary> + /// <param name="secret"></param> + /// <returns>The <see cref="ReadOnlyJsonWebKey"/> from the secret, or null if the secret was not found</returns> + /// <exception cref="ArgumentNullException"></exception> + public static async Task<ReadOnlyJsonWebKey?> ToJsonWebKey(this Task<SecretResult?> secret) + { + _ = secret ?? throw new ArgumentNullException(nameof(secret)); + using SecretResult? sec = await secret.ConfigureAwait(false); + return sec?.GetJsonWebKey(); + } } } |