up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-13 00:20:26 +02:00
parent e1f1bef4c1
commit 564df71bfb
2376 changed files with 334389 additions and 328032 deletions

View File

@@ -1,16 +1,16 @@
using System;
using StellaOps.Plugin;
using StellaOps.Scanner.Analyzers.OS.Abstractions;
namespace StellaOps.Scanner.Analyzers.OS.Plugin;
/// <summary>
/// Represents a restart-time plug-in that publishes a single <see cref="IOSPackageAnalyzer"/>.
/// </summary>
public interface IOSAnalyzerPlugin : IAvailabilityPlugin
{
/// <summary>
/// Creates the analyzer instance bound to the host service provider.
/// </summary>
IOSPackageAnalyzer CreateAnalyzer(IServiceProvider services);
}
using System;
using StellaOps.Plugin;
using StellaOps.Scanner.Analyzers.OS.Abstractions;
namespace StellaOps.Scanner.Analyzers.OS.Plugin;
/// <summary>
/// Represents a restart-time plug-in that publishes a single <see cref="IOSPackageAnalyzer"/>.
/// </summary>
public interface IOSAnalyzerPlugin : IAvailabilityPlugin
{
/// <summary>
/// Creates the analyzer instance bound to the host service provider.
/// </summary>
IOSPackageAnalyzer CreateAnalyzer(IServiceProvider services);
}

View File

@@ -1,16 +1,16 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Logging;
using StellaOps.Plugin;
using StellaOps.Plugin.Hosting;
using StellaOps.Scanner.Analyzers.OS.Abstractions;
using StellaOps.Scanner.Core.Security;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Logging;
using StellaOps.Plugin;
using StellaOps.Plugin.Hosting;
using StellaOps.Scanner.Analyzers.OS.Abstractions;
using StellaOps.Scanner.Core.Security;
namespace StellaOps.Scanner.Analyzers.OS.Plugin;
public interface IOSAnalyzerPluginCatalog
@@ -24,124 +24,124 @@ public interface IOSAnalyzerPluginCatalog
public sealed class OsAnalyzerPluginCatalog : IOSAnalyzerPluginCatalog
{
private readonly ILogger<OsAnalyzerPluginCatalog> _logger;
private readonly IPluginCatalogGuard _guard;
private readonly ConcurrentDictionary<string, Assembly> _assemblies = new(StringComparer.OrdinalIgnoreCase);
private IReadOnlyList<IOSAnalyzerPlugin> _plugins = Array.Empty<IOSAnalyzerPlugin>();
public OsAnalyzerPluginCatalog(IPluginCatalogGuard guard, ILogger<OsAnalyzerPluginCatalog> logger)
{
_guard = guard ?? throw new ArgumentNullException(nameof(guard));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public IReadOnlyCollection<IOSAnalyzerPlugin> Plugins => _plugins;
public void LoadFromDirectory(string directory, bool seal = true)
{
ArgumentException.ThrowIfNullOrWhiteSpace(directory);
var fullDirectory = Path.GetFullPath(directory);
var options = new PluginHostOptions
{
PluginsDirectory = fullDirectory,
EnsureDirectoryExists = false,
RecursiveSearch = false,
};
options.SearchPatterns.Add("StellaOps.Scanner.Analyzers.*.dll");
var result = PluginHost.LoadPlugins(options, _logger);
if (result.Plugins.Count == 0)
{
_logger.LogWarning("No OS analyzer plug-ins discovered under '{Directory}'.", fullDirectory);
}
foreach (var descriptor in result.Plugins)
{
try
{
_guard.EnsureRegistrationAllowed(descriptor.AssemblyPath);
_assemblies[descriptor.AssemblyPath] = descriptor.Assembly;
_logger.LogInformation("Registered OS analyzer plug-in assembly '{Assembly}' from '{Path}'.",
descriptor.Assembly.FullName,
descriptor.AssemblyPath);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to register analyzer plug-in '{Path}'.", descriptor.AssemblyPath);
}
}
RefreshPluginList();
if (seal)
{
_guard.Seal();
}
}
public IReadOnlyList<IOSPackageAnalyzer> CreateAnalyzers(IServiceProvider services)
{
ArgumentNullException.ThrowIfNull(services);
if (_plugins.Count == 0)
{
_logger.LogWarning("No OS analyzer plug-ins available; scanning will skip OS package extraction.");
return Array.Empty<IOSPackageAnalyzer>();
}
var analyzers = new List<IOSPackageAnalyzer>(_plugins.Count);
foreach (var plugin in _plugins)
{
if (!IsPluginAvailable(plugin, services))
{
continue;
}
try
{
var analyzer = plugin.CreateAnalyzer(services);
if (analyzer is null)
{
continue;
}
analyzers.Add(analyzer);
}
catch (Exception ex)
{
_logger.LogError(ex, "Analyzer plug-in '{Plugin}' failed to create analyzer instance.", plugin.Name);
}
}
if (analyzers.Count == 0)
{
_logger.LogWarning("All OS analyzer plug-ins were unavailable.");
return Array.Empty<IOSPackageAnalyzer>();
}
analyzers.Sort(static (a, b) => string.CompareOrdinal(a.AnalyzerId, b.AnalyzerId));
return new ReadOnlyCollection<IOSPackageAnalyzer>(analyzers);
}
private void RefreshPluginList()
{
var assemblies = _assemblies.Values.ToArray();
var plugins = PluginLoader.LoadPlugins<IOSAnalyzerPlugin>(assemblies);
_plugins = plugins is IReadOnlyList<IOSAnalyzerPlugin> list
? list
: new ReadOnlyCollection<IOSAnalyzerPlugin>(plugins.ToArray());
}
private static bool IsPluginAvailable(IOSAnalyzerPlugin plugin, IServiceProvider services)
{
try
{
return plugin.IsAvailable(services);
}
catch
{
return false;
}
}
}
private readonly ILogger<OsAnalyzerPluginCatalog> _logger;
private readonly IPluginCatalogGuard _guard;
private readonly ConcurrentDictionary<string, Assembly> _assemblies = new(StringComparer.OrdinalIgnoreCase);
private IReadOnlyList<IOSAnalyzerPlugin> _plugins = Array.Empty<IOSAnalyzerPlugin>();
public OsAnalyzerPluginCatalog(IPluginCatalogGuard guard, ILogger<OsAnalyzerPluginCatalog> logger)
{
_guard = guard ?? throw new ArgumentNullException(nameof(guard));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public IReadOnlyCollection<IOSAnalyzerPlugin> Plugins => _plugins;
public void LoadFromDirectory(string directory, bool seal = true)
{
ArgumentException.ThrowIfNullOrWhiteSpace(directory);
var fullDirectory = Path.GetFullPath(directory);
var options = new PluginHostOptions
{
PluginsDirectory = fullDirectory,
EnsureDirectoryExists = false,
RecursiveSearch = false,
};
options.SearchPatterns.Add("StellaOps.Scanner.Analyzers.*.dll");
var result = PluginHost.LoadPlugins(options, _logger);
if (result.Plugins.Count == 0)
{
_logger.LogWarning("No OS analyzer plug-ins discovered under '{Directory}'.", fullDirectory);
}
foreach (var descriptor in result.Plugins)
{
try
{
_guard.EnsureRegistrationAllowed(descriptor.AssemblyPath);
_assemblies[descriptor.AssemblyPath] = descriptor.Assembly;
_logger.LogInformation("Registered OS analyzer plug-in assembly '{Assembly}' from '{Path}'.",
descriptor.Assembly.FullName,
descriptor.AssemblyPath);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to register analyzer plug-in '{Path}'.", descriptor.AssemblyPath);
}
}
RefreshPluginList();
if (seal)
{
_guard.Seal();
}
}
public IReadOnlyList<IOSPackageAnalyzer> CreateAnalyzers(IServiceProvider services)
{
ArgumentNullException.ThrowIfNull(services);
if (_plugins.Count == 0)
{
_logger.LogWarning("No OS analyzer plug-ins available; scanning will skip OS package extraction.");
return Array.Empty<IOSPackageAnalyzer>();
}
var analyzers = new List<IOSPackageAnalyzer>(_plugins.Count);
foreach (var plugin in _plugins)
{
if (!IsPluginAvailable(plugin, services))
{
continue;
}
try
{
var analyzer = plugin.CreateAnalyzer(services);
if (analyzer is null)
{
continue;
}
analyzers.Add(analyzer);
}
catch (Exception ex)
{
_logger.LogError(ex, "Analyzer plug-in '{Plugin}' failed to create analyzer instance.", plugin.Name);
}
}
if (analyzers.Count == 0)
{
_logger.LogWarning("All OS analyzer plug-ins were unavailable.");
return Array.Empty<IOSPackageAnalyzer>();
}
analyzers.Sort(static (a, b) => string.CompareOrdinal(a.AnalyzerId, b.AnalyzerId));
return new ReadOnlyCollection<IOSPackageAnalyzer>(analyzers);
}
private void RefreshPluginList()
{
var assemblies = _assemblies.Values.ToArray();
var plugins = PluginLoader.LoadPlugins<IOSAnalyzerPlugin>(assemblies);
_plugins = plugins is IReadOnlyList<IOSAnalyzerPlugin> list
? list
: new ReadOnlyCollection<IOSAnalyzerPlugin>(plugins.ToArray());
}
private static bool IsPluginAvailable(IOSAnalyzerPlugin plugin, IServiceProvider services)
{
try
{
return plugin.IsAvailable(services);
}
catch
{
return false;
}
}
}