feat: Implement MongoDB orchestrator storage with registry, commands, and heartbeats
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Added NullAdvisoryObservationEventTransport for handling advisory observation events. - Created IOrchestratorRegistryStore interface for orchestrator registry operations. - Implemented MongoOrchestratorRegistryStore for MongoDB interactions with orchestrator data. - Defined OrchestratorCommandDocument and OrchestratorCommandRecord for command handling. - Added OrchestratorHeartbeatDocument and OrchestratorHeartbeatRecord for heartbeat tracking. - Created OrchestratorRegistryDocument and OrchestratorRegistryRecord for registry management. - Developed tests for orchestrator collections migration and MongoOrchestratorRegistryStore functionality. - Introduced AirgapImportRequest and AirgapImportValidator for air-gapped VEX bundle imports. - Added incident mode rules sample JSON for notifier configuration.
This commit is contained in:
@@ -21,6 +21,8 @@ public sealed class ConcelierOptions
|
||||
|
||||
public AdvisoryChunkOptions AdvisoryChunks { get; set; } = new();
|
||||
|
||||
public EvidenceBundleOptions Evidence { get; set; } = new();
|
||||
|
||||
public StellaOpsCryptoOptions Crypto { get; } = new();
|
||||
|
||||
public sealed class StorageOptions
|
||||
@@ -172,4 +174,20 @@ public sealed class ConcelierOptions
|
||||
|
||||
public int CacheDurationSeconds { get; set; } = 30;
|
||||
}
|
||||
|
||||
public sealed class EvidenceBundleOptions
|
||||
{
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
public string Root { get; set; } = System.IO.Path.Combine("out", "evidence", "bundles");
|
||||
|
||||
public string? DefaultManifestFileName { get; set; } = "manifest.json";
|
||||
|
||||
public string? DefaultTransparencyFileName { get; set; } = "transparency.json";
|
||||
|
||||
public string PipelineVersion { get; set; } = "git:unknown";
|
||||
|
||||
[JsonIgnore]
|
||||
public string RootAbsolute { get; internal set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public static class ConcelierOptionsPostConfigure
|
||||
|
||||
options.Authority ??= new ConcelierOptions.AuthorityOptions();
|
||||
options.Features ??= new ConcelierOptions.FeaturesOptions();
|
||||
options.Evidence ??= new ConcelierOptions.EvidenceBundleOptions();
|
||||
|
||||
var authority = options.Authority;
|
||||
if (string.IsNullOrWhiteSpace(authority.ClientSecret)
|
||||
@@ -44,8 +45,8 @@ public static class ConcelierOptionsPostConfigure
|
||||
authority.ClientSecret = secret;
|
||||
}
|
||||
|
||||
options.Mirror ??= new ConcelierOptions.MirrorOptions();
|
||||
var mirror = options.Mirror;
|
||||
options.Mirror ??= new ConcelierOptions.MirrorOptions();
|
||||
var mirror = options.Mirror;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(mirror.ExportRoot))
|
||||
{
|
||||
@@ -65,9 +66,33 @@ public static class ConcelierOptionsPostConfigure
|
||||
mirror.LatestDirectoryName = "latest";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(mirror.MirrorDirectoryName))
|
||||
{
|
||||
mirror.MirrorDirectoryName = "mirror";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(mirror.MirrorDirectoryName))
|
||||
{
|
||||
mirror.MirrorDirectoryName = "mirror";
|
||||
}
|
||||
|
||||
var evidence = options.Evidence;
|
||||
if (string.IsNullOrWhiteSpace(evidence.Root))
|
||||
{
|
||||
evidence.Root = Path.Combine("out", "evidence", "bundles");
|
||||
}
|
||||
|
||||
var evidenceRoot = evidence.Root;
|
||||
if (!Path.IsPathRooted(evidenceRoot))
|
||||
{
|
||||
evidenceRoot = Path.Combine(contentRootPath, evidenceRoot);
|
||||
}
|
||||
|
||||
evidence.RootAbsolute = Path.GetFullPath(evidenceRoot);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(evidence.DefaultManifestFileName))
|
||||
{
|
||||
evidence.DefaultManifestFileName = "manifest.json";
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(evidence.DefaultTransparencyFileName))
|
||||
{
|
||||
evidence.DefaultTransparencyFileName = "transparency.json";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,9 @@ public static class ConcelierOptionsValidator
|
||||
options.Mirror ??= new ConcelierOptions.MirrorOptions();
|
||||
ValidateMirror(options.Mirror);
|
||||
|
||||
options.Evidence ??= new ConcelierOptions.EvidenceBundleOptions();
|
||||
ValidateEvidence(options.Evidence);
|
||||
|
||||
options.AdvisoryChunks ??= new ConcelierOptions.AdvisoryChunkOptions();
|
||||
ValidateAdvisoryChunks(options.AdvisoryChunks);
|
||||
}
|
||||
@@ -312,4 +315,22 @@ public static class ConcelierOptionsValidator
|
||||
throw new InvalidOperationException("Advisory chunk cacheDurationSeconds must be greater than or equal to zero.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateEvidence(ConcelierOptions.EvidenceBundleOptions evidence)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(evidence.Root))
|
||||
{
|
||||
throw new InvalidOperationException("Evidence bundle root must be configured.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(evidence.RootAbsolute))
|
||||
{
|
||||
throw new InvalidOperationException("Evidence bundle root could not be resolved.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(evidence.PipelineVersion))
|
||||
{
|
||||
throw new InvalidOperationException("Evidence bundle pipelineVersion must be provided.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user