Restore vendor connector internals and configure offline packages
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user