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.
143 lines
4.5 KiB
C#
143 lines
4.5 KiB
C#
using MongoDB.Bson;
|
|
|
|
namespace StellaOps.Provenance.Mongo;
|
|
|
|
public static class ProvenanceMongoExtensions
|
|
{
|
|
private const string ProvenanceFieldName = "provenance";
|
|
private const string DsseFieldName = "dsse";
|
|
private const string TrustFieldName = "trust";
|
|
private const string ChainFieldName = "chain";
|
|
private static BsonValue StringOrNull(string? value) =>
|
|
value is null ? BsonNull.Value : new BsonString(value);
|
|
|
|
/// <summary>
|
|
/// Attach DSSE provenance + trust info to an event document in-place.
|
|
/// Designed for generic BsonDocument-based event envelopes.
|
|
/// </summary>
|
|
public static BsonDocument AttachDsseProvenance(
|
|
this BsonDocument eventDoc,
|
|
DsseProvenance dsse,
|
|
TrustInfo trust)
|
|
{
|
|
if (eventDoc is null) throw new ArgumentNullException(nameof(eventDoc));
|
|
if (dsse is null) throw new ArgumentNullException(nameof(dsse));
|
|
if (trust is null) throw new ArgumentNullException(nameof(trust));
|
|
|
|
var dsseDoc = new BsonDocument
|
|
{
|
|
{ "envelopeDigest", dsse.EnvelopeDigest },
|
|
{ "payloadType", dsse.PayloadType },
|
|
{ "key", new BsonDocument
|
|
{
|
|
{ "keyId", dsse.Key.KeyId },
|
|
{ "issuer", StringOrNull(dsse.Key.Issuer) },
|
|
{ "algo", StringOrNull(dsse.Key.Algo) }
|
|
}
|
|
}
|
|
};
|
|
|
|
if (dsse.Rekor is not null)
|
|
{
|
|
var rekorDoc = new BsonDocument
|
|
{
|
|
{ "logIndex", dsse.Rekor.LogIndex },
|
|
{ "uuid", dsse.Rekor.Uuid }
|
|
};
|
|
|
|
if (dsse.Rekor.IntegratedTime is not null)
|
|
rekorDoc.Add("integratedTime", dsse.Rekor.IntegratedTime);
|
|
|
|
if (dsse.Rekor.MirrorSeq is not null)
|
|
rekorDoc.Add("mirrorSeq", dsse.Rekor.MirrorSeq);
|
|
|
|
dsseDoc.Add("rekor", rekorDoc);
|
|
}
|
|
|
|
if (dsse.Chain is not null && dsse.Chain.Count > 0)
|
|
{
|
|
var chainArray = new BsonArray();
|
|
foreach (var link in dsse.Chain)
|
|
{
|
|
chainArray.Add(new BsonDocument
|
|
{
|
|
{ "type", link.Type },
|
|
{ "id", link.Id },
|
|
{ "digest", link.Digest }
|
|
});
|
|
}
|
|
|
|
dsseDoc.Add(ChainFieldName, chainArray);
|
|
}
|
|
|
|
var trustDoc = new BsonDocument
|
|
{
|
|
{ "verified", trust.Verified },
|
|
{ "verifier", StringOrNull(trust.Verifier) }
|
|
};
|
|
|
|
if (trust.Witnesses is not null)
|
|
trustDoc.Add("witnesses", trust.Witnesses);
|
|
|
|
if (trust.PolicyScore is not null)
|
|
trustDoc.Add("policyScore", trust.PolicyScore);
|
|
|
|
var provenanceDoc = new BsonDocument
|
|
{
|
|
{ DsseFieldName, dsseDoc }
|
|
};
|
|
|
|
eventDoc[ProvenanceFieldName] = provenanceDoc;
|
|
eventDoc[TrustFieldName] = trustDoc;
|
|
|
|
return eventDoc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper to query for "cryptographically proven" events:
|
|
/// kind + subject.digest.sha256 + presence of Rekor logIndex + trust.verified = true.
|
|
/// </summary>
|
|
public static BsonDocument BuildProvenVexFilter(
|
|
string kind,
|
|
string subjectDigestSha256)
|
|
{
|
|
return new BsonDocument
|
|
{
|
|
{ "kind", kind },
|
|
{ "subject.digest.sha256", subjectDigestSha256 },
|
|
{ $"{ProvenanceFieldName}.{DsseFieldName}.rekor.logIndex", new BsonDocument("$exists", true) },
|
|
{ $"{TrustFieldName}.verified", true }
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper to query for events influencing policy without solid provenance.
|
|
/// </summary>
|
|
public static BsonDocument BuildUnprovenEvidenceFilter(
|
|
IEnumerable<string> kinds)
|
|
{
|
|
var kindsArray = new BsonArray(kinds);
|
|
|
|
return new BsonDocument
|
|
{
|
|
{
|
|
"kind", new BsonDocument("$in", kindsArray)
|
|
},
|
|
{
|
|
"$or", new BsonArray
|
|
{
|
|
new BsonDocument
|
|
{
|
|
{ $"{TrustFieldName}.verified", new BsonDocument("$ne", true) }
|
|
},
|
|
new BsonDocument
|
|
{
|
|
{ $"{ProvenanceFieldName}.{DsseFieldName}.rekor.logIndex",
|
|
new BsonDocument("$exists", false) }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|