feat(deployment): add secure Linux runtime (#17)
quality-gate / quality (push) Failing after 1m9s
quality-gate / container (push) Has been skipped

This commit is contained in:
KyuubiYoru
2026-07-16 15:03:04 +02:00
parent be732de7c9
commit 08729ae25c
23 changed files with 1941 additions and 28 deletions
@@ -40,18 +40,32 @@ internal sealed class SecretMaterial : IDisposable
internal sealed class EnvironmentSecretProvider : ISecretProvider
{
private const string Prefix = "env:";
private const string EnvironmentPrefix = "env:";
private const string FilePrefix = "file:";
private const int MaximumSecretBytes = 4096;
public bool TryGetSecret(string reference, out SecretMaterial? secret)
{
secret = null;
if (!reference.StartsWith(Prefix, StringComparison.Ordinal)
|| reference.Length == Prefix.Length)
if (reference.StartsWith(EnvironmentPrefix, StringComparison.Ordinal)
&& reference.Length > EnvironmentPrefix.Length)
{
return false;
return TryGetEnvironmentSecret(reference[EnvironmentPrefix.Length..], out secret);
}
string? encoded = Environment.GetEnvironmentVariable(reference[Prefix.Length..]);
if (reference.StartsWith(FilePrefix, StringComparison.Ordinal)
&& reference.Length > FilePrefix.Length)
{
return TryGetFileSecret(reference[FilePrefix.Length..], out secret);
}
return false;
}
private static bool TryGetEnvironmentSecret(string variableName, out SecretMaterial? secret)
{
secret = null;
string? encoded = Environment.GetEnvironmentVariable(variableName);
if (string.IsNullOrEmpty(encoded))
{
return false;
@@ -60,6 +74,12 @@ internal sealed class EnvironmentSecretProvider : ISecretProvider
try
{
byte[] bytes = Convert.FromBase64String(encoded);
if (bytes.Length is 0 or > MaximumSecretBytes)
{
CryptographicOperations.ZeroMemory(bytes);
return false;
}
secret = new SecretMaterial(bytes);
CryptographicOperations.ZeroMemory(bytes);
return true;
@@ -69,6 +89,47 @@ internal sealed class EnvironmentSecretProvider : ISecretProvider
return false;
}
}
private static bool TryGetFileSecret(string path, out SecretMaterial? secret)
{
secret = null;
byte[]? bytes = null;
try
{
FileInfo file = new(path);
if (!file.Exists
|| !Path.IsPathFullyQualified(path)
|| file.LinkTarget is not null
|| file.Length is <= 0 or > MaximumSecretBytes)
{
return false;
}
bytes = File.ReadAllBytes(path);
if (bytes.Length is 0 or > MaximumSecretBytes)
{
return false;
}
secret = new SecretMaterial(bytes);
return true;
}
catch (Exception exception) when (exception is IOException
or UnauthorizedAccessException
or ArgumentException
or NotSupportedException
or System.Security.SecurityException)
{
return false;
}
finally
{
if (bytes is not null)
{
CryptographicOperations.ZeroMemory(bytes);
}
}
}
}
internal sealed class EphemeralDevelopmentSecretProvider : ISecretProvider, IDisposable