network-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.
- network_aiops-0.1.0/.gitignore +22 -0
- network_aiops-0.1.0/LICENSE +21 -0
- network_aiops-0.1.0/PKG-INFO +150 -0
- network_aiops-0.1.0/README.md +133 -0
- network_aiops-0.1.0/RELEASE_NOTES.md +24 -0
- network_aiops-0.1.0/SECURITY.md +82 -0
- network_aiops-0.1.0/mcp_server/__init__.py +0 -0
- network_aiops-0.1.0/mcp_server/_shared.py +113 -0
- network_aiops-0.1.0/mcp_server/server.py +33 -0
- network_aiops-0.1.0/mcp_server/tools/__init__.py +0 -0
- network_aiops-0.1.0/mcp_server/tools/config_ops.py +107 -0
- network_aiops-0.1.0/mcp_server/tools/facts.py +87 -0
- network_aiops-0.1.0/mcp_server/tools/netbox.py +39 -0
- network_aiops-0.1.0/network_aiops/__init__.py +11 -0
- network_aiops-0.1.0/network_aiops/cli/__init__.py +9 -0
- network_aiops-0.1.0/network_aiops/cli/_common.py +84 -0
- network_aiops-0.1.0/network_aiops/cli/_root.py +50 -0
- network_aiops-0.1.0/network_aiops/cli/config.py +111 -0
- network_aiops-0.1.0/network_aiops/cli/device.py +86 -0
- network_aiops-0.1.0/network_aiops/cli/doctor.py +21 -0
- network_aiops-0.1.0/network_aiops/cli/netbox.py +39 -0
- network_aiops-0.1.0/network_aiops/config.py +159 -0
- network_aiops-0.1.0/network_aiops/connection.py +202 -0
- network_aiops-0.1.0/network_aiops/doctor.py +76 -0
- network_aiops-0.1.0/network_aiops/governance/__init__.py +40 -0
- network_aiops-0.1.0/network_aiops/governance/audit.py +377 -0
- network_aiops-0.1.0/network_aiops/governance/budget.py +225 -0
- network_aiops-0.1.0/network_aiops/governance/decorators.py +474 -0
- network_aiops-0.1.0/network_aiops/governance/paths.py +23 -0
- network_aiops-0.1.0/network_aiops/governance/patterns.py +378 -0
- network_aiops-0.1.0/network_aiops/governance/policy.py +411 -0
- network_aiops-0.1.0/network_aiops/governance/sanitize.py +39 -0
- network_aiops-0.1.0/network_aiops/governance/undo.py +218 -0
- network_aiops-0.1.0/network_aiops/ops/__init__.py +0 -0
- network_aiops-0.1.0/network_aiops/ops/_shared.py +38 -0
- network_aiops-0.1.0/network_aiops/ops/config_ops.py +135 -0
- network_aiops-0.1.0/network_aiops/ops/facts.py +130 -0
- network_aiops-0.1.0/network_aiops/ops/netbox_ops.py +50 -0
- network_aiops-0.1.0/pyproject.toml +60 -0
- network_aiops-0.1.0/server.json +21 -0
- network_aiops-0.1.0/skills/network-aiops/SKILL.md +189 -0
- network_aiops-0.1.0/skills/network-aiops/references/capabilities.md +61 -0
- network_aiops-0.1.0/skills/network-aiops/references/cli-reference.md +57 -0
- network_aiops-0.1.0/skills/network-aiops/references/setup-guide.md +112 -0
- network_aiops-0.1.0/tests/test_smoke.py +366 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
|
|
8
|
+
# Virtual envs / build
|
|
9
|
+
.venv/
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
|
|
13
|
+
# uv
|
|
14
|
+
uv.lock
|
|
15
|
+
|
|
16
|
+
# Local config / secrets (never commit)
|
|
17
|
+
*.env
|
|
18
|
+
.env
|
|
19
|
+
config.yaml
|
|
20
|
+
|
|
21
|
+
# OS
|
|
22
|
+
.DS_Store
|
|
@@ -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,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: network-aiops
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Governed multi-vendor network device operations for AI agents (NAPALM) 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: mcp[cli]<2.0,>=1.10
|
|
10
|
+
Requires-Dist: napalm<6,>=4.1
|
|
11
|
+
Requires-Dist: pynetbox<8,>=7
|
|
12
|
+
Requires-Dist: python-dotenv<2.0,>=1.0
|
|
13
|
+
Requires-Dist: pyyaml<7.0,>=6.0
|
|
14
|
+
Requires-Dist: rich<16.0,>=13.0
|
|
15
|
+
Requires-Dist: typer<1.0,>=0.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
<!-- mcp-name: io.github.AIops-tools/network-aiops -->
|
|
19
|
+
# network-aiops (preview)
|
|
20
|
+
|
|
21
|
+
> **Disclaimer**: This is a community-maintained open-source project and is **not
|
|
22
|
+
> affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox
|
|
23
|
+
> Labs, or any network vendor.** Vendor and product names are trademarks of their
|
|
24
|
+
> respective owners. Source code is publicly auditable at
|
|
25
|
+
> [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
|
|
26
|
+
> under the MIT license.
|
|
27
|
+
|
|
28
|
+
Governed multi-vendor network device operations for AI agents — **13 MCP tools**,
|
|
29
|
+
every one wrapped with the bundled `@governed_tool` harness: a local unified audit
|
|
30
|
+
log under `~/.network-aiops/`, policy engine, token/runaway budget guard,
|
|
31
|
+
undo-token recording, and graduated-autonomy risk tiers.
|
|
32
|
+
|
|
33
|
+
Devices are reached over [NAPALM](https://napalm.readthedocs.io/); an optional
|
|
34
|
+
NetBox block adds source-of-truth lookups.
|
|
35
|
+
|
|
36
|
+
> **Standalone**: the governance harness is bundled in the package
|
|
37
|
+
> (`network_aiops.governance`) — network-aiops has no external skill-family
|
|
38
|
+
> dependency. Preview: common device operations, not yet exhaustive.
|
|
39
|
+
|
|
40
|
+
## What works
|
|
41
|
+
|
|
42
|
+
Read device facts/interfaces/IP/BGP/LLDP/ARP, back up the running config, dry-run
|
|
43
|
+
a config diff, and merge/replace/rollback config — across the five core NAPALM
|
|
44
|
+
platforms below. Optional NetBox lookups confirm intended state before a change.
|
|
45
|
+
|
|
46
|
+
## Supported devices
|
|
47
|
+
|
|
48
|
+
| Platform | NAPALM driver | Transport |
|
|
49
|
+
|----------|---------------|-----------|
|
|
50
|
+
| Cisco IOS / IOS-XE | `ios` | SSH |
|
|
51
|
+
| Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |
|
|
52
|
+
| Cisco IOS-XR | `iosxr` | SSH (XML agent) |
|
|
53
|
+
| Arista EOS | `eos` | eAPI (HTTPS) |
|
|
54
|
+
| Juniper Junos | `junos` | NETCONF (SSH) |
|
|
55
|
+
|
|
56
|
+
Additional platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via
|
|
57
|
+
NAPALM **community drivers** but are **not officially tested here**. Need one?
|
|
58
|
+
See [Contributing](#contributing--feature-requests).
|
|
59
|
+
|
|
60
|
+
## Supported actions
|
|
61
|
+
|
|
62
|
+
| Action | Tool | R/W | Risk |
|
|
63
|
+
|--------|------|:---:|:----:|
|
|
64
|
+
| Device facts (hostname/vendor/model/OS/serial/uptime) | `device_facts` | R | low |
|
|
65
|
+
| Interfaces (up/down, speed, description) | `get_interfaces` | R | low |
|
|
66
|
+
| Interface IP addresses | `get_interfaces_ip` | R | low |
|
|
67
|
+
| BGP neighbors | `get_bgp_neighbors` | R | low |
|
|
68
|
+
| LLDP neighbors | `get_lldp_neighbors` | R | low |
|
|
69
|
+
| ARP table | `get_arp_table` | R | low |
|
|
70
|
+
| Back up running config | `config_backup` | R | low |
|
|
71
|
+
| Diff a candidate (dry-run) | `config_diff` | R | low |
|
|
72
|
+
| Merge config + commit | `config_merge` | W | medium |
|
|
73
|
+
| Replace full config + commit | `config_replace` | W | **high** |
|
|
74
|
+
| Roll back last commit | `config_rollback` | W | medium |
|
|
75
|
+
| NetBox list devices | `netbox_list_devices` | R | low |
|
|
76
|
+
| NetBox get device | `netbox_get_device` | R | low |
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
uv tool install network-aiops
|
|
82
|
+
network-aiops doctor
|
|
83
|
+
network-aiops device facts -t core-sw1
|
|
84
|
+
network-aiops config backup -t core-sw1 -o core-sw1.cfg
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Create `~/.network-aiops/config.yaml`:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
devices:
|
|
91
|
+
- name: core-sw1 # used as -t core-sw1
|
|
92
|
+
driver: eos # ios | nxos | nxos_ssh | iosxr | eos | junos
|
|
93
|
+
host: 10.0.0.1
|
|
94
|
+
username: admin
|
|
95
|
+
optional_args: # passed verbatim to NAPALM (optional)
|
|
96
|
+
secret: enable-pw # enable/secret
|
|
97
|
+
port: 443
|
|
98
|
+
# Optional source-of-truth:
|
|
99
|
+
netbox:
|
|
100
|
+
url: https://netbox.example.com
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Put secrets in `~/.network-aiops/.env` (chmod 600) — never in config.yaml:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
NETWORK_CORE_SW1_PASSWORD=... # NETWORK_<TARGET_UPPER>_PASSWORD
|
|
107
|
+
NETWORK_NETBOX_TOKEN=...
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## MCP
|
|
111
|
+
|
|
112
|
+
```jsonc
|
|
113
|
+
{
|
|
114
|
+
"command": "network-aiops",
|
|
115
|
+
"args": ["mcp"],
|
|
116
|
+
"env": { "NETWORK_AIOPS_CONFIG": "~/.network-aiops/config.yaml" }
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Audit & Safety
|
|
121
|
+
|
|
122
|
+
- Every tool call is logged to `~/.network-aiops/audit.db` (local SQLite;
|
|
123
|
+
relocate with `NETWORK_AIOPS_HOME`).
|
|
124
|
+
- `config_merge` / `config_replace` capture the pre-change running config and
|
|
125
|
+
record an inverse `config_replace`-to-backup undo descriptor.
|
|
126
|
+
- `config_replace` is `risk_level=high`; CLI destructive commands (`config
|
|
127
|
+
merge/replace/rollback`) require double confirmation and support `--dry-run`
|
|
128
|
+
(which prints the diff without committing).
|
|
129
|
+
- All device text passes through `sanitize()` (prompt-injection defense).
|
|
130
|
+
|
|
131
|
+
See `skills/network-aiops/SKILL.md` and `SECURITY.md` for details.
|
|
132
|
+
|
|
133
|
+
## Companion Skills
|
|
134
|
+
|
|
135
|
+
| If you want… | Use |
|
|
136
|
+
|--------------|-----|
|
|
137
|
+
| Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this) |
|
|
138
|
+
| Kubernetes cluster operations | a cluster ops skill |
|
|
139
|
+
| Hypervisor VM lifecycle | a hypervisor ops skill |
|
|
140
|
+
|
|
141
|
+
## Contributing & feature requests
|
|
142
|
+
|
|
143
|
+
This is a preview — coverage is intentionally focused. **Need a device or action
|
|
144
|
+
that isn't here yet?** Open an issue or pull request at
|
|
145
|
+
[github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)
|
|
146
|
+
— contributions, feature requests, and comments are all welcome.
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!-- mcp-name: io.github.AIops-tools/network-aiops -->
|
|
2
|
+
# network-aiops (preview)
|
|
3
|
+
|
|
4
|
+
> **Disclaimer**: This is a community-maintained open-source project and is **not
|
|
5
|
+
> affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox
|
|
6
|
+
> Labs, or any network vendor.** Vendor and product names are trademarks of their
|
|
7
|
+
> respective owners. Source code is publicly auditable at
|
|
8
|
+
> [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
|
|
9
|
+
> under the MIT license.
|
|
10
|
+
|
|
11
|
+
Governed multi-vendor network device operations for AI agents — **13 MCP tools**,
|
|
12
|
+
every one wrapped with the bundled `@governed_tool` harness: a local unified audit
|
|
13
|
+
log under `~/.network-aiops/`, policy engine, token/runaway budget guard,
|
|
14
|
+
undo-token recording, and graduated-autonomy risk tiers.
|
|
15
|
+
|
|
16
|
+
Devices are reached over [NAPALM](https://napalm.readthedocs.io/); an optional
|
|
17
|
+
NetBox block adds source-of-truth lookups.
|
|
18
|
+
|
|
19
|
+
> **Standalone**: the governance harness is bundled in the package
|
|
20
|
+
> (`network_aiops.governance`) — network-aiops has no external skill-family
|
|
21
|
+
> dependency. Preview: common device operations, not yet exhaustive.
|
|
22
|
+
|
|
23
|
+
## What works
|
|
24
|
+
|
|
25
|
+
Read device facts/interfaces/IP/BGP/LLDP/ARP, back up the running config, dry-run
|
|
26
|
+
a config diff, and merge/replace/rollback config — across the five core NAPALM
|
|
27
|
+
platforms below. Optional NetBox lookups confirm intended state before a change.
|
|
28
|
+
|
|
29
|
+
## Supported devices
|
|
30
|
+
|
|
31
|
+
| Platform | NAPALM driver | Transport |
|
|
32
|
+
|----------|---------------|-----------|
|
|
33
|
+
| Cisco IOS / IOS-XE | `ios` | SSH |
|
|
34
|
+
| Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |
|
|
35
|
+
| Cisco IOS-XR | `iosxr` | SSH (XML agent) |
|
|
36
|
+
| Arista EOS | `eos` | eAPI (HTTPS) |
|
|
37
|
+
| Juniper Junos | `junos` | NETCONF (SSH) |
|
|
38
|
+
|
|
39
|
+
Additional platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via
|
|
40
|
+
NAPALM **community drivers** but are **not officially tested here**. Need one?
|
|
41
|
+
See [Contributing](#contributing--feature-requests).
|
|
42
|
+
|
|
43
|
+
## Supported actions
|
|
44
|
+
|
|
45
|
+
| Action | Tool | R/W | Risk |
|
|
46
|
+
|--------|------|:---:|:----:|
|
|
47
|
+
| Device facts (hostname/vendor/model/OS/serial/uptime) | `device_facts` | R | low |
|
|
48
|
+
| Interfaces (up/down, speed, description) | `get_interfaces` | R | low |
|
|
49
|
+
| Interface IP addresses | `get_interfaces_ip` | R | low |
|
|
50
|
+
| BGP neighbors | `get_bgp_neighbors` | R | low |
|
|
51
|
+
| LLDP neighbors | `get_lldp_neighbors` | R | low |
|
|
52
|
+
| ARP table | `get_arp_table` | R | low |
|
|
53
|
+
| Back up running config | `config_backup` | R | low |
|
|
54
|
+
| Diff a candidate (dry-run) | `config_diff` | R | low |
|
|
55
|
+
| Merge config + commit | `config_merge` | W | medium |
|
|
56
|
+
| Replace full config + commit | `config_replace` | W | **high** |
|
|
57
|
+
| Roll back last commit | `config_rollback` | W | medium |
|
|
58
|
+
| NetBox list devices | `netbox_list_devices` | R | low |
|
|
59
|
+
| NetBox get device | `netbox_get_device` | R | low |
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv tool install network-aiops
|
|
65
|
+
network-aiops doctor
|
|
66
|
+
network-aiops device facts -t core-sw1
|
|
67
|
+
network-aiops config backup -t core-sw1 -o core-sw1.cfg
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Create `~/.network-aiops/config.yaml`:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
devices:
|
|
74
|
+
- name: core-sw1 # used as -t core-sw1
|
|
75
|
+
driver: eos # ios | nxos | nxos_ssh | iosxr | eos | junos
|
|
76
|
+
host: 10.0.0.1
|
|
77
|
+
username: admin
|
|
78
|
+
optional_args: # passed verbatim to NAPALM (optional)
|
|
79
|
+
secret: enable-pw # enable/secret
|
|
80
|
+
port: 443
|
|
81
|
+
# Optional source-of-truth:
|
|
82
|
+
netbox:
|
|
83
|
+
url: https://netbox.example.com
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Put secrets in `~/.network-aiops/.env` (chmod 600) — never in config.yaml:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
NETWORK_CORE_SW1_PASSWORD=... # NETWORK_<TARGET_UPPER>_PASSWORD
|
|
90
|
+
NETWORK_NETBOX_TOKEN=...
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## MCP
|
|
94
|
+
|
|
95
|
+
```jsonc
|
|
96
|
+
{
|
|
97
|
+
"command": "network-aiops",
|
|
98
|
+
"args": ["mcp"],
|
|
99
|
+
"env": { "NETWORK_AIOPS_CONFIG": "~/.network-aiops/config.yaml" }
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Audit & Safety
|
|
104
|
+
|
|
105
|
+
- Every tool call is logged to `~/.network-aiops/audit.db` (local SQLite;
|
|
106
|
+
relocate with `NETWORK_AIOPS_HOME`).
|
|
107
|
+
- `config_merge` / `config_replace` capture the pre-change running config and
|
|
108
|
+
record an inverse `config_replace`-to-backup undo descriptor.
|
|
109
|
+
- `config_replace` is `risk_level=high`; CLI destructive commands (`config
|
|
110
|
+
merge/replace/rollback`) require double confirmation and support `--dry-run`
|
|
111
|
+
(which prints the diff without committing).
|
|
112
|
+
- All device text passes through `sanitize()` (prompt-injection defense).
|
|
113
|
+
|
|
114
|
+
See `skills/network-aiops/SKILL.md` and `SECURITY.md` for details.
|
|
115
|
+
|
|
116
|
+
## Companion Skills
|
|
117
|
+
|
|
118
|
+
| If you want… | Use |
|
|
119
|
+
|--------------|-----|
|
|
120
|
+
| Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this) |
|
|
121
|
+
| Kubernetes cluster operations | a cluster ops skill |
|
|
122
|
+
| Hypervisor VM lifecycle | a hypervisor ops skill |
|
|
123
|
+
|
|
124
|
+
## Contributing & feature requests
|
|
125
|
+
|
|
126
|
+
This is a preview — coverage is intentionally focused. **Need a device or action
|
|
127
|
+
that isn't here yet?** Open an issue or pull request at
|
|
128
|
+
[github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)
|
|
129
|
+
— contributions, feature requests, and comments are all welcome.
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Release Notes
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (preview)
|
|
4
|
+
|
|
5
|
+
Initial preview release of **network-aiops** — governed multi-vendor network
|
|
6
|
+
device operations for AI agents.
|
|
7
|
+
|
|
8
|
+
- **13 MCP tools** (10 read / 3 write), every one wrapped with the bundled
|
|
9
|
+
`@governed_tool` harness (audit, policy, token/runaway budget, undo-token
|
|
10
|
+
recording, graduated risk tiers).
|
|
11
|
+
- Devices reached over **NAPALM**. Officially supported drivers: `ios`,
|
|
12
|
+
`nxos`, `nxos_ssh`, `iosxr`, `eos`, `junos`.
|
|
13
|
+
- Read getters: device facts, interfaces, interface IPs, BGP neighbors, LLDP
|
|
14
|
+
neighbors, ARP table, config backup, config diff (dry-run).
|
|
15
|
+
- Config writes: merge (medium), replace (high), rollback (medium). Merge and
|
|
16
|
+
replace capture the pre-change running config and record a `config_replace`
|
|
17
|
+
undo descriptor that restores it.
|
|
18
|
+
- Optional **NetBox** source-of-truth lookups (`netbox_list_devices`,
|
|
19
|
+
`netbox_get_device`); degrade gracefully when not configured.
|
|
20
|
+
- CLI: `device facts/interfaces/bgp/lldp/arp`, `config backup/diff/merge/replace/rollback`,
|
|
21
|
+
`netbox list/get`, `doctor`, `mcp`. Destructive config ops require double
|
|
22
|
+
confirmation and `--dry-run`.
|
|
23
|
+
- Standalone: governance harness bundled under `network_aiops.governance`; no
|
|
24
|
+
external skill-family dependency.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Disclaimer
|
|
4
|
+
|
|
5
|
+
This is a community-maintained open-source project and is **not affiliated with,
|
|
6
|
+
endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network
|
|
7
|
+
vendor.** Vendor and product names are trademarks of their respective owners.
|
|
8
|
+
Source code is publicly auditable at
|
|
9
|
+
[github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
|
|
10
|
+
under the MIT license.
|
|
11
|
+
|
|
12
|
+
## Reporting Vulnerabilities
|
|
13
|
+
|
|
14
|
+
Report security issues privately to **zhouwei008@gmail.com** or via a GitHub
|
|
15
|
+
private security advisory on the repository. Please do not open public issues for
|
|
16
|
+
undisclosed vulnerabilities.
|
|
17
|
+
|
|
18
|
+
## Security Design
|
|
19
|
+
|
|
20
|
+
### Credential Management
|
|
21
|
+
|
|
22
|
+
Device passwords are read from `~/.network-aiops/.env` as
|
|
23
|
+
`NETWORK_<TARGET_UPPER>_PASSWORD` (one per device); enable/secret and transport
|
|
24
|
+
options go in the device's `optional_args` and are passed verbatim to NAPALM. The
|
|
25
|
+
optional NetBox token is read from `NETWORK_NETBOX_TOKEN`. `config.yaml` holds
|
|
26
|
+
only device names, drivers, hosts, usernames, and `optional_args` — never
|
|
27
|
+
secrets. The state directory `~/.network-aiops` should be owner-only
|
|
28
|
+
(`chmod 700`) and `.env` `chmod 600`; the skill warns if the directory is more
|
|
29
|
+
permissive. Credentials are never read into results, logged, or echoed.
|
|
30
|
+
|
|
31
|
+
### Destructive Operation Safety
|
|
32
|
+
|
|
33
|
+
Config write operations (merge, replace, rollback) all pass through the bundled
|
|
34
|
+
`@governed_tool` decorator: policy pre-check, token / runaway budget guard,
|
|
35
|
+
graduated-autonomy risk-tier gate, and audit logging. The CLI layer additionally
|
|
36
|
+
requires double confirmation and supports `--dry-run` (which prints the diff
|
|
37
|
+
without committing) for `config merge`, `config replace`, and `config rollback`.
|
|
38
|
+
`config_merge` and `config_replace` capture the pre-change running config and
|
|
39
|
+
record an inverse `config_replace`-to-backup undo descriptor; `config_rollback`
|
|
40
|
+
declares no undo; `config_replace` is tagged `risk_level=high`. `config_diff` is a
|
|
41
|
+
pure dry-run (stage candidate → compare → discard).
|
|
42
|
+
|
|
43
|
+
### Least Privilege
|
|
44
|
+
|
|
45
|
+
Use a device account with only the privilege you need — a read-only login for
|
|
46
|
+
facts/backup, and a config-capable login only for the merge/replace/rollback
|
|
47
|
+
tools. The optional NetBox token should be read-only.
|
|
48
|
+
|
|
49
|
+
### Webhooks / Outbound Network
|
|
50
|
+
|
|
51
|
+
None. The skill makes no outbound network calls beyond the configured device
|
|
52
|
+
sessions (NAPALM) and the optional NetBox API. There are no background services
|
|
53
|
+
or post-install scripts.
|
|
54
|
+
|
|
55
|
+
### TLS Verification
|
|
56
|
+
|
|
57
|
+
NAPALM driver transports (eAPI / NX-API over HTTPS, NETCONF / SSH) follow each
|
|
58
|
+
device's own certificate and SSH host-key configuration. The skill does not
|
|
59
|
+
weaken transport security.
|
|
60
|
+
|
|
61
|
+
### Prompt Injection Protection
|
|
62
|
+
|
|
63
|
+
All text returned from a device (facts, configs, diffs, interface descriptions,
|
|
64
|
+
neighbor data) and from NetBox is run through `sanitize()` — truncation plus
|
|
65
|
+
C0/C1 control-character stripping — before reaching the agent.
|
|
66
|
+
|
|
67
|
+
### Transitive Dependencies
|
|
68
|
+
|
|
69
|
+
`napalm` (device drivers), `pynetbox` (optional source-of-truth), `typer`/`rich`
|
|
70
|
+
(CLI), `pyyaml`/`python-dotenv` (config), and the MCP SDK. No external
|
|
71
|
+
skill-family dependency — the governance harness is vendored under
|
|
72
|
+
`network_aiops.governance`.
|
|
73
|
+
|
|
74
|
+
## Static Analysis
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uvx bandit -r network_aiops/ mcp_server/
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Supported Versions
|
|
81
|
+
|
|
82
|
+
The latest released version (currently 0.1.0, preview) receives security fixes.
|
|
File without changes
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Shared MCP server primitives: the FastMCP instance, manager helper,
|
|
2
|
+
error sanitisation, and the ``@tool_errors`` decorator.
|
|
3
|
+
|
|
4
|
+
Tool modules under ``mcp_server/tools/`` import ``mcp`` from here and register
|
|
5
|
+
their ``@mcp.tool()`` functions onto it. ``mcp_server/server.py`` then imports
|
|
6
|
+
those modules and runs the server.
|
|
7
|
+
|
|
8
|
+
Keep ``Optional[X]`` (never PEP 604 ``X | None``) in any FastMCP-reflected
|
|
9
|
+
tool signature — on older mcp/pydantic the union eval'd to ``types.UnionType``
|
|
10
|
+
crashes FastMCP's ``issubclass`` check.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import functools
|
|
14
|
+
import logging
|
|
15
|
+
import os
|
|
16
|
+
from collections.abc import Callable
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any, Optional
|
|
19
|
+
|
|
20
|
+
from mcp.server.fastmcp import FastMCP
|
|
21
|
+
|
|
22
|
+
from network_aiops.config import load_config
|
|
23
|
+
from network_aiops.connection import ConnectionManager, NetworkApiError
|
|
24
|
+
from network_aiops.governance import sanitize
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
_DOCTOR_HINT = "Run 'network-aiops doctor' to verify device config and reachability."
|
|
29
|
+
|
|
30
|
+
_SUPPORTED = "ios, nxos, nxos_ssh, iosxr, eos, junos"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _safe_error(exc: Exception, tool: str) -> str:
|
|
34
|
+
"""Return an agent-safe error string; log full detail server-side only."""
|
|
35
|
+
logger.error("Tool %s failed", tool, exc_info=True)
|
|
36
|
+
_passthrough = (
|
|
37
|
+
ValueError,
|
|
38
|
+
FileNotFoundError,
|
|
39
|
+
KeyError,
|
|
40
|
+
PermissionError,
|
|
41
|
+
TimeoutError,
|
|
42
|
+
ConnectionError,
|
|
43
|
+
NetworkApiError,
|
|
44
|
+
)
|
|
45
|
+
if isinstance(exc, _passthrough):
|
|
46
|
+
return sanitize(str(exc), 300)
|
|
47
|
+
return f"{type(exc).__name__}: operation failed."
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def tool_errors(shape: str = "dict") -> Callable:
|
|
51
|
+
"""Wrap a tool body in the canonical try/except → ``_safe_error`` pattern.
|
|
52
|
+
|
|
53
|
+
Place this *between* ``@governed_tool`` and the function so the audit
|
|
54
|
+
decorator and FastMCP still see the original signature.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def decorator(func: Callable) -> Callable:
|
|
58
|
+
name = func.__name__
|
|
59
|
+
|
|
60
|
+
@functools.wraps(func)
|
|
61
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
62
|
+
try:
|
|
63
|
+
return func(*args, **kwargs)
|
|
64
|
+
except Exception as e: # noqa: BLE001 — sanitised below
|
|
65
|
+
msg = _safe_error(e, name)
|
|
66
|
+
if shape == "list":
|
|
67
|
+
return [{"error": msg, "hint": _DOCTOR_HINT}]
|
|
68
|
+
if shape == "str":
|
|
69
|
+
return f"Error: {msg} {_DOCTOR_HINT}"
|
|
70
|
+
return {"error": msg, "hint": _DOCTOR_HINT}
|
|
71
|
+
|
|
72
|
+
return wrapper
|
|
73
|
+
|
|
74
|
+
return decorator
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
mcp = FastMCP(
|
|
78
|
+
"network-aiops",
|
|
79
|
+
instructions=(
|
|
80
|
+
"Governed multi-vendor network device operations (preview) over NAPALM. "
|
|
81
|
+
f"Officially supported drivers: {_SUPPORTED} (Cisco IOS/IOS-XE, Nexus "
|
|
82
|
+
"NX-OS, IOS-XR, Arista EOS, Juniper Junos). Read tools: device facts, "
|
|
83
|
+
"interfaces, IP addresses, BGP/LLDP neighbors, ARP table, config backup, "
|
|
84
|
+
"and config diff (dry-run). Write tools: config merge, config replace, "
|
|
85
|
+
"config rollback. An optional NetBox block adds source-of-truth device "
|
|
86
|
+
"lookups. A 'target' selects a device from config. Every tool runs "
|
|
87
|
+
"through the network-aiops governance harness (audit / budget / risk-tier "
|
|
88
|
+
"/ undo). Need another platform (Nokia SR OS, Huawei VRP) or action? "
|
|
89
|
+
"Request it via a GitHub issue or PR."
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
_conn_mgr: Optional[ConnectionManager] = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _manager() -> ConnectionManager:
|
|
97
|
+
"""Return the connection manager, lazily initialising it from config."""
|
|
98
|
+
global _conn_mgr # noqa: PLW0603
|
|
99
|
+
if _conn_mgr is None:
|
|
100
|
+
config_path_str = os.environ.get("NETWORK_AIOPS_CONFIG")
|
|
101
|
+
config_path = Path(config_path_str) if config_path_str else None
|
|
102
|
+
_conn_mgr = ConnectionManager(load_config(config_path))
|
|
103
|
+
return _conn_mgr
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _target(name: Optional[str] = None) -> Any:
|
|
107
|
+
"""Resolve a device target by name (or the default device)."""
|
|
108
|
+
return _manager().target(name)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _netbox() -> Any:
|
|
112
|
+
"""Return a NetBox client (raises a teaching NetworkApiError if unconfigured)."""
|
|
113
|
+
return _manager().netbox()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""MCP server wrapping network-aiops operations (stdio transport).
|
|
2
|
+
|
|
3
|
+
Thin adapter layer: each ``@mcp.tool()`` function (in ``mcp_server/tools/``)
|
|
4
|
+
delegates to the ``network_aiops`` ops package and is wrapped with the
|
|
5
|
+
network-aiops ``@governed_tool`` harness (audit / budget / undo / risk-tier).
|
|
6
|
+
|
|
7
|
+
Standalone, self-governed network device operations (preview) over NAPALM —
|
|
8
|
+
Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, Juniper Junos, plus optional
|
|
9
|
+
NetBox source-of-truth.
|
|
10
|
+
|
|
11
|
+
Source: https://github.com/AIops-tools/Network-AIops
|
|
12
|
+
License: MIT
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
from mcp_server._shared import _safe_error, mcp, tool_errors
|
|
18
|
+
|
|
19
|
+
# Importing the tool modules registers every @mcp.tool() onto the shared
|
|
20
|
+
# `mcp` instance. Order does not matter; each module is self-contained.
|
|
21
|
+
from mcp_server.tools import ( # noqa: F401 — side effects
|
|
22
|
+
config_ops,
|
|
23
|
+
facts,
|
|
24
|
+
netbox,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = ["mcp", "main", "_safe_error", "tool_errors"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def main() -> None:
|
|
31
|
+
"""Run the MCP server over stdio."""
|
|
32
|
+
logging.basicConfig(level=logging.INFO)
|
|
33
|
+
mcp.run(transport="stdio")
|
|
File without changes
|