Restructure solution layout by module

This commit is contained in:
master
2025-10-28 15:10:40 +02:00
parent 95daa159c4
commit d870da18ce
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -0,0 +1,241 @@
using System;
using System.Collections.Immutable;
using System.Linq;
namespace StellaOps.Policy;
/// <summary>
/// Canonical representation of a StellaOps policy document.
/// </summary>
public sealed record PolicyDocument(
string Version,
ImmutableArray<PolicyRule> Rules,
ImmutableDictionary<string, string> Metadata,
PolicyExceptionConfiguration Exceptions)
{
public static PolicyDocument Empty { get; } = new(
PolicySchema.CurrentVersion,
ImmutableArray<PolicyRule>.Empty,
ImmutableDictionary<string, string>.Empty,
PolicyExceptionConfiguration.Empty);
}
public static class PolicySchema
{
public const string SchemaId = "https://schemas.stella-ops.org/policy/policy-schema@1.json";
public const string CurrentVersion = "1.0";
public static PolicyDocumentFormat DetectFormat(string fileName)
{
if (fileName is null)
{
throw new ArgumentNullException(nameof(fileName));
}
var lower = fileName.Trim().ToLowerInvariant();
if (lower.EndsWith(".yaml", StringComparison.Ordinal)
|| lower.EndsWith(".yml", StringComparison.Ordinal)
|| lower.EndsWith(".stella", StringComparison.Ordinal))
{
return PolicyDocumentFormat.Yaml;
}
return PolicyDocumentFormat.Json;
}
}
public sealed record PolicyRule(
string Name,
string? Identifier,
string? Description,
PolicyAction Action,
ImmutableArray<PolicySeverity> Severities,
ImmutableArray<string> Environments,
ImmutableArray<string> Sources,
ImmutableArray<string> Vendors,
ImmutableArray<string> Licenses,
ImmutableArray<string> Tags,
PolicyRuleMatchCriteria Match,
DateTimeOffset? Expires,
string? Justification,
ImmutableDictionary<string, string> Metadata)
{
public static PolicyRuleMatchCriteria EmptyMatch { get; } = new(
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty);
public static PolicyRule Create(
string name,
PolicyAction action,
ImmutableArray<PolicySeverity> severities,
ImmutableArray<string> environments,
ImmutableArray<string> sources,
ImmutableArray<string> vendors,
ImmutableArray<string> licenses,
ImmutableArray<string> tags,
PolicyRuleMatchCriteria match,
DateTimeOffset? expires,
string? justification,
string? identifier = null,
string? description = null,
ImmutableDictionary<string, string>? metadata = null)
{
metadata ??= ImmutableDictionary<string, string>.Empty;
return new PolicyRule(
name,
identifier,
description,
action,
severities,
environments,
sources,
vendors,
licenses,
tags,
match,
expires,
justification,
metadata);
}
public bool MatchesAnyEnvironment => Environments.IsDefaultOrEmpty;
}
public sealed record PolicyRuleMatchCriteria(
ImmutableArray<string> Images,
ImmutableArray<string> Repositories,
ImmutableArray<string> Packages,
ImmutableArray<string> Purls,
ImmutableArray<string> Cves,
ImmutableArray<string> Paths,
ImmutableArray<string> LayerDigests,
ImmutableArray<string> UsedByEntrypoint)
{
public static PolicyRuleMatchCriteria Create(
ImmutableArray<string> images,
ImmutableArray<string> repositories,
ImmutableArray<string> packages,
ImmutableArray<string> purls,
ImmutableArray<string> cves,
ImmutableArray<string> paths,
ImmutableArray<string> layerDigests,
ImmutableArray<string> usedByEntrypoint)
=> new(
images,
repositories,
packages,
purls,
cves,
paths,
layerDigests,
usedByEntrypoint);
public static PolicyRuleMatchCriteria Empty { get; } = new(
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty,
ImmutableArray<string>.Empty);
public bool IsEmpty =>
Images.IsDefaultOrEmpty &&
Repositories.IsDefaultOrEmpty &&
Packages.IsDefaultOrEmpty &&
Purls.IsDefaultOrEmpty &&
Cves.IsDefaultOrEmpty &&
Paths.IsDefaultOrEmpty &&
LayerDigests.IsDefaultOrEmpty &&
UsedByEntrypoint.IsDefaultOrEmpty;
}
public sealed record PolicyAction(
PolicyActionType Type,
PolicyIgnoreOptions? Ignore,
PolicyEscalateOptions? Escalate,
PolicyRequireVexOptions? RequireVex,
bool Quiet);
public enum PolicyActionType
{
Block,
Ignore,
Warn,
Defer,
Escalate,
RequireVex,
}
public sealed record PolicyIgnoreOptions(DateTimeOffset? Until, string? Justification);
public sealed record PolicyEscalateOptions(
PolicySeverity? MinimumSeverity,
bool RequireKev,
double? MinimumEpss);
public sealed record PolicyRequireVexOptions(
ImmutableArray<string> Vendors,
ImmutableArray<string> Justifications);
public enum PolicySeverity
{
Critical,
High,
Medium,
Low,
Informational,
None,
Unknown,
}
public sealed record PolicyExceptionConfiguration(
ImmutableArray<PolicyExceptionEffect> Effects,
ImmutableArray<PolicyExceptionRoutingTemplate> RoutingTemplates)
{
public static PolicyExceptionConfiguration Empty { get; } = new(
ImmutableArray<PolicyExceptionEffect>.Empty,
ImmutableArray<PolicyExceptionRoutingTemplate>.Empty);
public PolicyExceptionEffect? FindEffect(string effectId)
{
if (string.IsNullOrWhiteSpace(effectId) || Effects.IsDefaultOrEmpty)
{
return null;
}
return Effects.FirstOrDefault(effect =>
string.Equals(effect.Id, effectId, StringComparison.OrdinalIgnoreCase));
}
}
public sealed record PolicyExceptionEffect(
string Id,
string? Name,
PolicyExceptionEffectType Effect,
PolicySeverity? DowngradeSeverity,
string? RequiredControlId,
string? RoutingTemplate,
int? MaxDurationDays,
string? Description);
public enum PolicyExceptionEffectType
{
Suppress,
Defer,
Downgrade,
RequireControl,
}
public sealed record PolicyExceptionRoutingTemplate(
string Id,
string AuthorityRouteId,
bool RequireMfa,
string? Description);