aboutsummaryrefslogtreecommitdiff
path: root/lib/VNLib.Plugins.Extensions.Loading/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src')
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs46
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs2
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Secrets/SecretResult.cs11
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Secrets/VaultSecrets.cs28
4 files changed, 85 insertions, 2 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
index adfd997..ccb2341 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
@@ -167,6 +167,52 @@ namespace VNLib.Plugins.Extensions.Loading
}
/// <summary>
+ /// Gets a required configuration property from the specified configuration scope
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="config"></param>
+ /// <param name="property">The name of the property to get</param>
+ /// <param name="getter">A function to get the value from the json type</param>
+ /// <returns>The property value</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ public static T? GetProperty<T>(this IConfigScope config, string property, Func<JsonElement, T> getter)
+ {
+ //Check null
+ _ = config ?? throw new ArgumentNullException(nameof(config));
+ _ = property ?? throw new ArgumentNullException(nameof(property));
+ _ = getter ?? throw new ArgumentNullException(nameof(getter));
+
+ return !config.TryGetValue(property, out JsonElement el) ? default : getter(el);
+ }
+
+ /// <summary>
+ /// Gets a required configuration property from the specified configuration scope
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="config"></param>
+ /// <param name="property">The name of the property to get</param>
+ /// <param name="getter">A function to get the value from the json type</param>
+ /// <returns>The property value</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="KeyNotFoundException"></exception>
+ public static T GetRequiredProperty<T>(this IConfigScope config, string property, Func<JsonElement, T> getter)
+ {
+ //Check null
+ _ = config ?? throw new ArgumentNullException(nameof(config));
+ _ = property ?? throw new ArgumentNullException(nameof(property));
+ _ = getter ?? throw new ArgumentNullException(nameof(getter));
+
+ //Get the property
+ if(!config.TryGetValue(property, out JsonElement el))
+ {
+ throw new KeyNotFoundException($"Missing required configuration property '{property}'");
+ }
+
+ //Even if the getter returns null, throw
+ return getter(el) ?? throw new KeyNotFoundException($"Missing required configuration property '{property}'");
+ }
+
+ /// <summary>
/// Gets the configuration property name for the type
/// </summary>
/// <param name="type">The type to get the configuration name for</param>
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs
index 57e4a9c..40a52fc 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Events/EventManagment.cs
@@ -57,7 +57,7 @@ namespace VNLib.Plugins.Extensions.Loading.Events
{
plugin.ThrowIfUnloaded();
- plugin.Log.Verbose("Interval for {t} scheduled", interval);
+ plugin.Log.Verbose("Interval for {t} scheduled on type {rr}", interval, asyncCallback.Target);
//Run interval on plugins bg scheduler
_ = plugin.ObserveWork(() => RunIntervalOnPluginScheduler(plugin, asyncCallback, interval, immediate));
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/SecretResult.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/SecretResult.cs
index f2cbd28..c1e6b3d 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/SecretResult.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/SecretResult.cs
@@ -42,7 +42,14 @@ namespace VNLib.Plugins.Extensions.Loading
public ReadOnlySpan<char> Result => _secretChars;
- internal SecretResult(ReadOnlySpan<char> value) => _secretChars = value.ToArray();
+ internal SecretResult(ReadOnlySpan<char> value) : this(value.ToArray())
+ { }
+
+ private SecretResult(char[] secretChars)
+ {
+ _secretChars = secretChars;
+ }
+
///<inheritdoc/>
protected override void Free()
@@ -56,5 +63,7 @@ namespace VNLib.Plugins.Extensions.Loading
MemoryUtil.UnsafeZeroMemory<char>(result);
return res;
}
+
+ internal static SecretResult ToSecret(char[] result) => new(result);
}
}
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/VaultSecrets.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/VaultSecrets.cs
index 08af485..c2d830f 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/VaultSecrets.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Secrets/VaultSecrets.cs
@@ -23,9 +23,11 @@
*/
using System;
+using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
@@ -62,6 +64,7 @@ namespace VNLib.Plugins.Extensions.Loading
public const string VAULT_URL_SCHEME = "vault://";
public const string ENV_URL_SCHEME = "env://";
+ public const string FILE_URL_SCHEME = "file://";
/// <summary>
@@ -125,11 +128,36 @@ namespace VNLib.Plugins.Extensions.Loading
return Task.FromResult<ISecretResult?>(envVal == null ? null : new SecretResult(envVal));
}
+
+ //See if the secret is a file path
+ if (rawSecret.StartsWith(FILE_URL_SCHEME, StringComparison.OrdinalIgnoreCase))
+ {
+ string filePath = rawSecret[FILE_URL_SCHEME.Length..];
+ return GetSecretFromFileAsync(filePath, plugin.UnloadToken);
+ }
//Finally, return the raw value
return Task.FromResult<ISecretResult?>(new SecretResult(rawSecret.AsSpan()));
}
+ private static async Task<ISecretResult?> GetSecretFromFileAsync(string filePath, CancellationToken ct)
+ {
+ //read the file data
+ byte[] secretFileData = await File.ReadAllBytesAsync(filePath, ct);
+
+ //recover the character data from the file data
+ int chars = Encoding.UTF8.GetCharCount(secretFileData);
+ char[] secretFileChars = new char[chars];
+ Encoding.UTF8.GetChars(secretFileData, secretFileChars);
+
+ //Create secret from the file data
+ SecretResult sr = SecretResult.ToSecret(secretFileChars);
+
+ //Clear file data buffer
+ MemoryUtil.InitializeBlock(secretFileData.AsSpan());
+ return sr;
+ }
+
/// <summary>
/// Gets a secret at the given vault url (in the form of "vault://[mount-name]/[secret-path]?secret=[secret_name]")
/// </summary>