notify doctors work, audit work, new product advisory sprints

This commit is contained in:
master
2026-01-13 08:36:29 +02:00
parent b8868a5f13
commit 9ca7cb183e
343 changed files with 24492 additions and 3544 deletions

View File

@@ -4,6 +4,8 @@ namespace StellaOps.Scanner.Surface.Secrets;
public interface ISurfaceSecretProvider
{
SurfaceSecretHandle Get(SurfaceSecretRequest request);
ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default);

View File

@@ -29,6 +29,50 @@ internal sealed class AuditingSurfaceSecretProvider : ISurfaceSecretProvider
_componentName = componentName ?? throw new ArgumentNullException(nameof(componentName));
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
var startTime = _timeProvider.GetUtcNow();
try
{
var handle = _inner.Get(request);
var elapsed = _timeProvider.GetUtcNow() - startTime;
LogAuditEvent(
request,
handle.Metadata,
success: true,
elapsed,
error: null);
return handle;
}
catch (SurfaceSecretNotFoundException)
{
var elapsed = _timeProvider.GetUtcNow() - startTime;
LogAuditEvent(
request,
metadata: null,
success: false,
elapsed,
error: "NotFound");
throw;
}
catch (Exception ex)
{
var elapsed = _timeProvider.GetUtcNow() - startTime;
LogAuditEvent(
request,
metadata: null,
success: false,
elapsed,
error: ex.GetType().Name);
throw;
}
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)

View File

@@ -35,6 +35,25 @@ internal sealed class CachingSurfaceSecretProvider : ISurfaceSecretProvider
public TimeSpan CacheTtl => _ttl;
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
var key = BuildCacheKey(request);
var now = _timeProvider.GetUtcNow();
if (_cache.TryGetValue(key, out var entry) && entry.ExpiresAt > now)
{
_logger.LogDebug("Surface secret cache hit for {Key}.", key);
return entry.Handle;
}
var handle = _inner.Get(request);
var newEntry = new CacheEntry(handle, now.Add(_ttl));
_cache[key] = newEntry;
_logger.LogDebug("Surface secret cached for {Key}, expires at {ExpiresAt}.", key, newEntry.ExpiresAt);
return handle;
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)

View File

@@ -18,6 +18,23 @@ internal sealed class CompositeSurfaceSecretProvider : ISurfaceSecretProvider
}
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
foreach (var provider in _providers)
{
try
{
return provider.Get(request);
}
catch (SurfaceSecretNotFoundException)
{
// try next provider
}
}
throw new SurfaceSecretNotFoundException(request);
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)

View File

@@ -20,6 +20,35 @@ internal sealed class FileSurfaceSecretProvider : ISurfaceSecretProvider
_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)

View File

@@ -21,6 +21,21 @@ public sealed class InMemorySurfaceSecretProvider : ISurfaceSecretProvider
_secrets[request.CacheKey] = handle;
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (_secrets.TryGetValue(request.CacheKey, out var handle))
{
return handle;
}
throw new SurfaceSecretNotFoundException(request);
}
public ValueTask<SurfaceSecretHandle> GetAsync(SurfaceSecretRequest request, CancellationToken cancellationToken = default)
{
if (request is null)

View File

@@ -14,6 +14,30 @@ internal sealed class InlineSurfaceSecretProvider : ISurfaceSecretProvider
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
if (!_configuration.AllowInline)
{
throw new SurfaceSecretNotFoundException(request);
}
var envKey = BuildEnvironmentKey(request);
var value = Environment.GetEnvironmentVariable(envKey);
if (string.IsNullOrWhiteSpace(value))
{
throw new SurfaceSecretNotFoundException(request);
}
var bytes = Convert.FromBase64String(value);
var metadata = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["source"] = "inline-env",
["key"] = envKey
};
return SurfaceSecretHandle.FromBytes(bytes, metadata);
}
public ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)

View File

@@ -23,6 +23,30 @@ internal sealed class KubernetesSurfaceSecretProvider : ISurfaceSecretProvider
}
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
var directory = Path.Combine(_configuration.Root!, request.Tenant, request.Component, request.SecretType);
if (!Directory.Exists(directory))
{
_logger.LogDebug("Kubernetes secret directory {Directory} not found.", directory);
throw new SurfaceSecretNotFoundException(request);
}
var name = request.Name ?? "default";
var payloadPath = Path.Combine(directory, name);
if (!File.Exists(payloadPath))
{
throw new SurfaceSecretNotFoundException(request);
}
var bytes = File.ReadAllBytes(payloadPath);
return SurfaceSecretHandle.FromBytes(bytes, new Dictionary<string, string>
{
["source"] = "kubernetes",
["path"] = payloadPath
});
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)

View File

@@ -42,6 +42,73 @@ internal sealed class OfflineSurfaceSecretProvider : ISurfaceSecretProvider
}
}
public SurfaceSecretHandle Get(SurfaceSecretRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
var directory = Path.Combine(_root, request.Tenant, request.Component, request.SecretType);
if (!Directory.Exists(directory))
{
_logger.LogDebug("Offline secret directory {Directory} not found.", directory);
throw new SurfaceSecretNotFoundException(request);
}
// Deterministic selection: if name is specified use it, otherwise pick lexicographically smallest
var targetName = request.Name ?? SelectDeterministicName(directory);
if (targetName is null)
{
throw new SurfaceSecretNotFoundException(request);
}
var path = Path.Combine(directory, targetName + ".json");
if (!File.Exists(path))
{
throw new SurfaceSecretNotFoundException(request);
}
var json = File.ReadAllText(path);
var descriptor = JsonSerializer.Deserialize<OfflineSecretDescriptor>(json);
if (descriptor is null)
{
throw new SurfaceSecretNotFoundException(request);
}
if (string.IsNullOrWhiteSpace(descriptor.Payload))
{
return SurfaceSecretHandle.Empty;
}
var bytes = Convert.FromBase64String(descriptor.Payload);
// Verify integrity if manifest entry exists
var manifestKey = BuildManifestKey(request.Tenant, request.Component, request.SecretType, targetName);
if (_manifest?.TryGetValue(manifestKey, out var entry) == true)
{
var actualHash = ComputeSha256(bytes);
if (!string.Equals(actualHash, entry.Sha256, StringComparison.OrdinalIgnoreCase))
{
_logger.LogError(
"Offline secret integrity check failed for {Key}. Expected {Expected}, got {Actual}.",
manifestKey,
entry.Sha256,
actualHash);
throw new InvalidOperationException($"Offline secret integrity check failed for {manifestKey}.");
}
_logger.LogDebug("Offline secret integrity verified for {Key}.", manifestKey);
}
var metadata = descriptor.Metadata ?? new Dictionary<string, string>();
metadata["source"] = "offline";
metadata["path"] = path;
metadata["name"] = targetName;
return SurfaceSecretHandle.FromBytes(bytes, metadata);
}
public async ValueTask<SurfaceSecretHandle> GetAsync(
SurfaceSecretRequest request,
CancellationToken cancellationToken = default)