Documentation
¶
Overview ¶
Package parser provides the factory for creating device-specific parsers that transform vendor configuration files into the platform-agnostic CommonDevice model.
Package parser provides the factory for creating device-specific parsers that transform vendor configuration files into the platform-agnostic CommonDevice model.
External consumers register custom DeviceParser implementations via init() and blank imports, following the database/sql driver registration pattern.
Package parser provides shared XML utilities for device-specific parsers.
Index ¶
Constants ¶
const DefaultMaxInputSize = 10 * 1024 * 1024 // 10MB
DefaultMaxInputSize is the default maximum size in bytes for XML input. This prevents XML bomb attacks by limiting how much data is read during root-element detection and parsing.
Variables ¶
This section is empty.
Functions ¶
func CharsetReader ¶
CharsetReader creates a reader for the specified XML charset declaration. Supported encodings: UTF-8, US-ASCII, ISO-8859-1 (Latin1), and Windows-1252. Only charsets whose ASCII subset matches UTF-8 are accepted, which is sufficient because XML element names use only ASCII-range characters.
func NewSecureXMLDecoder ¶
NewSecureXMLDecoder returns an *xml.Decoder configured with security hardening:
- Input size limited to maxSize bytes (prevents XML bomb attacks)
- Entity expansion disabled (prevents XXE attacks)
- Charset reader for UTF-8, US-ASCII, ISO-8859-1, and Windows-1252
Both the OPNsense and pfSense parsers delegate to this function to avoid duplicating security hardening logic.
func Register ¶
func Register(deviceType string, fn ConstructorFunc)
Register is a package-level convenience wrapper around DefaultRegistry().Register(). It follows the database/sql.Register() pattern for use in init() functions.
Types ¶
type ConstructorFunc ¶
type ConstructorFunc = func(XMLDecoder) DeviceParser
ConstructorFunc is the factory function signature for creating DeviceParser instances. The XMLDecoder parameter allows injection of the XML parsing backend. External parsers that manage their own XML decoding may ignore it.
type DeviceParser ¶
type DeviceParser interface {
// Parse reads and converts the configuration, returning non-fatal conversion warnings.
Parse(ctx context.Context, r io.Reader) (*common.CommonDevice, []common.ConversionWarning, error)
// ParseAndValidate reads, converts, and validates the configuration, returning non-fatal conversion warnings.
ParseAndValidate(ctx context.Context, r io.Reader) (*common.CommonDevice, []common.ConversionWarning, error)
}
DeviceParser is the interface for device-specific parsers. Implementations return non-fatal conversion warnings alongside the parsed device model. Callers should log or surface these warnings without treating them as errors.
type DeviceParserRegistry ¶
type DeviceParserRegistry struct {
// contains filtered or unexported fields
}
DeviceParserRegistry manages registered DeviceParser constructors, keyed by the lowercase XML root element name of the device type they handle. It is safe for concurrent use.
func DefaultRegistry ¶
func DefaultRegistry() *DeviceParserRegistry
DefaultRegistry returns the package-level DeviceParserRegistry singleton. External parsers call Register() on this instance from init().
func NewDeviceParserRegistry ¶
func NewDeviceParserRegistry() *DeviceParserRegistry
NewDeviceParserRegistry returns a new, empty DeviceParserRegistry. Use this constructor in tests to create isolated registry instances that do not pollute the global singleton.
func (*DeviceParserRegistry) Get ¶
func (r *DeviceParserRegistry) Get(deviceType string) (ConstructorFunc, bool)
Get returns the constructor for the given device type, or (nil, false) if no parser is registered for it. deviceType is normalized to lowercase with whitespace trimmed, matching the normalization applied by Register.
func (*DeviceParserRegistry) List ¶
func (r *DeviceParserRegistry) List() []string
List returns a sorted slice of all registered device type names. The returned slice is a copy and safe to modify.
func (*DeviceParserRegistry) Register ¶
func (r *DeviceParserRegistry) Register(deviceType string, fn ConstructorFunc)
Register adds a constructor for the given device type name. deviceType is normalized to lowercase with whitespace trimmed. Panics on duplicate registration, nil factory, or empty device type to surface wiring conflicts at startup (mirrors FormatRegistry and database/sql.Register contracts). Should only be called from init().
func (*DeviceParserRegistry) SupportedDevices ¶
func (r *DeviceParserRegistry) SupportedDevices() string
SupportedDevices returns a formatted string listing all registered device type names, suitable for error messages. When the registry is empty, it returns an actionable hint about missing blank imports. This is the single source of truth for supported-device messaging across factory errors and CLI validation.
type Factory ¶
type Factory struct {
// contains filtered or unexported fields
}
Factory detects device type and delegates to the appropriate DeviceParser. The XMLDecoder is injected at construction to keep pkg/ free of internal/ imports. The registry defaults to DefaultRegistry() unless overridden via NewFactoryWithRegistry (e.g., for isolated tests).
func NewFactory ¶
func NewFactory(decoder XMLDecoder) *Factory
NewFactory returns a new Factory that uses the given XMLDecoder for parsing and the global DefaultRegistry() for parser lookup. Pass cfgparser.NewXMLParser() from internal/cfgparser at the call site.
func NewFactoryWithRegistry ¶
func NewFactoryWithRegistry(decoder XMLDecoder, reg *DeviceParserRegistry) *Factory
NewFactoryWithRegistry returns a Factory that uses a custom registry instead of the global singleton. This is primarily useful for tests that need isolated registry state without polluting the global registry.
func (*Factory) CreateDevice ¶
func (f *Factory) CreateDevice( ctx context.Context, r io.Reader, deviceTypeOverride common.DeviceType, validateMode bool, ) (*common.CommonDevice, []common.ConversionWarning, error)
CreateDevice reads from r, detects (or uses the override) device type, and returns a fully converted CommonDevice along with any non-fatal conversion warnings. When validateMode is true, semantic validation is applied in addition to structural parsing.
type XMLDecoder ¶
type XMLDecoder interface {
// Parse reads XML from r and returns a parsed OpnSenseDocument.
Parse(ctx context.Context, r io.Reader) (*schema.OpnSenseDocument, error)
// ParseAndValidate reads XML from r, parses it, and applies semantic validation.
ParseAndValidate(ctx context.Context, r io.Reader) (*schema.OpnSenseDocument, error)
}
XMLDecoder parses raw XML input into an OpnSenseDocument. Implementations must handle charset detection, entity expansion protection, and input size limits. The cfgparser.XMLParser in internal/cfgparser provides the default implementation used by the CLI.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package opnsense provides an OPNsense-specific parser and converter that transforms schema.OpnSenseDocument into the platform-agnostic CommonDevice.
|
Package opnsense provides an OPNsense-specific parser and converter that transforms schema.OpnSenseDocument into the platform-agnostic CommonDevice. |
|
Package pfsense provides a pfSense-specific parser and converter that transforms pfsense.Document into the platform-agnostic CommonDevice.
|
Package pfsense provides a pfSense-specific parser and converter that transforms pfsense.Document into the platform-agnostic CommonDevice. |