92 lines
3.1 KiB
C#
92 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.Json;
|
|
using FluentAssertions;
|
|
using StellaOps.Cryptography;
|
|
using StellaOps.Provenance.Attestation;
|
|
using StellaOps.TestKit;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.Provenance.Attestation.Tests;
|
|
|
|
public class SampleStatementDigestTests
|
|
{
|
|
private readonly ICryptoHash _cryptoHash = DefaultCryptoHash.CreateForTests();
|
|
|
|
private static readonly JsonSerializerOptions SerializerOptions = new()
|
|
{
|
|
PropertyNamingPolicy = null,
|
|
WriteIndented = false
|
|
};
|
|
|
|
private static string RepoRoot
|
|
{
|
|
get
|
|
{
|
|
var dir = AppContext.BaseDirectory;
|
|
while (!string.IsNullOrEmpty(dir))
|
|
{
|
|
var candidate = Path.Combine(dir, "samples", "provenance");
|
|
if (Directory.Exists(candidate))
|
|
{
|
|
return dir;
|
|
}
|
|
|
|
var parent = Directory.GetParent(dir);
|
|
dir = parent?.FullName ?? string.Empty;
|
|
}
|
|
|
|
throw new DirectoryNotFoundException("Could not locate repository root containing samples/provenance.");
|
|
}
|
|
}
|
|
|
|
private static IEnumerable<(string Name, BuildStatement Statement)> LoadSamples()
|
|
{
|
|
var samplesDir = Path.Combine(RepoRoot, "samples", "provenance");
|
|
foreach (var path in Directory.EnumerateFiles(samplesDir, "*.json").OrderBy(p => p, StringComparer.Ordinal))
|
|
{
|
|
var json = File.ReadAllText(path);
|
|
var statement = JsonSerializer.Deserialize<BuildStatement>(json, SerializerOptions);
|
|
if (statement is null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
yield return (Path.GetFileName(path), statement);
|
|
}
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Hashes_match_expected_samples()
|
|
{
|
|
// Expected hashes using FIPS profile (SHA-256 for attestation purpose)
|
|
var expectations = new Dictionary<string, string>(StringComparer.Ordinal)
|
|
{
|
|
["build-statement-sample.json"] = "3d9f673803f711940f47c85b33ad9776dc90bdfaf58922903cc9bd401b9f56b0",
|
|
["export-service-statement.json"] = "fa73e8664566d45497d4c18d439b42ff38b1ed6e3e25ca8e29001d1201f1d41b",
|
|
["job-runner-statement.json"] = "27a5b433c320fed2984166641390953d02b9204ed1d75076ec9c000e04f3a82a",
|
|
["orchestrator-statement.json"] = "d79467d03da33d0b8f848d7a340c8cde845802bad7dadcb553125e8553615b28"
|
|
};
|
|
|
|
foreach (var (name, statement) in LoadSamples())
|
|
{
|
|
BuildStatementDigest.ComputeHashHex(_cryptoHash, statement)
|
|
.Should()
|
|
.Be(expectations[name], because: $"{name} hash must be deterministic");
|
|
}
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void Merkle_root_is_stable_across_sample_set()
|
|
{
|
|
var statements = LoadSamples().Select(pair => pair.Statement).ToArray();
|
|
BuildStatementDigest.ComputeMerkleRootHex(_cryptoHash, statements)
|
|
.Should()
|
|
.Be("958465d432c9c8497f9ea5c1476cc7f2bea2a87d3ca37d8293586bf73922dd73");
|
|
}
|
|
}
|