// // SPDX-License-Identifier: BUSL-1.1 // 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; /// /// DI registration extensions for eBPF runtime evidence collection. /// public static class ServiceCollectionExtensions { /// /// Adds eBPF runtime evidence collection services. /// /// The service collection. /// Optional configuration callback. /// The service collection for chaining. public static IServiceCollection AddEbpfRuntimeEvidence( this IServiceCollection services, Action? 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(sp => new MemoryCache(new MemoryCacheOptions { SizeLimit = options.SymbolCacheSizeLimit, })); // Register symbol resolver services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); var cache = sp.GetRequiredService(); return new EnhancedSymbolResolver(logger, cache, options.ProcRoot); }); // Register cgroup resolver services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); return new CgroupContainerResolver(logger, options.ProcRoot, options.CgroupRoot); }); // Register event parser services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); var symbolResolver = sp.GetRequiredService(); return new EventParser(logger, symbolResolver); }); // Register probe loader services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); var symbolResolver = sp.GetRequiredService(); return new CoreProbeLoader(logger, symbolResolver, options.ProbeDirectory); }); // Register air-gap probe loader separately (different interface) if (options.UseAirGapMode) { services.AddSingleton(sp => { var airGapLogger = sp.GetRequiredService>(); return new AirGapProbeLoader(airGapLogger); }); } // Register NDJSON writer services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); return new RuntimeEvidenceNdjsonWriter( logger, options.OutputDirectory, options.WriterOptions); }); // Register the unified evidence collector services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); var probeLoader = sp.GetRequiredService(); var eventParser = sp.GetRequiredService(); var cgroupResolver = sp.GetRequiredService(); var writer = sp.GetRequiredService(); return new RuntimeEvidenceCollector( logger, probeLoader, eventParser, cgroupResolver, writer, options.CollectorOptions); }); // Register the legacy IRuntimeSignalCollector adapter services.AddSingleton(sp => { var logger = sp.GetRequiredService>(); var probeLoader = sp.GetRequiredService(); return new RuntimeSignalCollector(logger, probeLoader); }); return services; } /// /// Adds eBPF runtime evidence collection with air-gap mode enabled. /// /// /// Air-gap mode uses offline probe loading without network dependencies. /// public static IServiceCollection AddEbpfRuntimeEvidenceAirGap( this IServiceCollection services, Action? configureOptions = null) { return services.AddEbpfRuntimeEvidence(options => { options.UseAirGapMode = true; configureOptions?.Invoke(options); }); } } /// /// Options for eBPF evidence collection services. /// public sealed class EbpfEvidenceOptions { /// /// Path to the /proc filesystem (default: /proc). /// public string ProcRoot { get; set; } = "/proc"; /// /// Path to the cgroup filesystem (default: /sys/fs/cgroup). /// public string CgroupRoot { get; set; } = "/sys/fs/cgroup"; /// /// Directory containing compiled BPF probe objects. /// public string? ProbeDirectory { get; set; } /// /// Directory for NDJSON evidence output. /// public string OutputDirectory { get; set; } = "/var/lib/stellaops/evidence"; /// /// Whether to use air-gap mode (offline probe loading). /// public bool UseAirGapMode { get; set; } /// /// Maximum size of the symbol resolution cache. /// public long SymbolCacheSizeLimit { get; set; } = 100000; /// /// NDJSON writer options. /// public NdjsonWriterOptions WriterOptions { get; set; } = new(); /// /// Collector options. /// public RuntimeEvidenceCollectorOptions CollectorOptions { get; set; } = new(); }