Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
158 lines
4.5 KiB
C#
158 lines
4.5 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|