up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
using StellaOps.Scanner.EntryTrace;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
|
||||
namespace StellaOps.Scanner.Worker.Processing.Reachability;
|
||||
|
||||
/// <summary>
|
||||
/// Builds a reachability union graph from the EntryTrace graph if available.
|
||||
/// </summary>
|
||||
public sealed class ReachabilityBuildStageExecutor : IScanStageExecutor
|
||||
{
|
||||
private readonly ILogger<ReachabilityBuildStageExecutor> _logger;
|
||||
|
||||
public ReachabilityBuildStageExecutor(ILogger<ReachabilityBuildStageExecutor> logger)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public string StageName => ScanStageNames.ComposeArtifacts;
|
||||
|
||||
public ValueTask ExecuteAsync(ScanJobContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
if (!context.Analysis.TryGet<EntryTraceGraph>(ScanAnalysisKeys.EntryTraceGraph, out var entryTrace) || entryTrace is null)
|
||||
{
|
||||
_logger.LogDebug("No EntryTrace graph present; reachability union graph not built.");
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
var nodeMap = entryTrace.Nodes.ToDictionary(n => n.Id);
|
||||
|
||||
var unionNodes = new List<ReachabilityUnionNode>(entryTrace.Nodes.Length);
|
||||
foreach (var node in entryTrace.Nodes)
|
||||
{
|
||||
var symbolId = ComputeSymbolId("shell", node.DisplayName, node.Kind.ToString());
|
||||
var source = node.Evidence is null
|
||||
? null
|
||||
: new ReachabilitySource("static", "entrytrace", node.Evidence.Path);
|
||||
|
||||
unionNodes.Add(new ReachabilityUnionNode(
|
||||
SymbolId: symbolId,
|
||||
Lang: "shell",
|
||||
Kind: node.Kind.ToString().ToLowerInvariant(),
|
||||
Display: node.DisplayName,
|
||||
Source: source));
|
||||
}
|
||||
|
||||
var unionEdges = new List<ReachabilityUnionEdge>(entryTrace.Edges.Length);
|
||||
foreach (var edge in entryTrace.Edges)
|
||||
{
|
||||
if (!nodeMap.TryGetValue(edge.FromNodeId, out var fromNode) || !nodeMap.TryGetValue(edge.ToNodeId, out var toNode))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var fromId = ComputeSymbolId("shell", fromNode.DisplayName, fromNode.Kind.ToString());
|
||||
var toId = ComputeSymbolId("shell", toNode.DisplayName, toNode.Kind.ToString());
|
||||
unionEdges.Add(new ReachabilityUnionEdge(
|
||||
From: fromId,
|
||||
To: toId,
|
||||
EdgeType: "call",
|
||||
Confidence: "high",
|
||||
Source: new ReachabilitySource("static", "entrytrace", edge.Relationship)));
|
||||
}
|
||||
|
||||
var unionGraph = new ReachabilityUnionGraph(unionNodes, unionEdges);
|
||||
context.Analysis.Set(ScanAnalysisKeys.ReachabilityUnionGraph, unionGraph);
|
||||
_logger.LogInformation("Reachability union graph built from EntryTrace: nodes={NodeCount} edges={EdgeCount}", unionNodes.Count, unionEdges.Count);
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
private static string ComputeSymbolId(string lang, string display, string kind)
|
||||
{
|
||||
using var sha = SHA256.Create();
|
||||
var input = Encoding.UTF8.GetBytes((display ?? string.Empty) + "|" + (kind ?? string.Empty));
|
||||
var hash = sha.ComputeHash(input);
|
||||
var base64 = Convert.ToBase64String(hash)
|
||||
.TrimEnd('=')
|
||||
.Replace('+', '-')
|
||||
.Replace('/', '_');
|
||||
return $"sym:{lang}:{base64}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
|
||||
namespace StellaOps.Scanner.Worker.Processing.Reachability;
|
||||
|
||||
/// <summary>
|
||||
/// Emits reachability union graphs to CAS during the EmitReports stage when present in the analysis store.
|
||||
/// </summary>
|
||||
public sealed class ReachabilityPublishStageExecutor : IScanStageExecutor
|
||||
{
|
||||
private readonly IReachabilityUnionPublisherService _publisher;
|
||||
private readonly ILogger<ReachabilityPublishStageExecutor> _logger;
|
||||
|
||||
public ReachabilityPublishStageExecutor(
|
||||
IReachabilityUnionPublisherService publisher,
|
||||
ILogger<ReachabilityPublishStageExecutor> logger)
|
||||
{
|
||||
_publisher = publisher ?? throw new ArgumentNullException(nameof(publisher));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public string StageName => ScanStageNames.EmitReports;
|
||||
|
||||
public async ValueTask ExecuteAsync(ScanJobContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
if (!context.Analysis.TryGet<ReachabilityUnionGraph>(ScanAnalysisKeys.ReachabilityUnionGraph, out var graph) || graph is null)
|
||||
{
|
||||
_logger.LogDebug("No reachability union graph present; skipping publish.");
|
||||
return;
|
||||
}
|
||||
|
||||
var publishResult = await _publisher.PublishAsync(graph, context.ScanId, cancellationToken).ConfigureAwait(false);
|
||||
context.Analysis.Set(ScanAnalysisKeys.ReachabilityUnionCas, publishResult);
|
||||
|
||||
_logger.LogInformation("Published reachability union graph to CAS: sha256={Sha} records={Records}", publishResult.Sha256, publishResult.Records);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
|
||||
namespace StellaOps.Scanner.Worker.Processing;
|
||||
|
||||
public sealed class ScanJobProcessor
|
||||
{
|
||||
private readonly IReadOnlyDictionary<string, IScanStageExecutor> _executors;
|
||||
private readonly ScanProgressReporter _progressReporter;
|
||||
private readonly ILogger<ScanJobProcessor> _logger;
|
||||
|
||||
public ScanJobProcessor(IEnumerable<IScanStageExecutor> executors, ScanProgressReporter progressReporter, ILogger<ScanJobProcessor> logger)
|
||||
{
|
||||
_progressReporter = progressReporter ?? throw new ArgumentNullException(nameof(progressReporter));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
private readonly IReadOnlyDictionary<string, IScanStageExecutor> _executors;
|
||||
private readonly ScanProgressReporter _progressReporter;
|
||||
private readonly ILogger<ScanJobProcessor> _logger;
|
||||
private readonly IReachabilityUnionPublisherService _reachabilityPublisher;
|
||||
|
||||
public ScanJobProcessor(
|
||||
IEnumerable<IScanStageExecutor> executors,
|
||||
ScanProgressReporter progressReporter,
|
||||
IReachabilityUnionPublisherService reachabilityPublisher,
|
||||
ILogger<ScanJobProcessor> logger)
|
||||
{
|
||||
_progressReporter = progressReporter ?? throw new ArgumentNullException(nameof(progressReporter));
|
||||
_reachabilityPublisher = reachabilityPublisher ?? throw new ArgumentNullException(nameof(reachabilityPublisher));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
var map = new Dictionary<string, IScanStageExecutor>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var executor in executors ?? Array.Empty<IScanStageExecutor>())
|
||||
@@ -42,12 +49,14 @@ public sealed class ScanJobProcessor
|
||||
_executors = map;
|
||||
}
|
||||
|
||||
public async ValueTask ExecuteAsync(ScanJobContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
|
||||
foreach (var stage in ScanStageNames.Ordered)
|
||||
{
|
||||
public async ValueTask ExecuteAsync(ScanJobContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
// Placeholder: reachability publisher will be fed once lifter outputs are routed here.
|
||||
_ = _reachabilityPublisher;
|
||||
|
||||
foreach (var stage in ScanStageNames.Ordered)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (!_executors.TryGetValue(stage, out var executor))
|
||||
@@ -55,11 +64,11 @@ public sealed class ScanJobProcessor
|
||||
continue;
|
||||
}
|
||||
|
||||
await _progressReporter.ExecuteStageAsync(
|
||||
context,
|
||||
stage,
|
||||
executor.ExecuteAsync,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
await _progressReporter.ExecuteStageAsync(
|
||||
context,
|
||||
stage,
|
||||
executor.ExecuteAsync,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Options;
|
||||
using StellaOps.Auth.Client;
|
||||
using StellaOps.Configuration;
|
||||
using StellaOps.Scanner.Cache;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
using StellaOps.Scanner.Analyzers.OS.Plugin;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Plugin;
|
||||
using StellaOps.Scanner.EntryTrace;
|
||||
@@ -24,6 +25,7 @@ using StellaOps.Scanner.Worker.Processing;
|
||||
using StellaOps.Scanner.Worker.Processing.Surface;
|
||||
using StellaOps.Scanner.Storage.Extensions;
|
||||
using StellaOps.Scanner.Storage;
|
||||
using Reachability = StellaOps.Scanner.Worker.Processing.Reachability;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
@@ -56,6 +58,9 @@ builder.Services.AddSingleton<IDelayScheduler, SystemDelayScheduler>();
|
||||
|
||||
builder.Services.AddEntryTraceAnalyzer();
|
||||
builder.Services.AddSingleton<IEntryTraceExecutionService, EntryTraceExecutionService>();
|
||||
builder.Services.AddSingleton<ReachabilityUnionWriter>();
|
||||
builder.Services.AddSingleton<ReachabilityUnionPublisher>();
|
||||
builder.Services.AddSingleton<IReachabilityUnionPublisherService, ReachabilityUnionPublisherService>();
|
||||
|
||||
var storageSection = builder.Configuration.GetSection("ScannerStorage");
|
||||
var connectionString = storageSection.GetValue<string>("Mongo:ConnectionString");
|
||||
@@ -78,6 +83,8 @@ builder.Services.AddSingleton<ILanguageAnalyzerPluginCatalog, LanguageAnalyzerPl
|
||||
builder.Services.AddSingleton<IScanAnalyzerDispatcher, CompositeScanAnalyzerDispatcher>();
|
||||
builder.Services.AddSingleton<IScanStageExecutor, RegistrySecretStageExecutor>();
|
||||
builder.Services.AddSingleton<IScanStageExecutor, AnalyzerStageExecutor>();
|
||||
builder.Services.AddSingleton<IScanStageExecutor, Reachability.ReachabilityBuildStageExecutor>();
|
||||
builder.Services.AddSingleton<IScanStageExecutor, Reachability.ReachabilityPublishStageExecutor>();
|
||||
|
||||
builder.Services.AddSingleton<ScannerWorkerHostedService>();
|
||||
builder.Services.AddHostedService(sp => sp.GetRequiredService<ScannerWorkerHostedService>());
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Analyzers.Lang/StellaOps.Scanner.Analyzers.Lang.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.EntryTrace/StellaOps.Scanner.EntryTrace.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Cache/StellaOps.Scanner.Cache.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Reachability/StellaOps.Scanner.Reachability.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Surface.Env/StellaOps.Scanner.Surface.Env.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Surface.Validation/StellaOps.Scanner.Surface.Validation.csproj" />
|
||||
<ProjectReference Include="../__Libraries/StellaOps.Scanner.Surface.Secrets/StellaOps.Scanner.Surface.Secrets.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user