Skip to main content

A Python client library for both OPNsense and pfSense.

Project description

Routers

Project Overview

The Routers project is a Python-based tool designed to manage firewall aliases across different routers, specifically pfSense (v1 and v2) and OPNsense. It provides a unified interface for creating, updating, deleting, and renaming firewall aliases, while abstracting away the differences between the APIs of these platforms.

This tool leverages client libraries for pfSense and OPNsense APIs, allowing seamless interaction with their respective firewall alias management functionalities. The core of the project is the Router class which handles connection to different router types, and the alias adapters which convert between internal data structures and router-specific models.

Features

  • Unified Router Management: Connect to pfSense v1, pfSense v2, and OPNsense routers using a common interface.
  • Advanced Alias Operations: Create, update, delete, and rename firewall aliases without needing to know the details of the underlying API.
  • Secure Configuration Storage: Store router connection details securely using Redis with encryption.
  • Adapter Architecture: Flexible adapter system to handle different router types and API versions.
  • Difference Detection: Identify differences between aliases across routers to help with synchronization.
  • Comprehensive Testing: Includes a robust test suite with mock objects to ensure code correctness without needing live routers.

Installation

Prerequisites

  • Python 3.14 or higher
  • Core dependencies:
    • pyfsense-client - Client library for pfSense
    • opn-api - Client library for OPNsense
    • redis[hiredis] - For configuration storage
    • cryptography - For secure configuration storage
    • Additional dependencies specified in pyproject.toml

Steps

  1. Clone this repository:

    git clone https://github.com/devinbarry/routers.git
    cd routers
    
  2. Install dependencies:

    uv sync
    

Project Structure

routers/
│
├── src/routers/
│   ├── __init__.py
│   ├── settings.py                    # Environment configuration
│   ├── firewall.py                    # Firewall utilities
│   ├── alias/                         # Alias management
│   │   ├── types.py                   # Alias dataclass, AliasType enum
│   │   ├── operations.py              # High-level sync operations
│   │   ├── loader.py                  # JSON alias loading & reference lookup
│   │   ├── adapter_factory.py         # Creates adapter for a given router
│   │   ├── type_conversions.py        # Router-specific format conversions
│   │   ├── exceptions.py              # Alias exceptions
│   │   └── adapter/                   # Platform-specific adapters
│   │       ├── base.py                # Abstract adapter interface
│   │       ├── pfsense_v1.py          # pfSense v1 adapter
│   │       ├── pfsense_v2.py          # pfSense v2 adapter
│   │       └── opnsense.py            # OPNsense adapter
│   ├── client/
│   │   └── pfsense_v2.py              # PfSenseV2MetaClient wrapper
│   └── router/
│       ├── core.py                    # Router dataclass, RouterType, ClientFactory
│       ├── exceptions.py              # Router exceptions
│       └── config/
│           ├── encrypt.py             # Fernet-encrypted Redis wrapper
│           └── store.py               # ConfigLoader & CredentialStore
│
├── tests/                             # Test suite organized by module
├── pyproject.toml
└── README.md

Usage

Initialize a Router

from routers import Router, RouterType

router = Router(name="MyRouter", type=RouterType.PFSENSE_V2)

Router credentials are loaded from encrypted Redis via ConfigLoader. See router/config/ for setup.

Direct Alias Operations (Adapter)

Use the adapter for direct CRUD on individual aliases:

from routers.alias.adapter_factory import get_alias_adapter
from routers.alias.types import Alias, AliasType

adapter = get_alias_adapter(router)

# List all aliases
aliases = adapter.get_all_aliases()

# Create
alias = Alias(
    name="BlockList",
    alias_type=AliasType.HOST,
    description="Block list of IPs",
    content=["192.168.1.1", "192.168.1.2"],
    detail=["IP1", "IP2"],
)
adapter.create_alias(alias)

# Update
alias.description = "Updated block list"
adapter.update_alias(alias)

# Delete
adapter.delete_alias("BlockList")

# Rename
adapter.rename_alias(alias, "NewBlockList")

Sync Operations (Reference-Based)

The operations module syncs router aliases against reference definitions:

from routers.alias.operations import (
    print_differing_client_aliases,
    update_differences_on_client,
    create_new_on_client,
    delete_missing_reference_aliases,
)

# Show differences between router state and reference aliases
print_differing_client_aliases(router)

# Sync: update differing aliases, create missing ones
update_differences_on_client(router)

# Create only missing aliases (no updates)
create_new_on_client(router)

# Delete aliases not in the reference list
delete_missing_reference_aliases(router)

Test Suite

Run the tests with pytest:

uv run pytest

Tests use mock objects -- no live routers required.

Contributing

Contributions are welcome. Fork the repository, submit a pull request, and include tests where applicable.

License

This project is licensed under the AGPLv3 License. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

routers-0.1.3.tar.gz (42.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

routers-0.1.3-py3-none-any.whl (47.8 kB view details)

Uploaded Python 3

File details

Details for the file routers-0.1.3.tar.gz.

File metadata

  • Download URL: routers-0.1.3.tar.gz
  • Upload date:
  • Size: 42.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for routers-0.1.3.tar.gz
Algorithm Hash digest
SHA256 4c224265148d3393f73c96d755e25677916e356cfb1d8b21e24e775e11c8352e
MD5 05c08fd65a8031d04878967440fb0a2f
BLAKE2b-256 e9d188cf23d46688731f5ab7398903b4450e22bb042d2f538e070d2eeabad65c

See more details on using hashes here.

File details

Details for the file routers-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: routers-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 47.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for routers-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0ba995358d0840b333d56a2cf742e7d1738de0a12e6018e3fb337ca50545de1e
MD5 1221f5d5cd41635ecd9c6c5132a132c8
BLAKE2b-256 db557f61464d9831114ac4dd0424e6cadbebc5d51722640832facea0f2a6fe29

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page