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,
_ => []
};
}
}