feat(secrets): Implement secret leak policies and signal binding
- Added `spl-secret-block@1.json` to block deployments with critical or high severity secret findings. - Introduced `spl-secret-warn@1.json` to warn on secret findings without blocking deployments. - Created `SecretSignalBinder.cs` to bind secret evidence to policy evaluation signals. - Developed unit tests for `SecretEvidenceContext` and `SecretSignalBinder` to ensure correct functionality. - Enhanced `SecretSignalContextExtensions` to integrate secret evidence into signal contexts.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
using StellaOps.Determinism;
|
||||
using StellaOps.Infrastructure.Postgres.Repositories;
|
||||
using StellaOps.Scheduler.Persistence.Postgres.Models;
|
||||
|
||||
@@ -10,12 +11,21 @@ namespace StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
||||
/// </summary>
|
||||
public sealed class FailureSignatureRepository : RepositoryBase<SchedulerDataSource>, IFailureSignatureRepository
|
||||
{
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new failure signature repository.
|
||||
/// </summary>
|
||||
public FailureSignatureRepository(SchedulerDataSource dataSource, ILogger<FailureSignatureRepository> logger)
|
||||
public FailureSignatureRepository(
|
||||
SchedulerDataSource dataSource,
|
||||
ILogger<FailureSignatureRepository> logger,
|
||||
TimeProvider? timeProvider = null,
|
||||
IGuidProvider? guidProvider = null)
|
||||
: base(dataSource, logger)
|
||||
{
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -332,7 +342,7 @@ public sealed class FailureSignatureRepository : RepositoryBase<SchedulerDataSou
|
||||
AND resolved_at < @cutoff
|
||||
""";
|
||||
|
||||
var cutoff = DateTimeOffset.UtcNow.Subtract(olderThan);
|
||||
var cutoff = _timeProvider.GetUtcNow().Subtract(olderThan);
|
||||
|
||||
await using var connection = await DataSource.OpenConnectionAsync(tenantId, "writer", cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
@@ -389,7 +399,7 @@ public sealed class FailureSignatureRepository : RepositoryBase<SchedulerDataSou
|
||||
|
||||
private void AddSignatureParameters(NpgsqlCommand command, FailureSignatureEntity signature)
|
||||
{
|
||||
AddParameter(command, "signature_id", signature.SignatureId == Guid.Empty ? Guid.NewGuid() : signature.SignatureId);
|
||||
AddParameter(command, "signature_id", signature.SignatureId == Guid.Empty ? _guidProvider.NewGuid() : signature.SignatureId);
|
||||
AddParameter(command, "tenant_id", signature.TenantId);
|
||||
AddParameter(command, "scope_type", signature.ScopeType.ToString().ToLowerInvariant());
|
||||
AddParameter(command, "scope_id", signature.ScopeId);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json;
|
||||
using Dapper;
|
||||
using StellaOps.Determinism;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Infrastructure.Postgres.Connections;
|
||||
|
||||
@@ -8,11 +9,13 @@ namespace StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
||||
public sealed class ImpactSnapshotRepository : IImpactSnapshotRepository
|
||||
{
|
||||
private readonly SchedulerDataSource _dataSource;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
private readonly JsonSerializerOptions _serializer = CanonicalJsonSerializer.Settings;
|
||||
|
||||
public ImpactSnapshotRepository(SchedulerDataSource dataSource)
|
||||
public ImpactSnapshotRepository(SchedulerDataSource dataSource, IGuidProvider? guidProvider = null)
|
||||
{
|
||||
_dataSource = dataSource ?? throw new ArgumentNullException(nameof(dataSource));
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
public async Task UpsertAsync(ImpactSet snapshot, CancellationToken cancellationToken = default)
|
||||
@@ -29,7 +32,7 @@ ON CONFLICT (snapshot_id) DO UPDATE SET impact = EXCLUDED.impact;
|
||||
|
||||
await conn.ExecuteAsync(sql, new
|
||||
{
|
||||
SnapshotId = snapshot.SnapshotId ?? $"impact::{Guid.NewGuid():N}",
|
||||
SnapshotId = snapshot.SnapshotId ?? $"impact::{_guidProvider.NewGuid():N}",
|
||||
TenantId = tenantId,
|
||||
Impact = JsonSerializer.Serialize(snapshot, _serializer)
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
using StellaOps.Determinism;
|
||||
using StellaOps.Infrastructure.Postgres.Repositories;
|
||||
using StellaOps.Scheduler.Persistence.Postgres.Models;
|
||||
|
||||
@@ -10,12 +11,21 @@ namespace StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
||||
/// </summary>
|
||||
public sealed class JobRepository : RepositoryBase<SchedulerDataSource>, IJobRepository
|
||||
{
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new job repository.
|
||||
/// </summary>
|
||||
public JobRepository(SchedulerDataSource dataSource, ILogger<JobRepository> logger)
|
||||
public JobRepository(
|
||||
SchedulerDataSource dataSource,
|
||||
ILogger<JobRepository> logger,
|
||||
TimeProvider? timeProvider = null,
|
||||
IGuidProvider? guidProvider = null)
|
||||
: base(dataSource, logger)
|
||||
{
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -123,8 +133,8 @@ public sealed class JobRepository : RepositoryBase<SchedulerDataSource>, IJobRep
|
||||
TimeSpan leaseDuration,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var leaseId = Guid.NewGuid();
|
||||
var leaseUntil = DateTimeOffset.UtcNow.Add(leaseDuration);
|
||||
var leaseId = _guidProvider.NewGuid();
|
||||
var leaseUntil = _timeProvider.GetUtcNow().Add(leaseDuration);
|
||||
|
||||
const string sql = """
|
||||
UPDATE scheduler.jobs
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Npgsql;
|
||||
using StellaOps.Determinism;
|
||||
using StellaOps.Infrastructure.Postgres.Repositories;
|
||||
using StellaOps.Scheduler.Persistence.Postgres.Models;
|
||||
|
||||
@@ -10,12 +11,18 @@ namespace StellaOps.Scheduler.Persistence.Postgres.Repositories;
|
||||
/// </summary>
|
||||
public sealed class TriggerRepository : RepositoryBase<SchedulerDataSource>, ITriggerRepository
|
||||
{
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new trigger repository.
|
||||
/// </summary>
|
||||
public TriggerRepository(SchedulerDataSource dataSource, ILogger<TriggerRepository> logger)
|
||||
public TriggerRepository(
|
||||
SchedulerDataSource dataSource,
|
||||
ILogger<TriggerRepository> logger,
|
||||
IGuidProvider? guidProvider = null)
|
||||
: base(dataSource, logger)
|
||||
{
|
||||
_guidProvider = guidProvider ?? SystemGuidProvider.Instance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -125,7 +132,7 @@ public sealed class TriggerRepository : RepositoryBase<SchedulerDataSource>, ITr
|
||||
RETURNING *
|
||||
""";
|
||||
|
||||
var id = trigger.Id == Guid.Empty ? Guid.NewGuid() : trigger.Id;
|
||||
var id = trigger.Id == Guid.Empty ? _guidProvider.NewGuid() : trigger.Id;
|
||||
await using var connection = await DataSource.OpenConnectionAsync(trigger.TenantId, "writer", cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
await using var command = CreateCommand(sql, connection);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Scheduler.Models\StellaOps.Scheduler.Models.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Determinism.Abstractions\StellaOps.Determinism.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.Postgres\StellaOps.Infrastructure.Postgres.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.EfCore\StellaOps.Infrastructure.EfCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user