191 lines
6.6 KiB
C#
191 lines
6.6 KiB
C#
// <copyright file="ServiceCollectionExtensions.cs" company="StellaOps">
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
// </copyright>
|
|
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using Microsoft.Extensions.Logging;
|
|
using StellaOps.Signals.Ebpf.Cgroup;
|
|
using StellaOps.Signals.Ebpf.Output;
|
|
using StellaOps.Signals.Ebpf.Parsers;
|
|
using StellaOps.Signals.Ebpf.Probes;
|
|
using StellaOps.Signals.Ebpf.Services;
|
|
using StellaOps.Signals.Ebpf.Symbols;
|
|
|
|
namespace StellaOps.Signals.Ebpf;
|
|
|
|
|
|
/// <summary>
|
|
/// DI registration extensions for eBPF runtime evidence collection.
|
|
/// </summary>
|
|
public static class ServiceCollectionExtensions
|
|
{
|
|
/// <summary>
|
|
/// Adds eBPF runtime evidence collection services.
|
|
/// </summary>
|
|
/// <param name="services">The service collection.</param>
|
|
/// <param name="configureOptions">Optional configuration callback.</param>
|
|
/// <returns>The service collection for chaining.</returns>
|
|
public static IServiceCollection AddEbpfRuntimeEvidence(
|
|
this IServiceCollection services,
|
|
Action<EbpfEvidenceOptions>? configureOptions = null)
|
|
{
|
|
var options = new EbpfEvidenceOptions();
|
|
configureOptions?.Invoke(options);
|
|
|
|
// Register options
|
|
services.AddSingleton(options);
|
|
services.AddSingleton(options.WriterOptions);
|
|
services.AddSingleton(options.CollectorOptions);
|
|
|
|
// Register memory cache if not already registered
|
|
services.TryAddSingleton<IMemoryCache>(sp =>
|
|
new MemoryCache(new MemoryCacheOptions
|
|
{
|
|
SizeLimit = options.SymbolCacheSizeLimit,
|
|
}));
|
|
|
|
// Register symbol resolver
|
|
services.AddSingleton<ISymbolResolver>(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<EnhancedSymbolResolver>>();
|
|
var cache = sp.GetRequiredService<IMemoryCache>();
|
|
return new EnhancedSymbolResolver(logger, cache, options.ProcRoot);
|
|
});
|
|
|
|
// Register cgroup resolver
|
|
services.AddSingleton(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<CgroupContainerResolver>>();
|
|
return new CgroupContainerResolver(logger, options.ProcRoot, options.CgroupRoot);
|
|
});
|
|
|
|
// Register event parser
|
|
services.AddSingleton(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<EventParser>>();
|
|
var symbolResolver = sp.GetRequiredService<ISymbolResolver>();
|
|
return new EventParser(logger, symbolResolver);
|
|
});
|
|
|
|
// Register probe loader
|
|
services.AddSingleton<IEbpfProbeLoader>(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<CoreProbeLoader>>();
|
|
var symbolResolver = sp.GetRequiredService<ISymbolResolver>();
|
|
return new CoreProbeLoader(logger, symbolResolver, options.ProbeDirectory);
|
|
});
|
|
|
|
// Register air-gap probe loader separately (different interface)
|
|
if (options.UseAirGapMode)
|
|
{
|
|
services.AddSingleton<IAirGapProbeLoader>(sp =>
|
|
{
|
|
var airGapLogger = sp.GetRequiredService<ILogger<AirGapProbeLoader>>();
|
|
return new AirGapProbeLoader(airGapLogger);
|
|
});
|
|
}
|
|
|
|
// Register NDJSON writer
|
|
services.AddSingleton(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<RuntimeEvidenceNdjsonWriter>>();
|
|
return new RuntimeEvidenceNdjsonWriter(
|
|
logger,
|
|
options.OutputDirectory,
|
|
options.WriterOptions);
|
|
});
|
|
|
|
// Register the unified evidence collector
|
|
services.AddSingleton(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<RuntimeEvidenceCollector>>();
|
|
var probeLoader = sp.GetRequiredService<IEbpfProbeLoader>();
|
|
var eventParser = sp.GetRequiredService<EventParser>();
|
|
var cgroupResolver = sp.GetRequiredService<CgroupContainerResolver>();
|
|
var writer = sp.GetRequiredService<RuntimeEvidenceNdjsonWriter>();
|
|
return new RuntimeEvidenceCollector(
|
|
logger,
|
|
probeLoader,
|
|
eventParser,
|
|
cgroupResolver,
|
|
writer,
|
|
options.CollectorOptions);
|
|
});
|
|
|
|
// Register the legacy IRuntimeSignalCollector adapter
|
|
services.AddSingleton<IRuntimeSignalCollector>(sp =>
|
|
{
|
|
var logger = sp.GetRequiredService<ILogger<RuntimeSignalCollector>>();
|
|
var probeLoader = sp.GetRequiredService<IEbpfProbeLoader>();
|
|
return new RuntimeSignalCollector(logger, probeLoader);
|
|
});
|
|
|
|
return services;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds eBPF runtime evidence collection with air-gap mode enabled.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Air-gap mode uses offline probe loading without network dependencies.
|
|
/// </remarks>
|
|
public static IServiceCollection AddEbpfRuntimeEvidenceAirGap(
|
|
this IServiceCollection services,
|
|
Action<EbpfEvidenceOptions>? configureOptions = null)
|
|
{
|
|
return services.AddEbpfRuntimeEvidence(options =>
|
|
{
|
|
options.UseAirGapMode = true;
|
|
configureOptions?.Invoke(options);
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Options for eBPF evidence collection services.
|
|
/// </summary>
|
|
public sealed class EbpfEvidenceOptions
|
|
{
|
|
/// <summary>
|
|
/// Path to the /proc filesystem (default: /proc).
|
|
/// </summary>
|
|
public string ProcRoot { get; set; } = "/proc";
|
|
|
|
/// <summary>
|
|
/// Path to the cgroup filesystem (default: /sys/fs/cgroup).
|
|
/// </summary>
|
|
public string CgroupRoot { get; set; } = "/sys/fs/cgroup";
|
|
|
|
/// <summary>
|
|
/// Directory containing compiled BPF probe objects.
|
|
/// </summary>
|
|
public string? ProbeDirectory { get; set; }
|
|
|
|
/// <summary>
|
|
/// Directory for NDJSON evidence output.
|
|
/// </summary>
|
|
public string OutputDirectory { get; set; } = "/var/lib/stellaops/evidence";
|
|
|
|
/// <summary>
|
|
/// Whether to use air-gap mode (offline probe loading).
|
|
/// </summary>
|
|
public bool UseAirGapMode { get; set; }
|
|
|
|
/// <summary>
|
|
/// Maximum size of the symbol resolution cache.
|
|
/// </summary>
|
|
public long SymbolCacheSizeLimit { get; set; } = 100000;
|
|
|
|
/// <summary>
|
|
/// NDJSON writer options.
|
|
/// </summary>
|
|
public NdjsonWriterOptions WriterOptions { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// Collector options.
|
|
/// </summary>
|
|
public RuntimeEvidenceCollectorOptions CollectorOptions { get; set; } = new();
|
|
}
|