182 lines
6.9 KiB
C#
182 lines
6.9 KiB
C#
// SPDX-License-Identifier: BUSL-1.1
|
|
// Sprint: SPRINT_5200_0001_0001 - Starter Policy Template
|
|
// Task: T6 - Starter Policy Tests
|
|
|
|
using System.Text.Json;
|
|
using System.Text.Json.Nodes;
|
|
using FluentAssertions;
|
|
using Json.Schema;
|
|
using YamlDotNet.Serialization;
|
|
|
|
using StellaOps.TestKit;
|
|
namespace StellaOps.Policy.Pack.Tests;
|
|
|
|
public class StarterPolicyPackTests
|
|
{
|
|
private readonly string _testDataPath;
|
|
private readonly IDeserializer _yamlDeserializer;
|
|
|
|
public StarterPolicyPackTests()
|
|
{
|
|
_testDataPath = Path.Combine(AppContext.BaseDirectory, "TestData");
|
|
_yamlDeserializer = new DeserializerBuilder()
|
|
.WithNamingConvention(YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention.Instance)
|
|
.Build();
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_Exists()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
File.Exists(policyPath).Should().BeTrue("starter-day1.yaml should exist");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasValidYamlStructure()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
|
|
var act = () => _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
act.Should().NotThrow("YAML should be valid and parseable");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasRequiredFields()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
policy.Should().ContainKey("apiVersion", "Policy should have apiVersion field");
|
|
policy.Should().ContainKey("kind", "Policy should have kind field");
|
|
policy.Should().ContainKey("metadata", "Policy should have metadata field");
|
|
policy.Should().ContainKey("spec", "Policy should have spec field");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasCorrectApiVersion()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
policy["apiVersion"].Should().Be("policy.stellaops.io/v1");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasCorrectKind()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
policy["kind"].Should().Be("PolicyPack");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasValidMetadata()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
var metadata = policy["metadata"] as Dictionary<object, object>;
|
|
metadata.Should().NotBeNull();
|
|
metadata!.Should().ContainKey("name");
|
|
metadata.Should().ContainKey("version");
|
|
metadata.Should().ContainKey("description");
|
|
|
|
metadata["name"].Should().Be("starter-day1");
|
|
metadata["version"].ToString().Should().MatchRegex(@"^\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?$", "version should be semver");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasRulesSection()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
var spec = policy["spec"] as Dictionary<object, object>;
|
|
spec.Should().NotBeNull();
|
|
spec!.Should().ContainKey("rules");
|
|
|
|
var rules = spec["rules"] as List<object>;
|
|
rules.Should().NotBeNull();
|
|
rules!.Should().HaveCountGreaterThan(0, "Policy should have at least one rule");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasSettingsSection()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
var spec = policy["spec"] as Dictionary<object, object>;
|
|
spec.Should().NotBeNull();
|
|
spec!.Should().ContainKey("settings");
|
|
|
|
var settings = spec["settings"] as Dictionary<object, object>;
|
|
settings.Should().NotBeNull();
|
|
settings!.Should().ContainKey("defaultAction");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Theory]
|
|
[InlineData("block-reachable-high-critical")]
|
|
[InlineData("warn-reachable-medium")]
|
|
[InlineData("allow-unreachable")]
|
|
[InlineData("fail-on-unknowns")]
|
|
[InlineData("block-kev")]
|
|
[InlineData("default-allow")]
|
|
public void StarterDay1Policy_ContainsExpectedRule(string ruleName)
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
var spec = policy["spec"] as Dictionary<object, object>;
|
|
var rules = spec!["rules"] as List<object>;
|
|
|
|
var ruleNames = rules!.Cast<Dictionary<object, object>>()
|
|
.Select(r => r["name"]?.ToString())
|
|
.Where(n => n != null)
|
|
.ToList();
|
|
|
|
ruleNames.Should().Contain(ruleName, $"Policy should contain rule '{ruleName}'");
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public void StarterDay1Policy_HasDefaultAllowRuleWithLowestPriority()
|
|
{
|
|
var policyPath = Path.Combine(_testDataPath, "starter-day1.yaml");
|
|
var content = File.ReadAllText(policyPath);
|
|
var policy = _yamlDeserializer.Deserialize<Dictionary<string, object>>(content);
|
|
|
|
var spec = policy["spec"] as Dictionary<object, object>;
|
|
var rules = spec!["rules"] as List<object>;
|
|
|
|
var defaultAllowRule = rules!.Cast<Dictionary<object, object>>()
|
|
.FirstOrDefault(r => r["name"]?.ToString() == "default-allow");
|
|
|
|
defaultAllowRule.Should().NotBeNull("Policy should have a default-allow rule");
|
|
|
|
var priority = Convert.ToInt32(defaultAllowRule!["priority"]);
|
|
priority.Should().Be(0, "default-allow rule should have the lowest priority (0)");
|
|
|
|
var action = defaultAllowRule["action"]?.ToString();
|
|
action.Should().Be("allow", "default-allow rule should have action 'allow'");
|
|
}
|
|
}
|