Documentation
¶
Overview ¶
Package audit provides security audit functionality for OPNsense configurations against industry-standard compliance frameworks through a plugin-based architecture.
Package audit provides security audit functionality for OPNsense configurations against industry-standard compliance frameworks through a plugin-based architecture.
Index ¶
- Variables
- func GetGlobalPlugin(name string) (compliance.Plugin, error)
- func ListGlobalPlugins() []string
- func RegisterGlobalPlugin(p compliance.Plugin) error
- type AttackSurface
- type ComplianceResult
- type ComplianceSummary
- type Finding
- type LoadResult
- type ModeConfig
- type ModeController
- type Options
- type PluginCompliance
- type PluginInfo
- type PluginLoadError
- type PluginManager
- func (pm *PluginManager) GetLoadResult() LoadResult
- func (pm *PluginManager) GetPluginControlInfo(pluginName, controlID string) (*compliance.Control, error)
- func (pm *PluginManager) GetPluginStatistics() map[string]any
- func (pm *PluginManager) GetRegistry() *PluginRegistry
- func (pm *PluginManager) InitializePlugins(ctx context.Context) error
- func (pm *PluginManager) ListAvailablePlugins(ctx context.Context) []PluginInfo
- func (pm *PluginManager) RunComplianceAudit(ctx context.Context, device *common.CommonDevice, pluginNames []string) (*ComplianceResult, error)
- func (pm *PluginManager) SetPluginDir(dir string, explicit bool)
- func (pm *PluginManager) ValidatePluginConfiguration(pluginName string) error
- type PluginRegistry
- func (pr *PluginRegistry) GetPlugin(name string) (compliance.Plugin, error)
- func (pr *PluginRegistry) ListPlugins() []string
- func (pr *PluginRegistry) LoadDynamicPlugins(ctx context.Context, dir string, explicitDir bool, logger *logging.Logger) (LoadResult, error)
- func (pr *PluginRegistry) RegisterPlugin(p compliance.Plugin) error
- func (pr *PluginRegistry) RunComplianceChecks(device *common.CommonDevice, pluginNames []string, logger *logging.Logger) (*ComplianceResult, error)
- type Report
- type ReportMode
Constants ¶
This section is empty.
Variables ¶
var ( // ErrModeConfigNil is returned when the mode configuration is nil. ErrModeConfigNil = errors.New("mode config cannot be nil") // ErrUnsupportedMode is returned when an unsupported report mode is specified. ErrUnsupportedMode = errors.New("unsupported report mode") // ErrPluginNotFound is returned when a requested compliance plugin cannot be found. ErrPluginNotFound = errors.New("plugin not found") // ErrConfigurationNil is returned when the OPNsense configuration is nil. ErrConfigurationNil = errors.New("configuration cannot be nil") // ErrDuplicatePlugin is returned when the same plugin appears more than once in the selection. ErrDuplicatePlugin = errors.New("duplicate plugin in selection") )
Static errors for better error handling.
Functions ¶
func GetGlobalPlugin ¶
func GetGlobalPlugin(name string) (compliance.Plugin, error)
GetGlobalPlugin retrieves a plugin from the global registry.
func ListGlobalPlugins ¶
func ListGlobalPlugins() []string
ListGlobalPlugins returns all plugins in the global registry.
func RegisterGlobalPlugin ¶
func RegisterGlobalPlugin(p compliance.Plugin) error
RegisterGlobalPlugin registers a compliance plugin with the global singleton registry. All calls to RegisterGlobalPlugin should occur during sequential application startup before the registry is accessed concurrently for reads. While the underlying PluginRegistry.RegisterPlugin is mutex-protected and technically safe to call concurrently, the application's intended pattern is register-at-startup, read-during-operation.
Note: PluginManager.InitializePlugins() populates the manager's own PluginRegistry, not this global singleton. Callers that need plugins in the global registry must call RegisterGlobalPlugin() directly.
Types ¶
type AttackSurface ¶
type AttackSurface struct {
Type string `json:"type"`
Ports []int `json:"ports"`
Services []string `json:"services"`
Vulnerabilities []string `json:"vulnerabilities"`
}
AttackSurface represents attack surface information for red team findings.
type ComplianceResult ¶
type ComplianceResult struct {
Findings []compliance.Finding `json:"findings"`
PluginFindings map[string][]compliance.Finding `json:"pluginFindings"`
Compliance map[string]map[string]bool `json:"compliance"`
Summary *ComplianceSummary `json:"summary"`
PluginInfo map[string]PluginInfo `json:"pluginInfo"`
}
ComplianceResult represents the complete result of compliance checks.
type ComplianceSummary ¶
type ComplianceSummary struct {
TotalFindings int `json:"totalFindings"`
CriticalFindings int `json:"criticalFindings"`
HighFindings int `json:"highFindings"`
MediumFindings int `json:"mediumFindings"`
LowFindings int `json:"lowFindings"`
PluginCount int `json:"pluginCount"`
Compliance map[string]PluginCompliance `json:"compliance"`
}
ComplianceSummary provides summary statistics.
type Finding ¶
type Finding struct {
analysis.Finding
AttackSurface *AttackSurface `json:"attackSurface,omitempty"`
ExploitNotes string `json:"exploitNotes,omitempty"`
Control string `json:"control,omitempty"`
}
Finding represents a security finding or audit result. It embeds analysis.Finding for the common fields (Title, Severity, Description, Recommendation, Component, Tags, etc.) and adds audit-specific extensions.
type LoadResult ¶ added in v1.3.0
type LoadResult struct {
Loaded int
Failures []PluginLoadError
}
LoadResult summarises the outcome of a LoadDynamicPlugins call, reporting how many plugins loaded successfully, how many failed, and the individual failure details. The zero value represents "no dynamic plugins attempted".
func (LoadResult) Failed ¶ added in v1.3.0
func (r LoadResult) Failed() int
Failed returns the number of plugins that failed to load.
type ModeConfig ¶
type ModeConfig struct {
Mode ReportMode
Comprehensive bool
SelectedPlugins []string
TemplateDir string
}
ModeConfig holds configuration options for report generation.
type ModeController ¶
type ModeController struct {
// contains filtered or unexported fields
}
ModeController manages the generation of different types of audit reports based on the selected mode and configuration.
func NewModeController ¶
func NewModeController(registry *PluginRegistry, logger *logging.Logger) *ModeController
NewModeController creates a new mode controller with the given plugin registry and logger.
func (*ModeController) GenerateReport ¶
func (mc *ModeController) GenerateReport( ctx context.Context, device *common.CommonDevice, config *ModeConfig, ) (*Report, error)
GenerateReport generates an audit report based on the specified mode and configuration.
func (*ModeController) ValidateModeConfig ¶
func (mc *ModeController) ValidateModeConfig(config *ModeConfig) error
ValidateModeConfig validates the mode configuration.
type Options ¶ added in v1.3.0
type Options struct {
// AuditMode specifies the audit reporting mode (blue, red).
AuditMode string
// SelectedPlugins specifies which compliance plugins to run.
SelectedPlugins []string
// PluginDir is the directory from which dynamic .so plugins are loaded.
// When non-empty, LoadDynamicPlugins scans this path during InitializePlugins.
PluginDir string
// ExplicitPluginDir indicates that PluginDir was explicitly configured by
// the user (via CLI flag). When true and the directory does not exist,
// LoadDynamicPlugins returns an error instead of silently continuing.
ExplicitPluginDir bool
}
Options contains configuration for audit report generation. Options is separate from converter.Options because audit concerns (mode selection, compliance plugins) are orthogonal to conversion concerns (format, theme, wrapping).
type PluginCompliance ¶
type PluginCompliance struct {
Compliant int `json:"compliant"`
NonCompliant int `json:"nonCompliant"`
Total int `json:"total"`
}
PluginCompliance represents compliance statistics for a single plugin.
type PluginInfo ¶
type PluginInfo struct {
Name string `json:"name"`
Version string `json:"version"`
Description string `json:"description"`
Controls []compliance.Control `json:"controls"`
}
PluginInfo contains metadata about a plugin.
type PluginLoadError ¶ added in v1.3.0
PluginLoadError records a single dynamic plugin that failed to load, capturing the .so filename and the underlying error. It implements the error interface for use with errors.Join.
func (PluginLoadError) Error ¶ added in v1.3.0
func (f PluginLoadError) Error() string
Error returns a human-readable description of the load failure.
func (PluginLoadError) Unwrap ¶ added in v1.3.0
func (f PluginLoadError) Unwrap() error
Unwrap returns the underlying error that caused the plugin load to fail. This allows consumers to use errors.Is and errors.As with PluginLoadError, including when these errors are combined via errors.Join.
type PluginManager ¶
type PluginManager struct {
// contains filtered or unexported fields
}
PluginManager manages the lifecycle of compliance plugins.
func NewPluginManager ¶
func NewPluginManager(logger *logging.Logger) *PluginManager
NewPluginManager creates a new plugin manager.
func (*PluginManager) GetLoadResult ¶ added in v1.3.0
func (pm *PluginManager) GetLoadResult() LoadResult
GetLoadResult returns the result of the most recent LoadDynamicPlugins call performed during InitializePlugins. If no dynamic plugin directory was configured, or InitializePlugins has not been called, the zero-value LoadResult is returned. The Failures slice is copied so callers cannot mutate the manager's internal slice state; error values within each PluginLoadError are shared references.
func (*PluginManager) GetPluginControlInfo ¶
func (pm *PluginManager) GetPluginControlInfo(pluginName, controlID string) (*compliance.Control, error)
GetPluginControlInfo returns detailed information about a specific control.
func (*PluginManager) GetPluginStatistics ¶
func (pm *PluginManager) GetPluginStatistics() map[string]any
GetPluginStatistics returns statistics about plugin usage and plugin.
func (*PluginManager) GetRegistry ¶
func (pm *PluginManager) GetRegistry() *PluginRegistry
GetRegistry returns the plugin registry.
func (*PluginManager) InitializePlugins ¶
func (pm *PluginManager) InitializePlugins(ctx context.Context) error
InitializePlugins registers all built-in compliance plugins (STIG, SANS, Firewall) with the manager's own PluginRegistry. This method is the sequential initialization entrypoint and must be called during application startup before the manager's registry is used concurrently. All built-in plugin registration for this manager happens here, ensuring the manager's registry is fully populated before any concurrent audit operations begin. Callers must not invoke this method concurrently.
Dynamic plugin loading: if SetPluginDir was called before this method, dynamic .so plugins are loaded from the configured directory. Per-plugin load failures are non-fatal — they do NOT cause InitializePlugins to return an error. Callers must inspect GetLoadResult() after this method returns to detect and surface dynamic plugin load failures.
Note: this populates pm.registry only, not the global singleton returned by GetGlobalRegistry(). If plugins need to be available via the global registry, callers must use RegisterGlobalPlugin() separately.
func (*PluginManager) ListAvailablePlugins ¶
func (pm *PluginManager) ListAvailablePlugins(ctx context.Context) []PluginInfo
ListAvailablePlugins returns information about all available plugins.
func (*PluginManager) RunComplianceAudit ¶
func (pm *PluginManager) RunComplianceAudit( ctx context.Context, device *common.CommonDevice, pluginNames []string, ) (*ComplianceResult, error)
RunComplianceAudit runs compliance checks using specified plugins.
func (*PluginManager) SetPluginDir ¶ added in v1.3.0
func (pm *PluginManager) SetPluginDir(dir string, explicit bool)
SetPluginDir configures the directory from which dynamic .so plugins are loaded during InitializePlugins. The explicit flag controls the behavior when the directory does not exist: true means the user explicitly configured this path (returns an error), false means it is a default/optional path (logs at Debug and continues).
func (*PluginManager) ValidatePluginConfiguration ¶
func (pm *PluginManager) ValidatePluginConfiguration(pluginName string) error
ValidatePluginConfiguration validates the configuration of a specific plugin.
type PluginRegistry ¶
type PluginRegistry struct {
// contains filtered or unexported fields
}
PluginRegistry manages the registration and retrieval of compliance plugins.
func GetGlobalRegistry ¶ added in v1.1.0
func GetGlobalRegistry() *PluginRegistry
GetGlobalRegistry returns the global plugin registry singleton, initializing it on first access via sync.Once. It is safe to call concurrently from multiple goroutines; the sync.Once guarantee ensures the initialization completes and its writes are visible before any caller receives the pointer. Subsequent calls return the same *PluginRegistry instance without further synchronization overhead.
func NewPluginRegistry ¶
func NewPluginRegistry() *PluginRegistry
NewPluginRegistry creates a new plugin registry with the default plugin loader.
func (*PluginRegistry) GetPlugin ¶
func (pr *PluginRegistry) GetPlugin(name string) (compliance.Plugin, error)
GetPlugin retrieves a plugin by name.
func (*PluginRegistry) ListPlugins ¶
func (pr *PluginRegistry) ListPlugins() []string
ListPlugins returns all registered plugin names.
func (*PluginRegistry) LoadDynamicPlugins ¶
func (pr *PluginRegistry) LoadDynamicPlugins( ctx context.Context, dir string, explicitDir bool, logger *logging.Logger, ) (LoadResult, error)
LoadDynamicPlugins loads .so plugins from the specified directory and registers them. When explicitDir is false, a missing directory is silently ignored (Debug log). When explicitDir is true, a missing directory returns an error because the user explicitly configured the path. A nil logger returns an error immediately. Per-plugin failures are collected in the returned LoadResult and aggregated into the returned error via errors.Join.
func (*PluginRegistry) RegisterPlugin ¶
func (pr *PluginRegistry) RegisterPlugin(p compliance.Plugin) error
RegisterPlugin registers a compliance plugin.
func (*PluginRegistry) RunComplianceChecks ¶
func (pr *PluginRegistry) RunComplianceChecks( device *common.CommonDevice, pluginNames []string, logger *logging.Logger, ) (*ComplianceResult, error)
RunComplianceChecks runs compliance checks for specified plugins. Each plugin's RunChecks call is wrapped in a panic recovery boundary so that a misbehaving (especially dynamically-loaded) plugin cannot crash the entire audit. Panicking plugins are logged and retained in the result with zero findings, ensuring downstream consumers can see they were requested and evaluated.
type Report ¶
type Report struct {
Mode ReportMode `json:"mode"`
Comprehensive bool `json:"comprehensive"`
Configuration *common.CommonDevice `json:"configuration"`
Findings []Finding `json:"findings"`
Compliance map[string]ComplianceResult `json:"compliance"`
Metadata map[string]any `json:"metadata"`
}
Report represents a comprehensive audit report with findings and analysis.
func (*Report) TotalFindingsCount ¶ added in v1.3.0
TotalFindingsCount returns the aggregate number of findings across both direct security findings (report.Findings) and per-plugin compliance findings (report.Compliance[*].Summary.TotalFindings). This ensures the top-level summary reflects the same totals as the per-plugin sections.
type ReportMode ¶
type ReportMode string
ReportMode represents the different types of audit reports that can be generated.
const ( // ModeBlue represents a defensive audit report with security findings and recommendations. ModeBlue ReportMode = "blue" // ModeRed represents an attacker-focused recon report highlighting attack surfaces. ModeRed ReportMode = "red" )
Report mode constants that determine the perspective and focus of audit output.
func ParseReportMode ¶
func ParseReportMode(s string) (ReportMode, error)
ParseReportMode parses a string into a ReportMode, returning an error if invalid.
func (ReportMode) String ¶
func (rm ReportMode) String() string
String returns the string representation of the ReportMode.