Files
git.stella-ops.org/src/Policy/__Tests/StellaOps.Policy.Tests/SplCanonicalizerTests.cs

95 lines
4.0 KiB
C#

using StellaOps.Policy;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Policy.Tests;
public class SplCanonicalizerTests
{
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Canonicalize_SortsStatementsActionsAndConditions()
{
const string input = """
{
"kind": "Policy",
"apiVersion": "spl.stellaops/v1",
"spec": {
"statements": [
{
"effect": "deny",
"id": "B-2",
"match": {
"resource": "/accounts/*",
"actions": ["delete", "read"]
}
},
{
"description": "desc",
"effect": "allow",
"id": "A-1",
"match": {
"actions": ["write", "read"],
"resource": "/accounts/*",
"conditions": [
{"operator": "gte", "value": 2, "field": "tier"},
{"field": "env", "value": "prod", "operator": "eq"}
]
},
"audit": {"severity": "warn", "message": "audit msg"}
}
],
"defaultEffect": "deny"
},
"metadata": {
"labels": {"env": "prod"},
"annotations": {"a": "1"},
"name": "demo"
}
}
""";
var canonical = SplCanonicalizer.CanonicalizeToString(input);
const string expected = "{\"apiVersion\":\"spl.stellaops/v1\",\"kind\":\"Policy\",\"metadata\":{\"annotations\":{\"a\":\"1\"},\"labels\":{\"env\":\"prod\"},\"name\":\"demo\"},\"spec\":{\"defaultEffect\":\"deny\",\"statements\":[{\"audit\":{\"message\":\"audit msg\",\"severity\":\"warn\"},\"description\":\"desc\",\"effect\":\"allow\",\"id\":\"A-1\",\"match\":{\"actions\":[\"read\",\"write\"],\"conditions\":[{\"field\":\"env\",\"operator\":\"eq\",\"value\":\"prod\"},{\"field\":\"tier\",\"operator\":\"gte\",\"value\":2}],\"resource\":\"/accounts/*\"}},{\"effect\":\"deny\",\"id\":\"B-2\",\"match\":{\"actions\":[\"delete\",\"read\"],\"resource\":\"/accounts/*\"}}]}}";
Assert.Equal(expected, canonical);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void ComputeDigest_IgnoresOrderingNoise()
{
const string versionA = """
{"apiVersion":"spl.stellaops/v1","kind":"Policy","metadata":{"name":"demo"},"spec":{"defaultEffect":"deny","statements":[{"id":"B","effect":"deny","match":{"resource":"/r","actions":["write","read"]}},{"id":"A","effect":"allow","match":{"resource":"/r","actions":["read"],"conditions":[{"field":"env","operator":"eq","value":"prod"}]}}]}}
""";
const string versionB = """
{"spec":{"statements":[{"match":{"actions":["read"],"resource":"/r","conditions":[{"value":"prod","operator":"eq","field":"env"}]},"effect":"allow","id":"A"},{"match":{"actions":["read","write"],"resource":"/r"},"effect":"deny","id":"B"}],"defaultEffect":"deny"},"kind":"Policy","metadata":{"name":"demo"},"apiVersion":"spl.stellaops/v1"}
""";
var hashA = SplCanonicalizer.ComputeDigest(versionA);
var hashB = SplCanonicalizer.ComputeDigest(versionB);
Assert.Equal(hashA, hashB);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void ComputeDigest_DetectsContentChange()
{
const string baseDoc = """
{"apiVersion":"spl.stellaops/v1","kind":"Policy","metadata":{"name":"demo"},"spec":{"statements":[{"id":"A","effect":"allow","match":{"resource":"/r","actions":["read"]}}]}}
""";
const string changedDoc = """
{"apiVersion":"spl.stellaops/v1","kind":"Policy","metadata":{"name":"demo"},"spec":{"statements":[{"id":"A","effect":"allow","match":{"resource":"/r","actions":["read","write"]}}]}}
""";
var original = SplCanonicalizer.ComputeDigest(baseDoc);
var changed = SplCanonicalizer.ComputeDigest(changedDoc);
Assert.NotEqual(original, changed);
}
}