Restructure solution layout by module
This commit is contained in:
157
src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs
Normal file
157
src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Policy.Tests;
|
||||
|
||||
public sealed class PolicyBinderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Bind_ValidYaml_ReturnsSuccess()
|
||||
{
|
||||
const string yaml = """
|
||||
version: "1.0"
|
||||
rules:
|
||||
- name: Block Critical
|
||||
severity: [Critical]
|
||||
sources: [NVD]
|
||||
action: block
|
||||
""";
|
||||
|
||||
var result = PolicyBinder.Bind(yaml, PolicyDocumentFormat.Yaml);
|
||||
|
||||
Assert.True(result.Success);
|
||||
Assert.Equal("1.0", result.Document.Version);
|
||||
Assert.Single(result.Document.Rules);
|
||||
Assert.Empty(result.Issues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_ExceptionsConfigured_ParsesDefinitions()
|
||||
{
|
||||
const string yaml = """
|
||||
version: "1.0"
|
||||
exceptions:
|
||||
effects:
|
||||
- id: suppress-temp
|
||||
name: Temporary Suppress
|
||||
effect: suppress
|
||||
routingTemplate: secops
|
||||
maxDurationDays: 30
|
||||
- id: downgrade-ops
|
||||
name: Downgrade To Low
|
||||
effect: downgrade
|
||||
downgradeSeverity: Low
|
||||
routingTemplates:
|
||||
- id: secops
|
||||
authorityRouteId: route-secops
|
||||
requireMfa: true
|
||||
rules:
|
||||
- name: Allow
|
||||
action: ignore
|
||||
""";
|
||||
|
||||
var result = PolicyBinder.Bind(yaml, PolicyDocumentFormat.Yaml);
|
||||
|
||||
Assert.True(result.Success);
|
||||
var effects = result.Document.Exceptions.Effects;
|
||||
Assert.Equal(2, effects.Length);
|
||||
|
||||
var suppress = effects.Single(effect => effect.Id == "suppress-temp");
|
||||
Assert.Equal(PolicyExceptionEffectType.Suppress, suppress.Effect);
|
||||
Assert.Equal("Temporary Suppress", suppress.Name);
|
||||
Assert.Equal("secops", suppress.RoutingTemplate);
|
||||
Assert.Equal(30, suppress.MaxDurationDays);
|
||||
|
||||
var downgrade = effects.Single(effect => effect.Id == "downgrade-ops");
|
||||
Assert.Equal(PolicyExceptionEffectType.Downgrade, downgrade.Effect);
|
||||
Assert.Equal("Downgrade To Low", downgrade.Name);
|
||||
Assert.Equal(PolicySeverity.Low, downgrade.DowngradeSeverity);
|
||||
|
||||
var routing = result.Document.Exceptions.RoutingTemplates;
|
||||
Assert.Single(routing);
|
||||
Assert.Equal("secops", routing[0].Id);
|
||||
Assert.Equal("route-secops", routing[0].AuthorityRouteId);
|
||||
Assert.True(routing[0].RequireMfa);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_ExceptionDowngradeMissingSeverity_ReturnsError()
|
||||
{
|
||||
const string yaml = """
|
||||
version: "1.0"
|
||||
exceptions:
|
||||
effects:
|
||||
- id: downgrade-invalid
|
||||
effect: downgrade
|
||||
routingTemplates: []
|
||||
rules:
|
||||
- name: Allow
|
||||
action: ignore
|
||||
""";
|
||||
|
||||
var result = PolicyBinder.Bind(yaml, PolicyDocumentFormat.Yaml);
|
||||
|
||||
Assert.False(result.Success);
|
||||
Assert.Contains(result.Issues, issue => issue.Code == "policy.exceptions.effect.downgrade.missingSeverity");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_InvalidSeverity_ReturnsError()
|
||||
{
|
||||
const string yaml = """
|
||||
version: "1.0"
|
||||
rules:
|
||||
- name: Invalid Severity
|
||||
severity: [Nope]
|
||||
action: block
|
||||
""";
|
||||
|
||||
var result = PolicyBinder.Bind(yaml, PolicyDocumentFormat.Yaml);
|
||||
|
||||
Assert.False(result.Success);
|
||||
Assert.Contains(result.Issues, issue => issue.Code == "policy.severity.invalid");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cli_StrictMode_FailsOnWarnings()
|
||||
{
|
||||
const string yaml = """
|
||||
version: "1.0"
|
||||
rules:
|
||||
- name: Quiet Warning
|
||||
sources: ["", "NVD"]
|
||||
action: ignore
|
||||
""";
|
||||
|
||||
var path = Path.Combine(Path.GetTempPath(), $"policy-{Guid.NewGuid():N}.yaml");
|
||||
await File.WriteAllTextAsync(path, yaml);
|
||||
|
||||
try
|
||||
{
|
||||
using var output = new StringWriter();
|
||||
using var error = new StringWriter();
|
||||
var cli = new PolicyValidationCli(output, error);
|
||||
var options = new PolicyValidationCliOptions
|
||||
{
|
||||
Inputs = new[] { path },
|
||||
Strict = true,
|
||||
};
|
||||
|
||||
var exitCode = await cli.RunAsync(options, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, exitCode);
|
||||
Assert.Contains("WARNING", output.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user