firewall-aiops 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- firewall_aiops-0.1.0/.github/workflows/publish.yml +26 -0
- firewall_aiops-0.1.0/.gitignore +7 -0
- firewall_aiops-0.1.0/CHANGELOG.md +52 -0
- firewall_aiops-0.1.0/LICENSE +21 -0
- firewall_aiops-0.1.0/PKG-INFO +169 -0
- firewall_aiops-0.1.0/README.md +153 -0
- firewall_aiops-0.1.0/RELEASE_NOTES.md +67 -0
- firewall_aiops-0.1.0/SECURITY.md +78 -0
- firewall_aiops-0.1.0/firewall_aiops/__init__.py +9 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/__init__.py +9 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/_common.py +78 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/_root.py +57 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/doctor.py +21 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/init.py +113 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/log.py +25 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/overview.py +16 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/rules.py +73 -0
- firewall_aiops-0.1.0/firewall_aiops/cli/secret.py +105 -0
- firewall_aiops-0.1.0/firewall_aiops/config.py +152 -0
- firewall_aiops-0.1.0/firewall_aiops/connection.py +185 -0
- firewall_aiops-0.1.0/firewall_aiops/doctor.py +86 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/__init__.py +40 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/audit.py +377 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/budget.py +225 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/decorators.py +474 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/paths.py +23 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/patterns.py +378 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/policy.py +411 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/sanitize.py +39 -0
- firewall_aiops-0.1.0/firewall_aiops/governance/undo.py +218 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/__init__.py +1 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/_util.py +73 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/aliases.py +69 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/analysis.py +298 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/dhcp.py +52 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/diag.py +96 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/nat.py +76 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/overview.py +53 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/rules.py +97 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/system.py +115 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/vpn.py +75 -0
- firewall_aiops-0.1.0/firewall_aiops/ops/writes.py +141 -0
- firewall_aiops-0.1.0/firewall_aiops/platform.py +270 -0
- firewall_aiops-0.1.0/firewall_aiops/secretstore.py +302 -0
- firewall_aiops-0.1.0/mcp_server/__init__.py +1 -0
- firewall_aiops-0.1.0/mcp_server/_shared.py +104 -0
- firewall_aiops-0.1.0/mcp_server/server.py +40 -0
- firewall_aiops-0.1.0/mcp_server/tools/__init__.py +1 -0
- firewall_aiops-0.1.0/mcp_server/tools/aliases.py +32 -0
- firewall_aiops-0.1.0/mcp_server/tools/analysis.py +105 -0
- firewall_aiops-0.1.0/mcp_server/tools/dhcp.py +32 -0
- firewall_aiops-0.1.0/mcp_server/tools/diag.py +48 -0
- firewall_aiops-0.1.0/mcp_server/tools/nat.py +43 -0
- firewall_aiops-0.1.0/mcp_server/tools/rules.py +59 -0
- firewall_aiops-0.1.0/mcp_server/tools/system.py +55 -0
- firewall_aiops-0.1.0/mcp_server/tools/vpn.py +43 -0
- firewall_aiops-0.1.0/mcp_server/tools/writes.py +249 -0
- firewall_aiops-0.1.0/pyproject.toml +59 -0
- firewall_aiops-0.1.0/server.json +21 -0
- firewall_aiops-0.1.0/skills/firewall-aiops/SKILL.md +143 -0
- firewall_aiops-0.1.0/skills/firewall-aiops/references/capabilities.md +93 -0
- firewall_aiops-0.1.0/skills/firewall-aiops/references/cli-reference.md +51 -0
- firewall_aiops-0.1.0/skills/firewall-aiops/references/setup-guide.md +86 -0
- firewall_aiops-0.1.0/smithery.yaml +9 -0
- firewall_aiops-0.1.0/tests/conftest.py +25 -0
- firewall_aiops-0.1.0/tests/test_analysis.py +91 -0
- firewall_aiops-0.1.0/tests/test_platform.py +138 -0
- firewall_aiops-0.1.0/tests/test_reads.py +233 -0
- firewall_aiops-0.1.0/tests/test_secretstore.py +99 -0
- firewall_aiops-0.1.0/tests/test_smoke.py +119 -0
- firewall_aiops-0.1.0/tests/test_writes.py +154 -0
- firewall_aiops-0.1.0/uv.lock +962 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Trusted Publishing (OIDC) — publishes from GitHub's runners with no API token,
|
|
4
|
+
# sidestepping the local-IP / account new-project rate limit. Configure a matching
|
|
5
|
+
# "trusted publisher" for this package on PyPI (see the repo release notes).
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
publish:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write # required for PyPI Trusted Publishing (OIDC)
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- name: Set up uv
|
|
22
|
+
uses: astral-sh/setup-uv@v5
|
|
23
|
+
- name: Build sdist + wheel
|
|
24
|
+
run: uv build
|
|
25
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
26
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to firewall-aiops are documented here. This project adheres
|
|
4
|
+
to [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [0.1.0] — preview
|
|
7
|
+
|
|
8
|
+
Initial preview release: governed AI-ops for **OPNsense** and **pfSense**
|
|
9
|
+
firewalls, with a bundled governance harness. One MCP server spans both platforms
|
|
10
|
+
via a per-target `platform` field; the same tools work on either firewall.
|
|
11
|
+
**Mock-validated only — not yet verified against a live firewall.**
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **32 MCP tools** (24 read, 8 write), every one wrapped with the bundled
|
|
16
|
+
`@governed_tool` harness (audit, policy, token/runaway budget, undo,
|
|
17
|
+
risk-tiers):
|
|
18
|
+
- **System (read)** — `firmware_status`, `health_status`, `interface_status`,
|
|
19
|
+
`gateway_status`.
|
|
20
|
+
- **Rules (read)** — `list_rules`, `rule_detail`, `rule_stats` (hit
|
|
21
|
+
counts/evaluations), `rule_states`.
|
|
22
|
+
- **NAT (read)** — `nat_port_forwards`, `nat_outbound`, `nat_one_to_one`.
|
|
23
|
+
- **Aliases (read)** — `list_aliases`, `alias_entries`.
|
|
24
|
+
- **VPN (read)** — `wireguard_status`, `openvpn_sessions`, `ipsec_sas`.
|
|
25
|
+
- **DHCP (read)** — `dhcp_leases`, `dhcp_static_mappings`.
|
|
26
|
+
- **Diagnostics (read)** — `firewall_log`, `states_table`, `top_talkers`.
|
|
27
|
+
- **Flagship analyses (read)** — `gateway_health_rca`,
|
|
28
|
+
`rule_hit_and_shadow_analysis`, `blocked_traffic_rca` — transparent
|
|
29
|
+
heuristics that report their numbers, not a black-box verdict.
|
|
30
|
+
- **Writes** — `toggle_rule` (med, undo restores prior enabled),
|
|
31
|
+
`add_alias_entry` / `remove_alias_entry` (med, capture prior entries, invert),
|
|
32
|
+
`kill_states` (med), `restart_service` (med), `apply_changes` (**high**),
|
|
33
|
+
`reconfigure` (**high**), `reboot` (**high**, irreversible/audit-only). Every
|
|
34
|
+
write takes a `dry_run` preview; high-risk writes require an approver.
|
|
35
|
+
- **Platform abstraction** — a name-keyed platform registry maps each target's
|
|
36
|
+
`platform` (`opnsense` / `pfsense`) to its auth style + REST resource paths, so
|
|
37
|
+
the ops/CLI/MCP layers stay platform-neutral. OPNsense uses HTTP Basic
|
|
38
|
+
(key+secret); pfSense uses an `X-API-Key` header.
|
|
39
|
+
- **Encrypted secret store** — the OPNsense API secret or pfSense API key is
|
|
40
|
+
stored encrypted in `~/.firewall-aiops/secrets.enc` (Fernet + scrypt); never
|
|
41
|
+
plaintext on disk. Legacy `FIREWALL_<TARGET>_SECRET` env var honoured as a
|
|
42
|
+
fallback.
|
|
43
|
+
- **CLI** (`firewall-aiops`) — `init` platform-picking wizard, `overview`,
|
|
44
|
+
`rules list/show/toggle` (dry-run + double-confirm), `log`, `secret`
|
|
45
|
+
management, and a `doctor` connectivity check (firmware/version query on both
|
|
46
|
+
platforms).
|
|
47
|
+
|
|
48
|
+
### Known limitations
|
|
49
|
+
|
|
50
|
+
- Preview / mock-only: OPNsense and pfSense responses are mocked and need live
|
|
51
|
+
verification against a real firewall; the modelled REST paths especially.
|
|
52
|
+
- **Missing a capability? Open an issue or PR** — contributions welcome.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wei <zhouwei008@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: firewall-aiops
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Governed AI-ops for OPNsense + pfSense firewalls: rules, NAT, aliases, VPN, DHCP, diagnostics, flagship RCA analyses, and governed writes (rule toggle, alias entries, apply/reconfigure/reboot) with a built-in governance harness (audit, budget, undo, risk tiers)
|
|
5
|
+
Author-email: wei <zhouwei008@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: cryptography>=42.0
|
|
10
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
11
|
+
Requires-Dist: mcp[cli]<2.0,>=1.10
|
|
12
|
+
Requires-Dist: pyyaml<7.0,>=6.0
|
|
13
|
+
Requires-Dist: rich<16.0,>=13.0
|
|
14
|
+
Requires-Dist: typer<1.0,>=0.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
<!-- mcp-name: io.github.AIops-tools/firewall-aiops -->
|
|
18
|
+
|
|
19
|
+
# Firewall AIops (preview)
|
|
20
|
+
|
|
21
|
+
Governed, audited AI-ops for **OPNsense** and **pfSense** firewalls — for AI agents (via MCP) and humans (via CLI).
|
|
22
|
+
|
|
23
|
+
> **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the OPNsense project, Deciso, Netgate, or the pfSense project.** OPNsense, pfSense and Netgate are trademarks of their respective owners. MIT licensed.
|
|
24
|
+
|
|
25
|
+
firewall-aiops speaks to two firewall platforms behind one MCP server — **OPNsense**
|
|
26
|
+
(REST API under `/api/...`, API key+secret via HTTP Basic auth) and **pfSense**
|
|
27
|
+
(REST API v2 under `/api/v2/...` from the pfSense-pkg-RESTAPI package, API key via
|
|
28
|
+
an `X-API-Key` header) — with the **same tools working on both**. Each target in the
|
|
29
|
+
config names its own `platform`; a name-keyed platform registry selects the API shape
|
|
30
|
+
(auth + resource paths), so an agent never has to know which firewall it is talking to.
|
|
31
|
+
|
|
32
|
+
Every tool runs through a **built-in governance harness** (vendored, zero external
|
|
33
|
+
dependency): audit log, token/call budget with runaway circuit-breaker, graduated
|
|
34
|
+
risk-tier approval, undo-token recording, and prompt-injection sanitisation.
|
|
35
|
+
|
|
36
|
+
## Why this exists
|
|
37
|
+
|
|
38
|
+
- **One server, both firewalls** — OPNsense and pfSense in a mixed estate, spoken to
|
|
39
|
+
through identical tool names. Adding a third firewall later is a new platform
|
|
40
|
+
descriptor, not a rewrite.
|
|
41
|
+
- **Read the whole firewall** — firmware/health, interfaces & gateways, filter rules
|
|
42
|
+
(with hit counts and state table), NAT (port-forward / outbound / 1:1), aliases,
|
|
43
|
+
VPN (WireGuard / OpenVPN / IPsec), DHCP leases & reservations, and the firewall log.
|
|
44
|
+
- **Flagship RCA analyses** — transparent heuristics that show their numbers, never a
|
|
45
|
+
black-box verdict: `gateway_health_rca` (WAN loss/latency/down → cause + action),
|
|
46
|
+
`rule_hit_and_shadow_analysis` (never-hit + shadowed/redundant rules), and
|
|
47
|
+
`blocked_traffic_rca` (top blocked sources/ports → scan / brute-force / probe).
|
|
48
|
+
- **Governed writes** — toggle a rule, add/remove an alias entry (reversible,
|
|
49
|
+
undo-recorded from the fetched before-state), flush states, restart a service, and
|
|
50
|
+
the "make it live" commit (`apply_changes` / `reconfigure`) and `reboot` at
|
|
51
|
+
**risk=high** with a dry-run preview and an approver gate.
|
|
52
|
+
|
|
53
|
+
## Tool inventory (32 tools)
|
|
54
|
+
|
|
55
|
+
| Domain | Tools | # | Kind |
|
|
56
|
+
|--------|-------|:-:|------|
|
|
57
|
+
| **System** | `firmware_status`, `health_status`, `interface_status`, `gateway_status` | 4 | read |
|
|
58
|
+
| **Rules** | `list_rules`, `rule_detail`, `rule_stats`, `rule_states` | 4 | read |
|
|
59
|
+
| **NAT** | `nat_port_forwards`, `nat_outbound`, `nat_one_to_one` | 3 | read |
|
|
60
|
+
| **Aliases** | `list_aliases`, `alias_entries` | 2 | read |
|
|
61
|
+
| **VPN** | `wireguard_status`, `openvpn_sessions`, `ipsec_sas` | 3 | read |
|
|
62
|
+
| **DHCP** | `dhcp_leases`, `dhcp_static_mappings` | 2 | read |
|
|
63
|
+
| **Diagnostics** | `firewall_log`, `states_table`, `top_talkers` | 3 | read |
|
|
64
|
+
| **Flagship analyses** | `gateway_health_rca`, `rule_hit_and_shadow_analysis`, `blocked_traffic_rca` | 3 | read |
|
|
65
|
+
| **Writes** | `toggle_rule`, `add_alias_entry`, `remove_alias_entry`, `kill_states`, `restart_service` | 5 | write (**med**) |
|
|
66
|
+
| **Writes** | `apply_changes`, `reconfigure`, `reboot` | 3 | write (**high**) |
|
|
67
|
+
|
|
68
|
+
Reversible writes record an inverse **undo descriptor** built from the real fetched
|
|
69
|
+
before-state (`toggle_rule` restores the rule's prior enabled flag; alias add/remove
|
|
70
|
+
invert). `apply_changes` / `reconfigure` / `reboot` are high-risk with `dry_run` +
|
|
71
|
+
an approver requirement; `reboot` is irreversible (audit only).
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv tool install firewall-aiops # or: pipx install firewall-aiops
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
firewall-aiops init # wizard: pick platform (opnsense/pfsense) + store the secret (encrypted)
|
|
83
|
+
firewall-aiops doctor # verify config, secrets, and connectivity
|
|
84
|
+
firewall-aiops overview # one-shot: version + gateway/interface health + rule count
|
|
85
|
+
firewall-aiops rules list # list filter rules
|
|
86
|
+
firewall-aiops rules toggle <uuid> --disable # dry-run + double-confirm governed write
|
|
87
|
+
firewall-aiops log --action block -n 50 # recent blocked traffic
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Run the MCP server (stdio) for an agent:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
firewall-aiops mcp # or: firewall-aiops-mcp
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### MCP client config
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"mcpServers": {
|
|
101
|
+
"firewall-aiops": {
|
|
102
|
+
"command": "uvx",
|
|
103
|
+
"args": ["--from", "firewall-aiops", "firewall-aiops-mcp"],
|
|
104
|
+
"env": { "FIREWALL_AIOPS_MASTER_PASSWORD": "your-master-password" }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
`~/.firewall-aiops/config.yaml` (non-secret connection details only):
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
targets:
|
|
116
|
+
- name: fw1
|
|
117
|
+
platform: opnsense # opnsense | pfsense
|
|
118
|
+
host: 192.0.2.1
|
|
119
|
+
port: 443
|
|
120
|
+
username: <opnsense-api-key> # OPNsense API key (unused for pfSense)
|
|
121
|
+
verify_ssl: false # false for self-signed lab certs
|
|
122
|
+
- name: edge
|
|
123
|
+
platform: pfsense
|
|
124
|
+
host: 192.0.2.2
|
|
125
|
+
verify_ssl: false
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The **secret** — the OPNsense API *secret* (paired with the key for HTTP Basic auth)
|
|
129
|
+
or the pfSense **API key** — is stored **encrypted** in `~/.firewall-aiops/secrets.enc`
|
|
130
|
+
(Fernet + scrypt-derived key), never plaintext on disk. Set it with
|
|
131
|
+
`firewall-aiops secret set <target>` or the `init` wizard. The store is unlocked by a
|
|
132
|
+
master password from `FIREWALL_AIOPS_MASTER_PASSWORD` (non-interactive/MCP/CI) or an
|
|
133
|
+
interactive prompt (CLI on a TTY). A legacy plaintext env var
|
|
134
|
+
`FIREWALL_<TARGET>_SECRET` is honoured as a fallback (migrate with
|
|
135
|
+
`firewall-aiops secret migrate`).
|
|
136
|
+
|
|
137
|
+
## Governance
|
|
138
|
+
|
|
139
|
+
Every MCP tool is wrapped by `@governed_tool`:
|
|
140
|
+
|
|
141
|
+
- **Audit** — every call is logged to `~/.firewall-aiops/audit.db` (tool, params with
|
|
142
|
+
secrets redacted, status, duration, risk tier, approver, rationale).
|
|
143
|
+
- **Budget / runaway guard** — per-process token/call caps and a repeat-call circuit
|
|
144
|
+
breaker (`FIREWALL_MAX_TOOL_CALLS`, `FIREWALL_RUNAWAY_MAX`, …).
|
|
145
|
+
- **Graduated risk tiers** — high-risk writes (`apply_changes`, `reconfigure`,
|
|
146
|
+
`reboot`) require an approver: set `FIREWALL_AUDIT_APPROVED_BY` (and
|
|
147
|
+
`FIREWALL_AUDIT_RATIONALE`) before they will run.
|
|
148
|
+
- **Undo recording** — reversible writes record an inverse descriptor to
|
|
149
|
+
`~/.firewall-aiops/undo.db` from the fetched before-state (recording only; an
|
|
150
|
+
external orchestrator executes it).
|
|
151
|
+
- **Sanitisation** — all firewall-returned text is bounded + injection-sanitised
|
|
152
|
+
before it reaches the agent.
|
|
153
|
+
|
|
154
|
+
## Preview status
|
|
155
|
+
|
|
156
|
+
- **Platforms**: OPNsense (REST API) and pfSense (REST API v2, pfSense-pkg-RESTAPI).
|
|
157
|
+
- **Preview — mock-validated only. Not run against a live firewall.** All behaviour is
|
|
158
|
+
validated against mocked OPNsense/pfSense JSON responses; the concrete REST paths are
|
|
159
|
+
modelled from each project's public API and need live verification. Both platforms are
|
|
160
|
+
free and self-hostable (OPNsense is fully open-source; pfSense CE is free), so a home
|
|
161
|
+
lab is the easiest live check — `firewall-aiops doctor` (a firmware/version query on
|
|
162
|
+
both) is the fastest connectivity check.
|
|
163
|
+
- **Missing a capability?** Open an issue or PR at
|
|
164
|
+
[github.com/AIops-tools/Firewall-AIops](https://github.com/AIops-tools/Firewall-AIops)
|
|
165
|
+
— contributions and feedback welcome.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<!-- mcp-name: io.github.AIops-tools/firewall-aiops -->
|
|
2
|
+
|
|
3
|
+
# Firewall AIops (preview)
|
|
4
|
+
|
|
5
|
+
Governed, audited AI-ops for **OPNsense** and **pfSense** firewalls — for AI agents (via MCP) and humans (via CLI).
|
|
6
|
+
|
|
7
|
+
> **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by the OPNsense project, Deciso, Netgate, or the pfSense project.** OPNsense, pfSense and Netgate are trademarks of their respective owners. MIT licensed.
|
|
8
|
+
|
|
9
|
+
firewall-aiops speaks to two firewall platforms behind one MCP server — **OPNsense**
|
|
10
|
+
(REST API under `/api/...`, API key+secret via HTTP Basic auth) and **pfSense**
|
|
11
|
+
(REST API v2 under `/api/v2/...` from the pfSense-pkg-RESTAPI package, API key via
|
|
12
|
+
an `X-API-Key` header) — with the **same tools working on both**. Each target in the
|
|
13
|
+
config names its own `platform`; a name-keyed platform registry selects the API shape
|
|
14
|
+
(auth + resource paths), so an agent never has to know which firewall it is talking to.
|
|
15
|
+
|
|
16
|
+
Every tool runs through a **built-in governance harness** (vendored, zero external
|
|
17
|
+
dependency): audit log, token/call budget with runaway circuit-breaker, graduated
|
|
18
|
+
risk-tier approval, undo-token recording, and prompt-injection sanitisation.
|
|
19
|
+
|
|
20
|
+
## Why this exists
|
|
21
|
+
|
|
22
|
+
- **One server, both firewalls** — OPNsense and pfSense in a mixed estate, spoken to
|
|
23
|
+
through identical tool names. Adding a third firewall later is a new platform
|
|
24
|
+
descriptor, not a rewrite.
|
|
25
|
+
- **Read the whole firewall** — firmware/health, interfaces & gateways, filter rules
|
|
26
|
+
(with hit counts and state table), NAT (port-forward / outbound / 1:1), aliases,
|
|
27
|
+
VPN (WireGuard / OpenVPN / IPsec), DHCP leases & reservations, and the firewall log.
|
|
28
|
+
- **Flagship RCA analyses** — transparent heuristics that show their numbers, never a
|
|
29
|
+
black-box verdict: `gateway_health_rca` (WAN loss/latency/down → cause + action),
|
|
30
|
+
`rule_hit_and_shadow_analysis` (never-hit + shadowed/redundant rules), and
|
|
31
|
+
`blocked_traffic_rca` (top blocked sources/ports → scan / brute-force / probe).
|
|
32
|
+
- **Governed writes** — toggle a rule, add/remove an alias entry (reversible,
|
|
33
|
+
undo-recorded from the fetched before-state), flush states, restart a service, and
|
|
34
|
+
the "make it live" commit (`apply_changes` / `reconfigure`) and `reboot` at
|
|
35
|
+
**risk=high** with a dry-run preview and an approver gate.
|
|
36
|
+
|
|
37
|
+
## Tool inventory (32 tools)
|
|
38
|
+
|
|
39
|
+
| Domain | Tools | # | Kind |
|
|
40
|
+
|--------|-------|:-:|------|
|
|
41
|
+
| **System** | `firmware_status`, `health_status`, `interface_status`, `gateway_status` | 4 | read |
|
|
42
|
+
| **Rules** | `list_rules`, `rule_detail`, `rule_stats`, `rule_states` | 4 | read |
|
|
43
|
+
| **NAT** | `nat_port_forwards`, `nat_outbound`, `nat_one_to_one` | 3 | read |
|
|
44
|
+
| **Aliases** | `list_aliases`, `alias_entries` | 2 | read |
|
|
45
|
+
| **VPN** | `wireguard_status`, `openvpn_sessions`, `ipsec_sas` | 3 | read |
|
|
46
|
+
| **DHCP** | `dhcp_leases`, `dhcp_static_mappings` | 2 | read |
|
|
47
|
+
| **Diagnostics** | `firewall_log`, `states_table`, `top_talkers` | 3 | read |
|
|
48
|
+
| **Flagship analyses** | `gateway_health_rca`, `rule_hit_and_shadow_analysis`, `blocked_traffic_rca` | 3 | read |
|
|
49
|
+
| **Writes** | `toggle_rule`, `add_alias_entry`, `remove_alias_entry`, `kill_states`, `restart_service` | 5 | write (**med**) |
|
|
50
|
+
| **Writes** | `apply_changes`, `reconfigure`, `reboot` | 3 | write (**high**) |
|
|
51
|
+
|
|
52
|
+
Reversible writes record an inverse **undo descriptor** built from the real fetched
|
|
53
|
+
before-state (`toggle_rule` restores the rule's prior enabled flag; alias add/remove
|
|
54
|
+
invert). `apply_changes` / `reconfigure` / `reboot` are high-risk with `dry_run` +
|
|
55
|
+
an approver requirement; `reboot` is irreversible (audit only).
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv tool install firewall-aiops # or: pipx install firewall-aiops
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
firewall-aiops init # wizard: pick platform (opnsense/pfsense) + store the secret (encrypted)
|
|
67
|
+
firewall-aiops doctor # verify config, secrets, and connectivity
|
|
68
|
+
firewall-aiops overview # one-shot: version + gateway/interface health + rule count
|
|
69
|
+
firewall-aiops rules list # list filter rules
|
|
70
|
+
firewall-aiops rules toggle <uuid> --disable # dry-run + double-confirm governed write
|
|
71
|
+
firewall-aiops log --action block -n 50 # recent blocked traffic
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run the MCP server (stdio) for an agent:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
firewall-aiops mcp # or: firewall-aiops-mcp
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### MCP client config
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"firewall-aiops": {
|
|
86
|
+
"command": "uvx",
|
|
87
|
+
"args": ["--from", "firewall-aiops", "firewall-aiops-mcp"],
|
|
88
|
+
"env": { "FIREWALL_AIOPS_MASTER_PASSWORD": "your-master-password" }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Configuration
|
|
95
|
+
|
|
96
|
+
`~/.firewall-aiops/config.yaml` (non-secret connection details only):
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
targets:
|
|
100
|
+
- name: fw1
|
|
101
|
+
platform: opnsense # opnsense | pfsense
|
|
102
|
+
host: 192.0.2.1
|
|
103
|
+
port: 443
|
|
104
|
+
username: <opnsense-api-key> # OPNsense API key (unused for pfSense)
|
|
105
|
+
verify_ssl: false # false for self-signed lab certs
|
|
106
|
+
- name: edge
|
|
107
|
+
platform: pfsense
|
|
108
|
+
host: 192.0.2.2
|
|
109
|
+
verify_ssl: false
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The **secret** — the OPNsense API *secret* (paired with the key for HTTP Basic auth)
|
|
113
|
+
or the pfSense **API key** — is stored **encrypted** in `~/.firewall-aiops/secrets.enc`
|
|
114
|
+
(Fernet + scrypt-derived key), never plaintext on disk. Set it with
|
|
115
|
+
`firewall-aiops secret set <target>` or the `init` wizard. The store is unlocked by a
|
|
116
|
+
master password from `FIREWALL_AIOPS_MASTER_PASSWORD` (non-interactive/MCP/CI) or an
|
|
117
|
+
interactive prompt (CLI on a TTY). A legacy plaintext env var
|
|
118
|
+
`FIREWALL_<TARGET>_SECRET` is honoured as a fallback (migrate with
|
|
119
|
+
`firewall-aiops secret migrate`).
|
|
120
|
+
|
|
121
|
+
## Governance
|
|
122
|
+
|
|
123
|
+
Every MCP tool is wrapped by `@governed_tool`:
|
|
124
|
+
|
|
125
|
+
- **Audit** — every call is logged to `~/.firewall-aiops/audit.db` (tool, params with
|
|
126
|
+
secrets redacted, status, duration, risk tier, approver, rationale).
|
|
127
|
+
- **Budget / runaway guard** — per-process token/call caps and a repeat-call circuit
|
|
128
|
+
breaker (`FIREWALL_MAX_TOOL_CALLS`, `FIREWALL_RUNAWAY_MAX`, …).
|
|
129
|
+
- **Graduated risk tiers** — high-risk writes (`apply_changes`, `reconfigure`,
|
|
130
|
+
`reboot`) require an approver: set `FIREWALL_AUDIT_APPROVED_BY` (and
|
|
131
|
+
`FIREWALL_AUDIT_RATIONALE`) before they will run.
|
|
132
|
+
- **Undo recording** — reversible writes record an inverse descriptor to
|
|
133
|
+
`~/.firewall-aiops/undo.db` from the fetched before-state (recording only; an
|
|
134
|
+
external orchestrator executes it).
|
|
135
|
+
- **Sanitisation** — all firewall-returned text is bounded + injection-sanitised
|
|
136
|
+
before it reaches the agent.
|
|
137
|
+
|
|
138
|
+
## Preview status
|
|
139
|
+
|
|
140
|
+
- **Platforms**: OPNsense (REST API) and pfSense (REST API v2, pfSense-pkg-RESTAPI).
|
|
141
|
+
- **Preview — mock-validated only. Not run against a live firewall.** All behaviour is
|
|
142
|
+
validated against mocked OPNsense/pfSense JSON responses; the concrete REST paths are
|
|
143
|
+
modelled from each project's public API and need live verification. Both platforms are
|
|
144
|
+
free and self-hostable (OPNsense is fully open-source; pfSense CE is free), so a home
|
|
145
|
+
lab is the easiest live check — `firewall-aiops doctor` (a firmware/version query on
|
|
146
|
+
both) is the fastest connectivity check.
|
|
147
|
+
- **Missing a capability?** Open an issue or PR at
|
|
148
|
+
[github.com/AIops-tools/Firewall-AIops](https://github.com/AIops-tools/Firewall-AIops)
|
|
149
|
+
— contributions and feedback welcome.
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Firewall AIops v0.1.0 — preview
|
|
2
|
+
|
|
3
|
+
Governed AI-ops for **OPNsense** and **pfSense** firewalls for AI agents, with a
|
|
4
|
+
built-in governance harness (audit, policy, token/runaway budget, undo-token
|
|
5
|
+
recording, graduated risk tiers) and an encrypted credential store. Standalone —
|
|
6
|
+
no external skill-family dependency. One MCP server spans both platforms: a
|
|
7
|
+
per-target `platform` field selects the API shape, and the same 32 tools work on
|
|
8
|
+
OPNsense (REST `/api/...`, key+secret via HTTP Basic) and pfSense (REST v2
|
|
9
|
+
`/api/v2/...`, API key via `X-API-Key` header).
|
|
10
|
+
|
|
11
|
+
> **Not affiliated with, endorsed by, or sponsored by the OPNsense project,
|
|
12
|
+
> Deciso, Netgate, or the pfSense project.** OPNsense, pfSense and Netgate are
|
|
13
|
+
> trademarks of their respective owners.
|
|
14
|
+
|
|
15
|
+
> **Preview / mock-only.** All behaviour is validated against mocked
|
|
16
|
+
> OPNsense/pfSense JSON responses; it has **not** been run against a live
|
|
17
|
+
> firewall. The concrete REST paths are modelled from each project's public API
|
|
18
|
+
> and need live verification. Both platforms are free/self-hostable, so a home
|
|
19
|
+
> lab is the easiest live check — `firewall-aiops doctor` is the fastest.
|
|
20
|
+
|
|
21
|
+
## Highlights
|
|
22
|
+
|
|
23
|
+
- **32 MCP tools** (24 read, 8 write), every one wrapped with `@governed_tool`:
|
|
24
|
+
- **System** — `firmware_status`, `health_status`, `interface_status`,
|
|
25
|
+
`gateway_status`.
|
|
26
|
+
- **Rules** — `list_rules`, `rule_detail`, `rule_stats` (hit counts),
|
|
27
|
+
`rule_states`.
|
|
28
|
+
- **NAT** — `nat_port_forwards`, `nat_outbound`, `nat_one_to_one`.
|
|
29
|
+
- **Aliases** — `list_aliases`, `alias_entries`.
|
|
30
|
+
- **VPN** — `wireguard_status`, `openvpn_sessions`, `ipsec_sas`.
|
|
31
|
+
- **DHCP** — `dhcp_leases`, `dhcp_static_mappings`.
|
|
32
|
+
- **Diagnostics** — `firewall_log`, `states_table`, `top_talkers`.
|
|
33
|
+
- **Writes** — `toggle_rule`, `add_alias_entry`, `remove_alias_entry`,
|
|
34
|
+
`kill_states`, `restart_service` (med); `apply_changes`, `reconfigure`,
|
|
35
|
+
`reboot` (**high**).
|
|
36
|
+
- **Flagship analyses** (transparent heuristics that show their numbers):
|
|
37
|
+
- `gateway_health_rca` — rank gateways by loss + latency, flag down/degraded,
|
|
38
|
+
map each to a likely cause + recommended action.
|
|
39
|
+
- `rule_hit_and_shadow_analysis` — never-hit (0 evaluations) enabled rules,
|
|
40
|
+
plus rules shadowed by an earlier terminating rule or duplicating one.
|
|
41
|
+
- `blocked_traffic_rca` — noisiest blocked sources/ports classified as scan,
|
|
42
|
+
service brute-force/probe, or generic — with an action.
|
|
43
|
+
- **Governed writes** — reversible writes capture the **real fetched
|
|
44
|
+
before-state** and record an undo descriptor (`toggle_rule` restores the prior
|
|
45
|
+
enabled flag; alias add/remove invert). High-risk commits (`apply_changes` /
|
|
46
|
+
`reconfigure` / `reboot`) take a `dry_run` preview and require an approver;
|
|
47
|
+
`reboot` is irreversible.
|
|
48
|
+
- **Encrypted secret store** — the OPNsense API secret or pfSense API key lives
|
|
49
|
+
encrypted in `~/.firewall-aiops/secrets.enc` (Fernet + scrypt), never plaintext;
|
|
50
|
+
legacy `FIREWALL_<TARGET>_SECRET` env fallback.
|
|
51
|
+
- **CLI** with an `init` platform-picking wizard, `doctor`, `overview`,
|
|
52
|
+
`rules list/show/toggle`, `log`, and `secret` management.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv tool install firewall-aiops
|
|
58
|
+
firewall-aiops init # pick platform (opnsense/pfsense) + store the secret
|
|
59
|
+
firewall-aiops doctor
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Caveats
|
|
63
|
+
|
|
64
|
+
- Preview / mock-only: OPNsense and pfSense responses are mocked and need live
|
|
65
|
+
verification against a real firewall (the modelled REST paths especially).
|
|
66
|
+
- **Missing a capability? Open an issue or PR** — contributions and feedback
|
|
67
|
+
welcome.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Disclaimer
|
|
4
|
+
|
|
5
|
+
Community-maintained open-source project. **Not affiliated with, endorsed by, or
|
|
6
|
+
sponsored by the OPNsense project, Deciso, Netgate, or the pfSense project.**
|
|
7
|
+
Product and trademark names (OPNsense, pfSense, Netgate) belong to their owners.
|
|
8
|
+
Source is auditable under the MIT license.
|
|
9
|
+
|
|
10
|
+
## Reporting Vulnerabilities
|
|
11
|
+
|
|
12
|
+
Report privately via a GitHub Security Advisory on
|
|
13
|
+
[github.com/AIops-tools/Firewall-AIops](https://github.com/AIops-tools/Firewall-AIops/security/advisories)
|
|
14
|
+
or email zhouwei008@gmail.com. Please do not open public issues for security
|
|
15
|
+
reports.
|
|
16
|
+
|
|
17
|
+
## Security Design
|
|
18
|
+
|
|
19
|
+
### Credential Management
|
|
20
|
+
- Per-target secrets — the OPNsense API **secret** (paired with the API key for
|
|
21
|
+
HTTP Basic auth) or the pfSense **API key** — live **encrypted** in
|
|
22
|
+
`~/.firewall-aiops/secrets.enc` (Fernet/AES-128 + scrypt-derived key; chmod
|
|
23
|
+
600), never in `config.yaml` and never in source. The master password is never
|
|
24
|
+
stored — only a per-store random salt and the ciphertext are on disk.
|
|
25
|
+
- A legacy plaintext env var `FIREWALL_<TARGET_NAME_UPPER>_SECRET` is still
|
|
26
|
+
honoured as a fallback with a deprecation warning (migrate with
|
|
27
|
+
`firewall-aiops secret migrate`).
|
|
28
|
+
- The secret is held only in memory and never logged or echoed. It is presented
|
|
29
|
+
as HTTP Basic auth (OPNsense) or an `X-API-Key` header (pfSense) at request
|
|
30
|
+
time; the config file holds only platform, host, port, username, and TLS
|
|
31
|
+
settings.
|
|
32
|
+
|
|
33
|
+
### Governed Operations
|
|
34
|
+
Every MCP tool runs through the bundled `@governed_tool` harness
|
|
35
|
+
(`firewall_aiops.governance`):
|
|
36
|
+
- **Audit** — every call logged to a local SQLite DB under `~/.firewall-aiops/`
|
|
37
|
+
(relocatable via `FIREWALL_AIOPS_HOME`), agent-attributed, secret-redacted.
|
|
38
|
+
- **Token/runaway budget** — hard ceilings (`FIREWALL_MAX_TOOL_CALLS` /
|
|
39
|
+
`FIREWALL_MAX_TOOL_SECONDS`) plus an on-by-default guard that trips a tight
|
|
40
|
+
poll/retry loop, preventing unbounded API consumption.
|
|
41
|
+
- **Graduated risk tiers** — `~/.firewall-aiops/rules.yaml` `risk_tiers` gate
|
|
42
|
+
writes by environment/tag; the highest tiers require a recorded approver.
|
|
43
|
+
- **Undo-token recording** — reversible writes capture the BEFORE state (via a
|
|
44
|
+
real GET) and record an inverse descriptor (e.g. `toggle_rule` restores the
|
|
45
|
+
prior enabled flag; `add_alias_entry`→`remove_alias_entry`) so the change can
|
|
46
|
+
be rolled back.
|
|
47
|
+
|
|
48
|
+
### State-Changing Operations
|
|
49
|
+
The "make it live" commits — `apply_changes`, `reconfigure` — and `reboot` are
|
|
50
|
+
`risk_level=high`, accept a `dry_run` preview, and (under `risk_tiers`) require a
|
|
51
|
+
recorded approver (`FIREWALL_AUDIT_APPROVED_BY` + `FIREWALL_AUDIT_RATIONALE`).
|
|
52
|
+
`reboot` is irreversible (audit only, no undo). Rule toggle, alias entry
|
|
53
|
+
add/remove, `kill_states`, and `restart_service` are `risk_level=medium`;
|
|
54
|
+
reversible ones capture before-state and record an undo token.
|
|
55
|
+
|
|
56
|
+
### SSL/TLS Verification
|
|
57
|
+
`verify_ssl` defaults to true; disable only for self-signed lab certificates.
|
|
58
|
+
|
|
59
|
+
### Prompt-Injection Protection
|
|
60
|
+
All firewall-returned text (rule descriptions, alias entries, log lines, VPN peer
|
|
61
|
+
names, gateway names) is passed through a `sanitize()` truncate + control-character
|
|
62
|
+
strip before reaching the agent.
|
|
63
|
+
|
|
64
|
+
### Network Scope
|
|
65
|
+
No webhooks, no telemetry, no outbound calls beyond the configured OPNsense /
|
|
66
|
+
pfSense REST API endpoints. No post-install scripts or background services.
|
|
67
|
+
|
|
68
|
+
## Static Analysis
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uvx bandit -r firewall_aiops/ mcp_server/
|
|
72
|
+
uv run ruff check .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Supported Versions
|
|
76
|
+
|
|
77
|
+
The latest released version receives security fixes. This is a preview (0.x);
|
|
78
|
+
pin a version in production.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""firewall-aiops — governed OPNsense + pfSense firewall operations for AI agents.
|
|
2
|
+
|
|
3
|
+
Standalone and self-contained: the governance harness (audit, token budget,
|
|
4
|
+
undo-token recording, graduated risk tiers, prompt-injection sanitize) is
|
|
5
|
+
bundled under ``firewall_aiops.governance`` — this package has no external
|
|
6
|
+
skill-family dependency. Preview: not yet full-coverage.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.1.0"
|