Implement ledger metrics for observability and add tests for Ruby packages endpoints
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added `LedgerMetrics` class to record write latency and total events for ledger operations.
- Created comprehensive tests for Ruby packages endpoints, covering scenarios for missing inventory, successful retrieval, and identifier handling.
- Introduced `TestSurfaceSecretsScope` for managing environment variables during tests.
- Developed `ProvenanceMongoExtensions` for attaching DSSE provenance and trust information to event documents.
- Implemented `EventProvenanceWriter` and `EventWriter` classes for managing event provenance in MongoDB.
- Established MongoDB indexes for efficient querying of events based on provenance and trust.
- Added models and JSON parsing logic for DSSE provenance and trust information.
This commit is contained in:
master
2025-11-13 09:29:09 +02:00
parent 151f6b35cc
commit 61f963fd52
101 changed files with 5881 additions and 1776 deletions

View File

@@ -0,0 +1,99 @@
using System.Collections.Generic;
using System.Linq;
using MongoDB.Bson;
using StellaOps.Provenance.Mongo;
using Xunit;
namespace StellaOps.Events.Mongo.Tests;
public sealed class ProvenanceMongoExtensionsTests
{
[Fact]
public void AttachDsseProvenance_WritesNestedDocuments()
{
var document = new BsonDocument
{
{ "kind", "VEX" },
{ "subject", new BsonDocument("digest", new BsonDocument("sha256", "sha256:abc")) }
};
var dsse = new DsseProvenance
{
EnvelopeDigest = "sha256:deadbeef",
PayloadType = "application/vnd.in-toto+json",
Key = new DsseKeyInfo
{
KeyId = "cosign:SHA256-PKIX:TEST",
Issuer = "fulcio",
Algo = "ECDSA"
},
Rekor = new DsseRekorInfo
{
LogIndex = 123,
Uuid = Guid.Parse("2d4d5f7c-1111-4a01-b9cb-aa42022a0a8c").ToString(),
IntegratedTime = 1_699_999_999,
MirrorSeq = 10
},
Chain = new List<DsseChainLink>
{
new()
{
Type = "build",
Id = "att:build#1",
Digest = "sha256:chain"
}
}
};
var trust = new TrustInfo
{
Verified = true,
Verifier = "Authority@stella",
Witnesses = 2,
PolicyScore = 0.9
};
document.AttachDsseProvenance(dsse, trust);
var provenanceDoc = document["provenance"].AsBsonDocument["dsse"].AsBsonDocument;
Assert.Equal("sha256:deadbeef", provenanceDoc["envelopeDigest"].AsString);
Assert.Equal(123, provenanceDoc["rekor"].AsBsonDocument["logIndex"].AsInt64);
Assert.Equal("att:build#1", provenanceDoc["chain"].AsBsonArray.Single().AsBsonDocument["id"].AsString);
var trustDoc = document["trust"].AsBsonDocument;
Assert.True(trustDoc["verified"].AsBoolean);
Assert.Equal(2, trustDoc["witnesses"].AsInt32);
Assert.Equal(0.9, trustDoc["policyScore"].AsDouble);
}
[Fact]
public void BuildProvenVexFilter_TargetsKindSubjectAndVerified()
{
var filter = ProvenanceMongoExtensions.BuildProvenVexFilter("VEX", "sha256:123");
Assert.Equal("VEX", filter["kind"].AsString);
Assert.Equal("sha256:123", filter["subject.digest.sha256"].AsString);
Assert.True(filter.Contains("provenance.dsse.rekor.logIndex"));
Assert.True(filter.Contains("trust.verified"));
}
[Fact]
public void BuildUnprovenEvidenceFilter_FlagsMissingTrustOrRekor()
{
var filter = ProvenanceMongoExtensions.BuildUnprovenEvidenceFilter(new[] { "SBOM", "VEX" });
var kindClause = filter["kind"].AsBsonDocument["$in"].AsBsonArray.Select(v => v.AsString).ToArray();
Assert.Contains("SBOM", kindClause);
Assert.Contains("VEX", kindClause);
var orConditions = filter["$or"].AsBsonArray;
Assert.Equal(2, orConditions.Count);
var trustCondition = orConditions[0].AsBsonDocument;
Assert.Equal("$ne", trustCondition["trust.verified"].AsBsonDocument.Elements.Single().Name);
var rekorCondition = orConditions[1].AsBsonDocument;
Assert.Equal("$exists", rekorCondition["provenance.dsse.rekor.logIndex"].AsBsonDocument.Elements.Single().Name);
Assert.False(rekorCondition["provenance.dsse.rekor.logIndex"].AsBsonDocument["$exists"].AsBoolean);
}
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
<PackageReference Include="MongoDB.Driver" Version="3.5.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageReference Include="coverlet.collector" Version="6.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../StellaOps.Events.Mongo/StellaOps.Events.Mongo.csproj" />
</ItemGroup>
</Project>