Restore vendor connector internals and configure offline packages
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
root
2025-10-20 14:50:58 +03:00
parent 09b6a28172
commit 44ad31591c
59 changed files with 7512 additions and 3797 deletions

View File

@@ -1,204 +1,205 @@
using System.Text;
using StellaOps.Zastava.Core.Contracts;
using StellaOps.Zastava.Core.Hashing;
using StellaOps.Zastava.Core.Serialization;
namespace StellaOps.Zastava.Core.Tests.Serialization;
public sealed class ZastavaCanonicalJsonSerializerTests
{
[Fact]
public void Serialize_RuntimeEventEnvelope_ProducesDeterministicOrdering()
{
var runtimeEvent = new RuntimeEvent
{
EventId = "evt-123",
When = DateTimeOffset.Parse("2025-10-19T12:34:56Z"),
Kind = RuntimeEventKind.ContainerStart,
Tenant = "tenant-01",
Node = "node-a",
Runtime = new RuntimeEngine
{
Engine = "containerd",
Version = "1.7.19"
},
Workload = new RuntimeWorkload
{
Platform = "kubernetes",
Namespace = "payments",
Pod = "api-7c9fbbd8b7-ktd84",
Container = "api",
ContainerId = "containerd://abc",
ImageRef = "ghcr.io/acme/api@sha256:abcd",
Owner = new RuntimeWorkloadOwner
{
Kind = "Deployment",
Name = "api"
}
},
Process = new RuntimeProcess
{
Pid = 12345,
Entrypoint = new[] { "/entrypoint.sh", "--serve" },
EntryTrace = new[]
{
new RuntimeEntryTrace
{
File = "/entrypoint.sh",
Line = 3,
Op = "exec",
Target = "/usr/bin/python3"
}
}
},
LoadedLibraries = new[]
{
new RuntimeLoadedLibrary
{
Path = "/lib/x86_64-linux-gnu/libssl.so.3",
Inode = 123456,
Sha256 = "abc123"
}
},
Posture = new RuntimePosture
{
ImageSigned = true,
SbomReferrer = "present",
Attestation = new RuntimeAttestation
{
Uuid = "rekor-uuid",
Verified = true
}
},
Delta = new RuntimeDelta
{
BaselineImageDigest = "sha256:abcd",
ChangedFiles = new[] { "/opt/app/server.py" },
NewBinaries = new[]
{
new RuntimeNewBinary
{
Path = "/usr/local/bin/helper",
Sha256 = "def456"
}
}
},
Evidence = new[]
{
new RuntimeEvidence
{
Signal = "procfs.maps",
Value = "/lib/.../libssl.so.3@0x7f..."
}
},
Annotations = new Dictionary<string, string>
{
["source"] = "unit-test"
}
};
var envelope = RuntimeEventEnvelope.Create(runtimeEvent, ZastavaContractVersions.RuntimeEvent);
var json = ZastavaCanonicalJsonSerializer.Serialize(envelope);
var expectedOrder = new[]
{
"\"schemaVersion\"",
"\"event\"",
"\"eventId\"",
"\"when\"",
"\"kind\"",
"\"tenant\"",
"\"node\"",
"\"runtime\"",
"\"engine\"",
"\"version\"",
"\"workload\"",
"\"platform\"",
"\"namespace\"",
"\"pod\"",
"\"container\"",
"\"containerId\"",
"\"imageRef\"",
"\"owner\"",
"\"kind\"",
"\"name\"",
"\"process\"",
"\"pid\"",
"\"entrypoint\"",
"\"entryTrace\"",
"\"loadedLibs\"",
"\"posture\"",
"\"imageSigned\"",
"\"sbomReferrer\"",
"\"attestation\"",
"\"uuid\"",
"\"verified\"",
"\"delta\"",
"\"baselineImageDigest\"",
"\"changedFiles\"",
"\"newBinaries\"",
"\"path\"",
"\"sha256\"",
"\"evidence\"",
"\"signal\"",
"\"value\"",
"\"annotations\"",
"\"source\""
};
var cursor = -1;
foreach (var token in expectedOrder)
{
var position = json.IndexOf(token, cursor + 1, StringComparison.Ordinal);
Assert.True(position > cursor, $"Property token {token} not found in the expected order.");
cursor = position;
}
Assert.DoesNotContain(" ", json, StringComparison.Ordinal);
Assert.StartsWith("{\"schemaVersion\"", json, StringComparison.Ordinal);
Assert.EndsWith("}}", json, StringComparison.Ordinal);
}
[Fact]
public void ComputeMultihash_ProducesStableBase64UrlDigest()
{
var decision = AdmissionDecisionEnvelope.Create(
new AdmissionDecision
{
AdmissionId = "admission-123",
Namespace = "payments",
PodSpecDigest = "sha256:deadbeef",
Images = new[]
{
new AdmissionImageVerdict
{
Name = "ghcr.io/acme/api:1.2.3",
Resolved = "ghcr.io/acme/api@sha256:abcd",
Signed = true,
HasSbomReferrers = true,
PolicyVerdict = PolicyVerdict.Pass,
Reasons = Array.Empty<string>(),
Rekor = new AdmissionRekorEvidence
{
Uuid = "xyz",
Verified = true
}
}
},
Decision = AdmissionDecisionOutcome.Allow,
TtlSeconds = 300
},
ZastavaContractVersions.AdmissionDecision);
var canonicalJson = ZastavaCanonicalJsonSerializer.Serialize(decision);
var expectedDigestBytes = SHA256.HashData(Encoding.UTF8.GetBytes(canonicalJson));
var expected = $"sha256-{Convert.ToBase64String(expectedDigestBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')}";
var hash = ZastavaHashing.ComputeMultihash(decision);
Assert.Equal(expected, hash);
var sha512 = ZastavaHashing.ComputeMultihash(Encoding.UTF8.GetBytes(canonicalJson), "sha512");
Assert.StartsWith("sha512-", sha512, StringComparison.Ordinal);
}
}
using System.Text;
using System.Security.Cryptography;
using StellaOps.Zastava.Core.Contracts;
using StellaOps.Zastava.Core.Hashing;
using StellaOps.Zastava.Core.Serialization;
namespace StellaOps.Zastava.Core.Tests.Serialization;
public sealed class ZastavaCanonicalJsonSerializerTests
{
[Fact]
public void Serialize_RuntimeEventEnvelope_ProducesDeterministicOrdering()
{
var runtimeEvent = new RuntimeEvent
{
EventId = "evt-123",
When = DateTimeOffset.Parse("2025-10-19T12:34:56Z"),
Kind = RuntimeEventKind.ContainerStart,
Tenant = "tenant-01",
Node = "node-a",
Runtime = new RuntimeEngine
{
Engine = "containerd",
Version = "1.7.19"
},
Workload = new RuntimeWorkload
{
Platform = "kubernetes",
Namespace = "payments",
Pod = "api-7c9fbbd8b7-ktd84",
Container = "api",
ContainerId = "containerd://abc",
ImageRef = "ghcr.io/acme/api@sha256:abcd",
Owner = new RuntimeWorkloadOwner
{
Kind = "Deployment",
Name = "api"
}
},
Process = new RuntimeProcess
{
Pid = 12345,
Entrypoint = new[] { "/entrypoint.sh", "--serve" },
EntryTrace = new[]
{
new RuntimeEntryTrace
{
File = "/entrypoint.sh",
Line = 3,
Op = "exec",
Target = "/usr/bin/python3"
}
}
},
LoadedLibraries = new[]
{
new RuntimeLoadedLibrary
{
Path = "/lib/x86_64-linux-gnu/libssl.so.3",
Inode = 123456,
Sha256 = "abc123"
}
},
Posture = new RuntimePosture
{
ImageSigned = true,
SbomReferrer = "present",
Attestation = new RuntimeAttestation
{
Uuid = "rekor-uuid",
Verified = true
}
},
Delta = new RuntimeDelta
{
BaselineImageDigest = "sha256:abcd",
ChangedFiles = new[] { "/opt/app/server.py" },
NewBinaries = new[]
{
new RuntimeNewBinary
{
Path = "/usr/local/bin/helper",
Sha256 = "def456"
}
}
},
Evidence = new[]
{
new RuntimeEvidence
{
Signal = "procfs.maps",
Value = "/lib/.../libssl.so.3@0x7f..."
}
},
Annotations = new Dictionary<string, string>
{
["source"] = "unit-test"
}
};
var envelope = RuntimeEventEnvelope.Create(runtimeEvent, ZastavaContractVersions.RuntimeEvent);
var json = ZastavaCanonicalJsonSerializer.Serialize(envelope);
var expectedOrder = new[]
{
"\"schemaVersion\"",
"\"event\"",
"\"eventId\"",
"\"when\"",
"\"kind\"",
"\"tenant\"",
"\"node\"",
"\"runtime\"",
"\"engine\"",
"\"version\"",
"\"workload\"",
"\"platform\"",
"\"namespace\"",
"\"pod\"",
"\"container\"",
"\"containerId\"",
"\"imageRef\"",
"\"owner\"",
"\"kind\"",
"\"name\"",
"\"process\"",
"\"pid\"",
"\"entrypoint\"",
"\"entryTrace\"",
"\"loadedLibs\"",
"\"posture\"",
"\"imageSigned\"",
"\"sbomReferrer\"",
"\"attestation\"",
"\"uuid\"",
"\"verified\"",
"\"delta\"",
"\"baselineImageDigest\"",
"\"changedFiles\"",
"\"newBinaries\"",
"\"path\"",
"\"sha256\"",
"\"evidence\"",
"\"signal\"",
"\"value\"",
"\"annotations\"",
"\"source\""
};
var cursor = -1;
foreach (var token in expectedOrder)
{
var position = json.IndexOf(token, cursor + 1, StringComparison.Ordinal);
Assert.True(position > cursor, $"Property token {token} not found in the expected order.");
cursor = position;
}
Assert.DoesNotContain(" ", json, StringComparison.Ordinal);
Assert.StartsWith("{\"schemaVersion\"", json, StringComparison.Ordinal);
Assert.EndsWith("}}", json, StringComparison.Ordinal);
}
[Fact]
public void ComputeMultihash_ProducesStableBase64UrlDigest()
{
var decision = AdmissionDecisionEnvelope.Create(
new AdmissionDecision
{
AdmissionId = "admission-123",
Namespace = "payments",
PodSpecDigest = "sha256:deadbeef",
Images = new[]
{
new AdmissionImageVerdict
{
Name = "ghcr.io/acme/api:1.2.3",
Resolved = "ghcr.io/acme/api@sha256:abcd",
Signed = true,
HasSbomReferrers = true,
PolicyVerdict = PolicyVerdict.Pass,
Reasons = Array.Empty<string>(),
Rekor = new AdmissionRekorEvidence
{
Uuid = "xyz",
Verified = true
}
}
},
Decision = AdmissionDecisionOutcome.Allow,
TtlSeconds = 300
},
ZastavaContractVersions.AdmissionDecision);
var canonicalJson = ZastavaCanonicalJsonSerializer.Serialize(decision);
var expectedDigestBytes = SHA256.HashData(Encoding.UTF8.GetBytes(canonicalJson));
var expected = $"sha256-{Convert.ToBase64String(expectedDigestBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')}";
var hash = ZastavaHashing.ComputeMultihash(decision);
Assert.Equal(expected, hash);
var sha512 = ZastavaHashing.ComputeMultihash(Encoding.UTF8.GetBytes(canonicalJson), "sha512");
Assert.StartsWith("sha512-", sha512, StringComparison.Ordinal);
}
}