<# .SYNOPSIS Generates plugin configuration files for StellaOps modules. .DESCRIPTION This script generates plugin.json manifests and config.yaml files for all plugins based on the plugin catalog definition. .PARAMETER RepoRoot Path to the repository root. Defaults to the parent of the devops folder. .PARAMETER OutputDir Output directory for generated configs. Defaults to etc/plugins/. .PARAMETER Force Overwrite existing configuration files. .EXAMPLE .\generate-plugin-configs.ps1 .\generate-plugin-configs.ps1 -Force #> param( [string]$RepoRoot = (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)), [string]$OutputDir = "", [switch]$Force ) if (-not $OutputDir) { $OutputDir = Join-Path $RepoRoot "etc/plugins" } # Plugin catalog - defines all plugins and their metadata $PluginCatalog = @{ # Router transports "router/transports" = @{ category = "router.transports" plugins = @( @{ id = "tcp"; name = "TCP Transport"; assembly = "StellaOps.Router.Transport.Tcp.dll"; enabled = $true; priority = 50 } @{ id = "tls"; name = "TLS Transport"; assembly = "StellaOps.Router.Transport.Tls.dll"; enabled = $true; priority = 60 } @{ id = "udp"; name = "UDP Transport"; assembly = "StellaOps.Router.Transport.Udp.dll"; enabled = $false; priority = 40 } @{ id = "rabbitmq"; name = "RabbitMQ Transport"; assembly = "StellaOps.Router.Transport.RabbitMq.dll"; enabled = $false; priority = 30 } @{ id = "inmemory"; name = "In-Memory Transport"; assembly = "StellaOps.Router.Transport.InMemory.dll"; enabled = $false; priority = 10 } ) } # Excititor connectors "excititor" = @{ category = "excititor.connectors" plugins = @( @{ id = "redhat-csaf"; name = "Red Hat CSAF Connector"; assembly = "StellaOps.Excititor.Connectors.RedHat.CSAF.dll"; enabled = $true; priority = 100; vendor = "Red Hat" } @{ id = "cisco-csaf"; name = "Cisco CSAF Connector"; assembly = "StellaOps.Excititor.Connectors.Cisco.CSAF.dll"; enabled = $false; priority = 90; vendor = "Cisco" } @{ id = "msrc-csaf"; name = "Microsoft CSAF Connector"; assembly = "StellaOps.Excititor.Connectors.MSRC.CSAF.dll"; enabled = $false; priority = 85; vendor = "Microsoft" } @{ id = "oracle-csaf"; name = "Oracle CSAF Connector"; assembly = "StellaOps.Excititor.Connectors.Oracle.CSAF.dll"; enabled = $false; priority = 80; vendor = "Oracle" } @{ id = "ubuntu-csaf"; name = "Ubuntu CSAF Connector"; assembly = "StellaOps.Excititor.Connectors.Ubuntu.CSAF.dll"; enabled = $false; priority = 75; vendor = "Canonical" } @{ id = "suse-rancher"; name = "SUSE Rancher VEX Hub"; assembly = "StellaOps.Excititor.Connectors.SUSE.RancherVEXHub.dll"; enabled = $false; priority = 70; vendor = "SUSE" } @{ id = "oci-openvex"; name = "OCI OpenVEX Connector"; assembly = "StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest.dll"; enabled = $false; priority = 60 } ) } # Scanner language analyzers "scanner/analyzers/lang" = @{ category = "scanner.analyzers.lang" plugins = @( @{ id = "dotnet"; name = ".NET Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.DotNet.dll"; enabled = $true; priority = 100 } @{ id = "go"; name = "Go Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Go.dll"; enabled = $true; priority = 95 } @{ id = "node"; name = "Node.js Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Node.dll"; enabled = $true; priority = 90 } @{ id = "python"; name = "Python Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Python.dll"; enabled = $true; priority = 85 } @{ id = "java"; name = "Java Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Java.dll"; enabled = $true; priority = 80 } @{ id = "rust"; name = "Rust Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Rust.dll"; enabled = $false; priority = 75 } @{ id = "ruby"; name = "Ruby Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Ruby.dll"; enabled = $false; priority = 70 } @{ id = "php"; name = "PHP Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Php.dll"; enabled = $false; priority = 65 } @{ id = "swift"; name = "Swift Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Swift.dll"; enabled = $false; priority = 60 } @{ id = "cpp"; name = "C/C++ Analyzer"; assembly = "StellaOps.Scanner.Analyzers.Lang.Cpp.dll"; enabled = $false; priority = 55 } ) } # Scanner OS analyzers "scanner/analyzers/os" = @{ category = "scanner.analyzers.os" plugins = @( @{ id = "apk"; name = "Alpine APK Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Apk.dll"; enabled = $true; priority = 100 } @{ id = "dpkg"; name = "Debian DPKG Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Dpkg.dll"; enabled = $true; priority = 95 } @{ id = "rpm"; name = "RPM Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Rpm.dll"; enabled = $true; priority = 90 } @{ id = "pacman"; name = "Arch Pacman Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Pacman.dll"; enabled = $false; priority = 80 } @{ id = "homebrew"; name = "Homebrew Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Homebrew.dll"; enabled = $false; priority = 70 } @{ id = "chocolatey"; name = "Chocolatey Analyzer"; assembly = "StellaOps.Scanner.Analyzers.OS.Chocolatey.dll"; enabled = $false; priority = 65 } ) } # Notify channels "notify" = @{ category = "notify.channels" plugins = @( @{ id = "email"; name = "Email Notifier"; assembly = "StellaOps.Notify.Connectors.Email.dll"; enabled = $true; priority = 100 } @{ id = "slack"; name = "Slack Notifier"; assembly = "StellaOps.Notify.Connectors.Slack.dll"; enabled = $true; priority = 90 } @{ id = "webhook"; name = "Webhook Notifier"; assembly = "StellaOps.Notify.Connectors.Webhook.dll"; enabled = $true; priority = 80 } @{ id = "teams"; name = "Microsoft Teams Notifier"; assembly = "StellaOps.Notify.Connectors.Teams.dll"; enabled = $false; priority = 85 } @{ id = "pagerduty"; name = "PagerDuty Notifier"; assembly = "StellaOps.Notify.Connectors.PagerDuty.dll"; enabled = $false; priority = 75 } @{ id = "opsgenie"; name = "OpsGenie Notifier"; assembly = "StellaOps.Notify.Connectors.OpsGenie.dll"; enabled = $false; priority = 70 } @{ id = "telegram"; name = "Telegram Notifier"; assembly = "StellaOps.Notify.Connectors.Telegram.dll"; enabled = $false; priority = 65 } @{ id = "discord"; name = "Discord Notifier"; assembly = "StellaOps.Notify.Connectors.Discord.dll"; enabled = $false; priority = 60 } ) } # Messaging transports "messaging" = @{ category = "messaging.transports" plugins = @( @{ id = "valkey"; name = "Valkey Transport"; assembly = "StellaOps.Messaging.Transport.Valkey.dll"; enabled = $true; priority = 100 } @{ id = "postgres"; name = "PostgreSQL Transport"; assembly = "StellaOps.Messaging.Transport.Postgres.dll"; enabled = $false; priority = 90 } @{ id = "inmemory"; name = "In-Memory Transport"; assembly = "StellaOps.Messaging.Transport.InMemory.dll"; enabled = $false; priority = 10 } ) } } function New-PluginManifest { param( [string]$ModulePath, [hashtable]$Plugin, [string]$Category ) $fullId = "stellaops.$($Category.Replace('/', '.').Replace('.', '-')).$($Plugin.id)" $manifest = @{ '$schema' = "https://schema.stella-ops.org/plugin-manifest/v2.json" schemaVersion = "2.0" id = $fullId name = $Plugin.name version = "1.0.0" assembly = @{ path = $Plugin.assembly } capabilities = @() platforms = @("linux-x64", "linux-arm64", "win-x64", "osx-x64", "osx-arm64") compliance = @("NIST") jurisdiction = "world" priority = $Plugin.priority enabled = $Plugin.enabled metadata = @{ author = "StellaOps" license = "AGPL-3.0-or-later" } } if ($Plugin.vendor) { $manifest.metadata["vendor"] = $Plugin.vendor } return $manifest | ConvertTo-Json -Depth 10 } function New-PluginConfig { param( [string]$ModulePath, [hashtable]$Plugin, [string]$Category ) $fullId = "stellaops.$($Category.Replace('/', '.').Replace('.', '-')).$($Plugin.id)" $config = @" id: $fullId name: $($Plugin.name) enabled: $($Plugin.enabled.ToString().ToLower()) priority: $($Plugin.priority) config: # Plugin-specific configuration # Add settings here as needed "@ return $config } function New-RegistryFile { param( [string]$Category, [array]$Plugins ) $entries = $Plugins | ForEach-Object { " $($_.id):`n enabled: $($_.enabled.ToString().ToLower())`n priority: $($_.priority)`n config: $($_.id)/config.yaml" } $registry = @" version: "1.0" category: $Category defaults: enabled: false timeout: "00:05:00" plugins: $($entries -join "`n") "@ return $registry } # Main generation logic Write-Host "Generating plugin configurations to: $OutputDir" -ForegroundColor Cyan foreach ($modulePath in $PluginCatalog.Keys) { $moduleConfig = $PluginCatalog[$modulePath] $moduleDir = Join-Path $OutputDir $modulePath Write-Host "Processing module: $modulePath" -ForegroundColor Yellow # Create module directory if (-not (Test-Path $moduleDir)) { New-Item -ItemType Directory -Path $moduleDir -Force | Out-Null } # Generate registry.yaml $registryPath = Join-Path $moduleDir "registry.yaml" if ($Force -or -not (Test-Path $registryPath)) { $registryContent = New-RegistryFile -Category $moduleConfig.category -Plugins $moduleConfig.plugins Set-Content -Path $registryPath -Value $registryContent -Encoding utf8 Write-Host " Created: registry.yaml" -ForegroundColor Green } # Generate plugin configs foreach ($plugin in $moduleConfig.plugins) { $pluginDir = Join-Path $moduleDir $plugin.id if (-not (Test-Path $pluginDir)) { New-Item -ItemType Directory -Path $pluginDir -Force | Out-Null } # plugin.json $manifestPath = Join-Path $pluginDir "plugin.json" if ($Force -or -not (Test-Path $manifestPath)) { $manifestContent = New-PluginManifest -ModulePath $modulePath -Plugin $plugin -Category $moduleConfig.category Set-Content -Path $manifestPath -Value $manifestContent -Encoding utf8 Write-Host " Created: $($plugin.id)/plugin.json" -ForegroundColor Green } # config.yaml $configPath = Join-Path $pluginDir "config.yaml" if ($Force -or -not (Test-Path $configPath)) { $configContent = New-PluginConfig -ModulePath $modulePath -Plugin $plugin -Category $moduleConfig.category Set-Content -Path $configPath -Value $configContent -Encoding utf8 Write-Host " Created: $($plugin.id)/config.yaml" -ForegroundColor Green } } } Write-Host "`nPlugin configuration generation complete!" -ForegroundColor Cyan