Skip to main content
Glama

OPNSense MCP Server

resource-model.md10.9 kB
# Resource Model Deep dive into the Infrastructure as Code resource system. ## Resource Architecture ### Resource Definition Every resource follows this structure: ```typescript interface Resource { // Identity id: string; // Unique identifier type: string; // Resource type name?: string; // Human-readable name // Configuration properties: Record<string, any>; // Resource-specific properties metadata?: ResourceMetadata; // Additional metadata // Relationships dependencies?: Dependency[]; // Other resources this depends on // State outputs?: Record<string, any>; // Values produced by resource status?: ResourceStatus; // Current status } ``` ### Resource Types Format: `provider:category:resource` Examples: - `opnsense:network:vlan` - `opnsense:firewall:rule` - `opnsense:services:dhcp` ## Resource Categories ### Network Resources #### VLAN Resource ```typescript type: "opnsense:network:vlan" properties: { interface: string; // Physical interface (e.g., "igc3") tag: number; // VLAN tag (1-4094) description?: string; // Description subnet?: string; // IP subnet (e.g., "192.168.10.0/24") gateway?: string; // Gateway IP dhcp?: boolean; // Enable DHCP } outputs: { interface: string; // Created interface name (e.g., "igc3_vlan10") subnet: string; // Configured subnet gateway: string; // Gateway IP } ``` #### Interface Resource ```typescript type: "opnsense:network:interface" properties: { name: string; // Interface name enabled: boolean; // Enable interface description?: string; // Description ipv4?: { type: "static" | "dhcp" | "none"; address?: string; // Static IP subnet?: number; // Subnet mask bits }; ipv6?: { type: "static" | "dhcp" | "none"; address?: string; prefix?: number; }; } outputs: { mac: string; // MAC address status: string; // up/down ip: string; // Assigned IP } ``` ### Firewall Resources #### Rule Resource ```typescript type: "opnsense:firewall:rule" properties: { interface: string; // Interface or alias direction?: "in" | "out"; // Default: "in" action: "pass" | "block" | "reject"; protocol?: string; // tcp, udp, icmp, any source?: { address?: string; // IP, network, or alias port?: string | number; // Port or range not?: boolean; // Negate }; destination?: { address?: string; port?: string | number; not?: boolean; }; description?: string; log?: boolean; enabled?: boolean; } outputs: { uuid: string; // Rule UUID position: number; // Rule position } ``` #### Alias Resource ```typescript type: "opnsense:firewall:alias" properties: { name: string; // Alias name type: "host" | "network" | "port" | "url"; content: string[]; // List of values description?: string; enabled?: boolean; } outputs: { uuid: string; resolved: string[]; // Resolved values } ``` #### NAT Resource ```typescript type: "opnsense:firewall:nat" properties: { interface: string; // WAN interface protocol: string; // tcp, udp, tcp/udp source_port: number; // External port destination: string; // Internal IP destination_port: number; // Internal port description?: string; reflection?: boolean; // NAT reflection } outputs: { uuid: string; rule_id: string; // Associated firewall rule } ``` ### Service Resources #### DHCP Resource ```typescript type: "opnsense:services:dhcp" properties: { interface: string; // Interface name or reference enabled: boolean; range: { from: string; // Start IP to: string; // End IP }; gateway?: string; // Default gateway dns?: string[]; // DNS servers domain?: string; // Domain name lease_time?: number; // Seconds static_mappings?: Array<{ mac: string; // MAC address ip: string; // Static IP hostname?: string; // Hostname description?: string; }>; options?: Array<{ number: number; // DHCP option number value: string; // Option value }>; } outputs: { active_leases: number; // Current lease count pool_usage: number; // Percentage used } ``` #### DNS Blocklist Resource ```typescript type: "opnsense:services:dns:blocklist" properties: { domains: string[]; // Domains to block categories?: string[]; // Predefined categories description?: string; enabled?: boolean; } outputs: { blocked_count: number; // Total blocked domains } ``` #### HAProxy Backend Resource ```typescript type: "opnsense:services:haproxy:backend" properties: { name: string; mode: "http" | "tcp"; balance: "roundrobin" | "leastconn" | "source" | "uri"; servers: Array<{ name: string; address: string; port: number; ssl?: boolean; check?: boolean; weight?: number; }>; health_check?: { type: "http" | "tcp"; path?: string; // HTTP check path interval?: number; // Seconds timeout?: number; }; } outputs: { uuid: string; status: string; // UP/DOWN active_servers: number; } ``` ## Resource Relationships ### Dependencies Resources can depend on others: ```yaml resources: - id: vlan-10 type: opnsense:network:vlan properties: tag: 10 - id: dhcp-vlan-10 type: opnsense:services:dhcp dependencies: - resourceId: vlan-10 type: hard outputRef: interface properties: interface: "${vlan-10.interface}" ``` ### Dependency Types **Hard Dependencies**: Must exist before creation ```typescript { type: "hard", resourceId: "other-resource", outputRef: "interface" } ``` **Soft Dependencies**: Preferred order but not required ```typescript { type: "soft", resourceId: "monitoring-setup" } ``` ### Reference Resolution Reference other resource outputs: ```yaml properties: # Direct reference interface: "${vlan-10.interface}" # Nested reference subnet: "${dhcp-config.outputs.subnet}" # Function reference ip: "${cidr_host(vlan-10.subnet, 1)}" ``` ## Resource Validation ### Schema Validation Each resource type has a Zod schema: ```typescript const VlanSchema = z.object({ interface: z.string().regex(/^[a-z]+[0-9]+$/), tag: z.number().min(1).max(4094), description: z.string().optional(), subnet: z.string().ip({ version: "v4" }).optional(), gateway: z.string().ip({ version: "v4" }).optional(), dhcp: z.boolean().optional() }); ``` ### Custom Validation Resources can implement custom validation: ```typescript class VlanResource extends IaCResource { validate(): ValidationResult { const schemaResult = this.schema.safeParse(this.properties); if (!schemaResult.success) { return { valid: false, errors: schemaResult.error.errors }; } // Custom validation if (this.properties.gateway && !this.properties.subnet) { return { valid: false, errors: ["Gateway requires subnet to be defined"] }; } return { valid: true }; } } ``` ## Resource Lifecycle ### Creation Flow 1. **Validation**: Schema and custom validation 2. **Dependency Resolution**: Ensure dependencies exist 3. **Reference Resolution**: Replace references with values 4. **API Mapping**: Convert to API format 5. **Execution**: Call OPNsense API 6. **Output Collection**: Gather resource outputs 7. **State Update**: Save to state database ### Update Flow 1. **Diff Calculation**: Compare desired vs current 2. **Validation**: Validate changes 3. **Update Plan**: Determine update strategy 4. **Execution**: Apply changes 5. **Verification**: Confirm changes applied 6. **State Update**: Update state database ### Deletion Flow 1. **Dependency Check**: Ensure no resources depend on this 2. **Pre-deletion**: Run cleanup tasks 3. **API Call**: Delete from OPNsense 4. **State Removal**: Remove from state database 5. **Cascade**: Handle dependent deletions ## State Management ### State Structure ```typescript interface ResourceState { id: string; type: string; name: string; properties: Record<string, any>; outputs: Record<string, any>; metadata: { createdAt: Date; updatedAt: Date; createdBy: string; version: number; }; status: { state: "creating" | "active" | "updating" | "deleting" | "failed"; message?: string; lastError?: string; }; } ``` ### State Operations **Read State**: Get current infrastructure state ```typescript const state = await stateManager.readState("deployment-id"); ``` **Write State**: Update after changes ```typescript await stateManager.writeState("deployment-id", newState); ``` **Lock State**: Prevent concurrent modifications ```typescript const lock = await stateManager.acquireLock("deployment-id"); try { // Make changes } finally { await lock.release(); } ``` ## Resource Registry ### Registration Register custom resources: ```typescript resourceRegistry.register({ type: "opnsense:custom:myresource", category: "custom", schema: MyResourceSchema, factory: (id, name, props) => new MyResource(id, name, props), validator: (props) => validateMyResource(props), apiMapper: (props) => mapToAPI(props) }); ``` ### Discovery Find available resources: ```typescript // List all resource types const types = resourceRegistry.listTypes(); // Get resource by type const resourceClass = resourceRegistry.get("opnsense:network:vlan"); // Filter by category const networkResources = resourceRegistry.getByCategory("network"); ``` ## Best Practices ### 1. Resource Naming - Use descriptive IDs: `web-server-vlan` not `vlan1` - Include environment: `prod-database-vlan` - Be consistent: always use hyphens or underscores ### 2. Property Organization - Group related properties - Use consistent naming - Provide sensible defaults - Document required vs optional ### 3. Output Design - Output useful values - Keep outputs minimal - Use consistent naming - Document output types ### 4. Dependency Management - Minimize dependencies - Use soft dependencies when possible - Avoid circular dependencies - Document dependency reasons ### 5. Validation - Validate early and often - Provide clear error messages - Check business logic - Validate references ## Next Steps - [Deployment Guide](deployment.md) - How to deploy resources - [Patterns](patterns.md) - Common resource patterns - [Examples](examples/) - Complete resource examples ## Related Documentation - [IaC Overview](overview.md) - [API Reference](../api-reference/resources.md) - [Troubleshooting](../troubleshooting/common-issues.md#iac)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vespo92/OPNSenseMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server