using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using StellaOps.Determinism; using StellaOps.Scanner.Analyzers.Native.Plugin; using StellaOps.Scanner.Analyzers.Native.RuntimeCapture; namespace StellaOps.Scanner.Analyzers.Native; /// /// Extension methods for registering native analyzer services with DI. /// public static class ServiceCollectionExtensions { /// /// Configuration section name for native analyzer options. /// public const string ConfigSectionName = "Scanner:Analyzers:Native"; /// /// Adds the native analyzer services to the service collection. /// /// Service collection. /// Configuration for binding options. /// Service collection for chaining. public static IServiceCollection AddNativeAnalyzer( this IServiceCollection services, IConfiguration? configuration = null) { return services.AddNativeAnalyzer(configuration, null); } /// /// Adds the native analyzer services to the service collection. /// /// Service collection. /// Optional action to configure options. /// Service collection for chaining. public static IServiceCollection AddNativeAnalyzer( this IServiceCollection services, Action? configure) { return services.AddNativeAnalyzer(null, configure); } /// /// Adds the native analyzer services to the service collection. /// /// Service collection. /// Configuration for binding options. /// Optional action to configure options. /// Service collection for chaining. public static IServiceCollection AddNativeAnalyzer( this IServiceCollection services, IConfiguration? configuration, Action? configure) { // Register options var optionsBuilder = services.AddOptions(); if (configuration != null) { optionsBuilder.Bind(configuration.GetSection(ConfigSectionName)); } if (configure != null) { optionsBuilder.Configure(configure); } // Register core services services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton, ElfSectionHashOptionsValidator>(); var sectionOptionsBuilder = services.AddOptions(); if (configuration != null) { sectionOptionsBuilder.Bind(configuration.GetSection($"{ConfigSectionName}:SectionHashes")); } sectionOptionsBuilder.ValidateOnStart(); services.TryAddSingleton(); return services; } /// /// Adds runtime capture adapter services (optional, requires elevated privileges). /// /// Service collection. /// Optional action to configure runtime capture options. /// Service collection for chaining. public static IServiceCollection AddNativeRuntimeCapture( this IServiceCollection services, Action? configure = null) { services.AddDeterminismDefaults(); var optionsBuilder = services.AddOptions(); if (configure != null) { optionsBuilder.Configure(configure); } // Register platform-appropriate capture adapter services.TryAddSingleton(sp => { var timeProvider = sp.GetRequiredService(); var guidProvider = sp.GetRequiredService(); var adapter = RuntimeCaptureAdapterFactory.CreateForCurrentPlatform(timeProvider, guidProvider); if (adapter == null) { throw new PlatformNotSupportedException( "Runtime capture is not supported on this platform."); } return adapter; }); return services; } } /// /// Configuration options for native analyzer services. /// public sealed class NativeAnalyzerServiceOptions { /// /// Directory for loading additional native analyzer plugins. /// Default: plugins/scanner/analyzers/native /// public string PluginDirectory { get; set; } = "plugins/scanner/analyzers/native"; /// /// Whether to enable heuristic scanning by default. /// Default: true. /// public bool EnableHeuristicScanning { get; set; } = true; /// /// Whether to enable dependency resolution by default. /// Default: true. /// public bool EnableResolution { get; set; } = true; /// /// Default timeout per binary analysis. /// Default: 30 seconds. /// public TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromSeconds(30); /// /// Default search paths for Linux (ELF). /// public List LinuxDefaultSearchPaths { get; set; } = [ "/lib", "/lib64", "/usr/lib", "/usr/lib64", "/usr/local/lib", "/lib/x86_64-linux-gnu", "/usr/lib/x86_64-linux-gnu" ]; /// /// Default search paths for Windows (PE). /// public List WindowsDefaultSearchPaths { get; set; } = [ @"C:\Windows\System32", @"C:\Windows\SysWOW64", @"C:\Windows" ]; /// /// Default search paths for macOS (Mach-O). /// public List MacOSDefaultSearchPaths { get; set; } = [ "/usr/lib", "/usr/local/lib", "/Library/Frameworks", "/System/Library/Frameworks" ]; /// /// Gets the default search paths for the specified format. /// public IReadOnlyList GetDefaultSearchPathsForFormat(NativeFormat format) { return format switch { NativeFormat.Elf => LinuxDefaultSearchPaths, NativeFormat.Pe => WindowsDefaultSearchPaths, NativeFormat.MachO => MacOSDefaultSearchPaths, _ => [] }; } }