95 lines
4.0 KiB
C#
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);
|
|
}
|
|
}
|