Files
git.stella-ops.org/src/Scanner/__Libraries/StellaOps.Scanner.Surface.Secrets/Providers/FileSurfaceSecretProvider.cs

95 lines
2.7 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace StellaOps.Scanner.Surface.Secrets.Providers;
internal sealed class FileSurfaceSecretProvider : ISurfaceSecretProvider
{
private readonly string _root;
public FileSurfaceSecretProvider(string root)
{
if (string.IsNullOrWhiteSpace(root))
{
throw new ArgumentException("File secret provider root cannot be null or whitespace.", nameof(root));
}
_root = root;
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
var path = ResolvePath(request);
if (!File.Exists(path))
{
throw new SurfaceSecretNotFoundException(request);
}
var json = File.ReadAllText(path);
var descriptor = JsonSerializer.Deserialize<FileSecretDescriptor>(json);
if (descriptor is null)
{
throw new SurfaceSecretNotFoundException(request);
}
if (string.IsNullOrWhiteSpace(descriptor.Payload))
{
return SurfaceSecretHandle.Empty;
}
var bytes = Convert.FromBase64String(descriptor.Payload);
return SurfaceSecretHandle.FromBytes(bytes, descriptor.Metadata);
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
var path = ResolvePath(request);
if (!File.Exists(path))
{
throw new SurfaceSecretNotFoundException(request);
}
await using var stream = File.OpenRead(path);
var descriptor = await JsonSerializer.DeserializeAsync<FileSecretDescriptor>(stream, cancellationToken: cancellationToken).ConfigureAwait(false);
if (descriptor is null)
{
throw new SurfaceSecretNotFoundException(request);
}
if (string.IsNullOrWhiteSpace(descriptor.Payload))
{
return SurfaceSecretHandle.Empty;
}
var bytes = Convert.FromBase64String(descriptor.Payload);
return SurfaceSecretHandle.FromBytes(bytes, descriptor.Metadata);
}
private string ResolvePath(SurfaceSecretRequest request)
{
var name = request.Name ?? "default";
return Path.Combine(_root, request.Tenant, request.Component, request.SecretType, name + ".json");
}
private sealed class FileSecretDescriptor
{
public string? Payload { get; init; }
public Dictionary<string, string>? Metadata { get; init; }
}
}