Some checks failed
		
		
	
	Docs CI / lint-and-preview (push) Has been cancelled
				
			- Added `SchedulerWorkerOptions` class to encapsulate configuration for the scheduler worker. - Introduced `PlannerBackgroundService` to manage the planner loop, fetching and processing planning runs. - Created `PlannerExecutionService` to handle the execution logic for planning runs, including impact targeting and run persistence. - Developed `PlannerExecutionResult` and `PlannerExecutionStatus` to standardize execution outcomes. - Implemented validation logic within `SchedulerWorkerOptions` to ensure proper configuration. - Added documentation for the planner loop and impact targeting features. - Established health check endpoints and authentication mechanisms for the Signals service. - Created unit tests for the Signals API to ensure proper functionality and response handling. - Configured options for authority integration and fallback authentication methods.
		
			
				
	
	
		
			158 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.6 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);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |