cryptography build prevention + docs

Signed-off-by: GitHub <noreply@github.com>
This commit is contained in:
Jokob @NetAlertX
2025-12-07 11:33:20 +00:00
committed by GitHub
parent 5c44fd8fea
commit 1dee812ce6
10 changed files with 563 additions and 20 deletions

View File

@@ -26,16 +26,25 @@ ENV PATH="/opt/venv/bin:$PATH"
# Install build dependencies
COPY requirements.txt /tmp/requirements.txt
RUN apk add --no-cache bash shadow python3 python3-dev gcc musl-dev libffi-dev openssl-dev git rust cargo \
RUN apk add --no-cache \
bash \
shadow \
python3 \
python3-dev \
gcc \
musl-dev \
libffi-dev \
openssl-dev \
git \
rust \
cargo \
&& python -m venv /opt/venv
# Create virtual environment owned by root, but readable by everyone else. This makes it easy to copy
# into hardened stage without worrying about permissions and keeps image size small. Keeping the commands
# together makes for a slightly smaller image size.
# Upgrade pip/wheel/setuptools and install Python packages
RUN python -m pip install --upgrade pip setuptools wheel && \
pip install --no-cache-dir -r /tmp/requirements.txt && \
chmod -R u-rwx,g-rwx /opt
# second stage is the main runtime stage with just the minimum required to run the application
# The runner is used for both devcontainer, and as a base for the hardened stage.
FROM alpine:3.22 AS runner

View File

@@ -36,9 +36,15 @@ Authorization: Bearer <API_TOKEN>
If the token is missing or invalid, the server will return:
```json
{ "error": "Forbidden" }
{
"success": false,
"message": "ERROR: Not authorized",
"error": "Forbidden"
}
```
HTTP Status: **403 Forbidden**
---
## Base URL
@@ -54,6 +60,8 @@ http://<server>:<GRAPHQL_PORT>/
> [!TIP]
> When retrieving devices or settings try using the GraphQL API endpoint first as it is read-optimized.
### Standard REST Endpoints
* [Device API Endpoints](API_DEVICE.md) Manage individual devices
* [Devices Collection](API_DEVICES.md) Bulk operations on multiple devices
* [Events](API_EVENTS.md) Device event logging and management
@@ -69,6 +77,18 @@ http://<server>:<GRAPHQL_PORT>/
* [Logs](API_LOGS.md) Purging of logs and adding to the event execution queue for user triggered events
* [DB query](API_DBQUERY.md) (⚠ Internal) - Low level database access - use other endpoints if possible
### MCP Server Bridge
NetAlertX includes an **MCP (Model Context Protocol) Server Bridge** that provides AI assistants access to NetAlertX functionality through standardized tools. MCP endpoints are available at `/mcp/sse/*` paths and mirror the functionality of standard REST endpoints:
* `/mcp/sse` - Server-Sent Events endpoint for MCP client connections
* `/mcp/sse/openapi.json` - OpenAPI specification for available MCP tools
* `/mcp/sse/device/*`, `/mcp/sse/devices/*`, `/mcp/sse/nettools/*`, `/mcp/sse/events/*` - MCP-enabled versions of REST endpoints
MCP endpoints require the same Bearer token authentication as REST endpoints.
**📖 See [MCP Server Bridge API](API_MCP.md) for complete documentation, tool specifications, and integration examples.**
See [Testing](API_TESTS.md) for example requests and usage.
---

View File

@@ -2,7 +2,7 @@
The **Database Query API** provides direct, low-level access to the NetAlertX database. It allows **read, write, update, and delete** operations against tables, using **base64-encoded** SQL or structured parameters.
> [!Warning]
> [!Warning]
> This API is primarily used internally to generate and render the application UI. These endpoints are low-level and powerful, and should be used with caution. Wherever possible, prefer the [standard API endpoints](API.md). Invalid or unsafe queries can corrupt data.
> If you need data in a specific format that is not already provided, please open an issue or pull request with a clear, broadly useful use case. This helps ensure new endpoints benefit the wider community rather than relying on raw database queries.
@@ -16,10 +16,14 @@ All `/dbquery/*` endpoints require an API token in the HTTP headers:
Authorization: Bearer <API_TOKEN>
```
If the token is missing or invalid:
If the token is missing or invalid (HTTP 403):
```json
{ "error": "Forbidden" }
{
\"success\": false,
\"message\": \"ERROR: Not authorized\",
\"error\": \"Forbidden\"
}
```
---

View File

@@ -41,6 +41,8 @@ Manage a **single device** by its MAC address. Operations include retrieval, upd
* Device not found → HTTP 404
* Unauthorized → HTTP 403
**MCP Integration**: Available as `get_device_info` and `set_device_alias` tools. See [MCP Server Bridge API](API_MCP.md).
---
## 2. Update Device Fields

View File

@@ -170,7 +170,7 @@ The Devices Collection API provides operations to **retrieve, manage, import/exp
**Response**:
```json
[
[
120, // Total devices
85, // Connected
5, // Favorites
@@ -207,6 +207,93 @@ The Devices Collection API provides operations to **retrieve, manage, import/exp
---
### 9. Search Devices
* **POST** `/devices/search`
Search for devices by MAC, name, or IP address.
**Request Body** (JSON):
```json
{
"query": ".50"
}
```
**Response**:
```json
{
"success": true,
"devices": [
{
"devName": "Test Device",
"devMac": "AA:BB:CC:DD:EE:FF",
"devLastIP": "192.168.1.50"
}
]
}
```
---
### 10. Get Latest Device
* **GET** `/devices/latest`
Get the most recently connected device.
**Response**:
```json
[
{
"devName": "Latest Device",
"devMac": "AA:BB:CC:DD:EE:FF",
"devLastIP": "192.168.1.100",
"devFirstConnection": "2025-12-07 10:30:00"
}
]
```
---
### 11. Get Network Topology
* **GET** `/devices/network/topology`
Get network topology showing device relationships.
**Response**:
```json
{
"nodes": [
{
"id": "AA:AA:AA:AA:AA:AA",
"name": "Router",
"vendor": "VendorA"
}
],
"links": [
{
"source": "AA:AA:AA:AA:AA:AA",
"target": "BB:BB:BB:BB:BB:BB",
"port": "eth1"
}
]
}
```
---
## MCP Tools
These endpoints are also available as **MCP Tools** for AI assistant integration:
- `list_devices`, `search_devices`, `get_latest_device`, `get_network_topology`, `set_device_alias`
📖 See [MCP Server Bridge API](API_MCP.md) for AI integration details.
---
## Example `curl` Requests
**Get All Devices**:
@@ -247,3 +334,26 @@ curl -X GET "http://<server_ip>:<GRAPHQL_PORT>/devices/by-status?status=online"
-H "Authorization: Bearer <API_TOKEN>"
```
**Search Devices**:
```sh
curl -X POST "http://<server_ip>:<GRAPHQL_PORT>/devices/search" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
--data '{"query": "192.168.1"}'
```
**Get Latest Device**:
```sh
curl -X GET "http://<server_ip>:<GRAPHQL_PORT>/devices/latest" \
-H "Authorization: Bearer <API_TOKEN>"
```
**Get Network Topology**:
```sh
curl -X GET "http://<server_ip>:<GRAPHQL_PORT>/devices/network/topology" \
-H "Authorization: Bearer <API_TOKEN>"
```

View File

@@ -88,7 +88,56 @@ The Events API provides access to **device event logs**, allowing creation, retr
---
### 4. Event Totals Over a Period
### 4. Get Recent Events
* **GET** `/events/recent` → Get events from the last 24 hours
* **GET** `/events/<hours>` → Get events from the last N hours
**Response** (JSON):
```json
{
"success": true,
"hours": 24,
"count": 5,
"events": [
{
"eve_DateTime": "2025-12-07 12:00:00",
"eve_EventType": "New Device",
"eve_MAC": "AA:BB:CC:DD:EE:FF",
"eve_IP": "192.168.1.100",
"eve_AdditionalInfo": "Device detected"
}
]
}
```
---
### 5. Get Latest Events
* **GET** `/events/last`
Get the 10 most recent events.
**Response** (JSON):
```json
{
"success": true,
"count": 10,
"events": [
{
"eve_DateTime": "2025-12-07 12:00:00",
"eve_EventType": "Device Down",
"eve_MAC": "AA:BB:CC:DD:EE:FF"
}
]
}
```
---
### 6. Event Totals Over a Period
* **GET** `/sessions/totals?period=<period>`
Return event and session totals over a given period.
@@ -116,12 +165,25 @@ The Events API provides access to **device event logs**, allowing creation, retr
---
## MCP Tools
Event endpoints are available as **MCP Tools** for AI assistant integration:
- `get_recent_alerts`, `get_last_events`
📖 See [MCP Server Bridge API](API_MCP.md) for AI integration details.
---
## Notes
* All endpoints require **authorization** (Bearer token). Unauthorized requests return:
* All endpoints require **authorization** (Bearer token). Unauthorized requests return HTTP 403:
```json
{ "error": "Forbidden" }
{
"success": false,
"message": "ERROR: Not authorized",
"error": "Forbidden"
}
```
* Events are stored in the **Events table** with the following fields:

326
docs/API_MCP.md Normal file
View File

@@ -0,0 +1,326 @@
# MCP Server Bridge API
The **MCP (Model Context Protocol) Server Bridge** provides AI assistants with standardized access to NetAlertX functionality through tools and server-sent events. This enables AI systems to interact with your network monitoring data in real-time.
---
## Overview
The MCP Server Bridge exposes NetAlertX functionality as **MCP Tools** that AI assistants can call to:
- Search and retrieve device information
- Trigger network scans
- Get network topology and events
- Wake devices via Wake-on-LAN
- Access open port information
- Set device aliases
All MCP endpoints mirror the functionality of standard REST endpoints but are optimized for AI assistant integration.
---
## Authentication
MCP endpoints use the same **Bearer token authentication** as REST endpoints:
```http
Authorization: Bearer <API_TOKEN>
```
Unauthorized requests return HTTP 403:
```json
{
"success": false,
"message": "ERROR: Not authorized",
"error": "Forbidden"
}
```
---
## MCP Connection Endpoint
### Server-Sent Events (SSE)
* **GET/POST** `/mcp/sse`
Main MCP connection endpoint for AI clients. Establishes a persistent connection using Server-Sent Events for real-time communication between AI assistants and NetAlertX.
**Connection Example**:
```javascript
const eventSource = new EventSource('/mcp/sse', {
headers: {
'Authorization': 'Bearer <API_TOKEN>'
}
});
eventSource.onmessage = function(event) {
const response = JSON.parse(event.data);
console.log('MCP Response:', response);
};
```
---
## OpenAPI Specification
### Get MCP Tools Specification
* **GET** `/mcp/sse/openapi.json`
Returns the OpenAPI specification for all available MCP tools, describing the parameters and schemas for each tool.
**Response**:
```json
{
"openapi": "3.0.0",
"info": {
"title": "NetAlertX Tools",
"version": "1.1.0"
},
"servers": [{"url": "/"}],
"paths": {
"/devices/by-status": {
"post": {"operationId": "list_devices"}
},
"/device/{mac}": {
"post": {"operationId": "get_device_info"}
},
"/devices/search": {
"post": {"operationId": "search_devices"}
}
}
}
```
---
## Available MCP Tools
### Device Management Tools
| Tool | Endpoint | Description |
|------|----------|-------------|
| `list_devices` | `/mcp/sse/devices/by-status` | List devices by online status |
| `get_device_info` | `/mcp/sse/device/<mac>` | Get detailed device information |
| `search_devices` | `/mcp/sse/devices/search` | Search devices by MAC, name, or IP |
| `get_latest_device` | `/mcp/sse/devices/latest` | Get most recently connected device |
| `set_device_alias` | `/mcp/sse/device/<mac>/set-alias` | Set device friendly name |
### Network Tools
| Tool | Endpoint | Description |
|------|----------|-------------|
| `trigger_scan` | `/mcp/sse/nettools/trigger-scan` | Trigger network discovery scan |
| `get_open_ports` | `/mcp/sse/device/open_ports` | Get stored NMAP open ports for device |
| `wol_wake_device` | `/mcp/sse/nettools/wakeonlan` | Wake device using Wake-on-LAN |
| `get_network_topology` | `/mcp/sse/devices/network/topology` | Get network topology map |
### Event & Monitoring Tools
| Tool | Endpoint | Description |
|------|----------|-------------|
| `get_recent_alerts` | `/mcp/sse/events/recent` | Get events from last 24 hours |
| `get_last_events` | `/mcp/sse/events/last` | Get 10 most recent events |
---
## Tool Usage Examples
### Search Devices Tool
**Tool Call**:
```json
{
"jsonrpc": "2.0",
"id": "1",
"method": "tools/call",
"params": {
"name": "search_devices",
"arguments": {
"query": "192.168.1"
}
}
}
```
**Response**:
```json
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"content": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"devices\": [\n {\n \"devName\": \"Router\",\n \"devMac\": \"AA:BB:CC:DD:EE:FF\",\n \"devLastIP\": \"192.168.1.1\"\n }\n ]\n}"
}
],
"isError": false
}
}
```
### Trigger Network Scan Tool
**Tool Call**:
```json
{
"jsonrpc": "2.0",
"id": "2",
"method": "tools/call",
"params": {
"name": "trigger_scan",
"arguments": {
"type": "ARPSCAN"
}
}
}
```
**Response**:
```json
{
"jsonrpc": "2.0",
"id": "2",
"result": {
"content": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"message\": \"Scan triggered for type: ARPSCAN\"\n}"
}
],
"isError": false
}
}
```
### Wake-on-LAN Tool
**Tool Call**:
```json
{
"jsonrpc": "2.0",
"id": "3",
"method": "tools/call",
"params": {
"name": "wol_wake_device",
"arguments": {
"devMac": "AA:BB:CC:DD:EE:FF"
}
}
}
```
---
## Integration with AI Assistants
### Claude Desktop Integration
Add to your Claude Desktop `mcp.json` configuration:
```json
{
"mcp": {
"servers": {
"netalertx": {
"command": "node",
"args": ["/path/to/mcp-client.js"],
"env": {
"NETALERTX_URL": "http://your-server:<GRAPHQL_PORT>",
"NETALERTX_TOKEN": "your-api-token"
}
}
}
}
}
```
### Generic MCP Client
```python
import asyncio
import json
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
# Connect to NetAlertX MCP server
server_params = StdioServerParameters(
command="curl",
args=[
"-N", "-H", "Authorization: Bearer <API_TOKEN>",
"http://your-server:<GRAPHQL_PORT>/mcp/sse"
]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize connection
await session.initialize()
# List available tools
tools = await session.list_tools()
print(f"Available tools: {[t.name for t in tools.tools]}")
# Call a tool
result = await session.call_tool("search_devices", {"query": "router"})
print(f"Search result: {result}")
if __name__ == "__main__":
asyncio.run(main())
```
---
## Error Handling
MCP tool calls return structured error information:
**Error Response**:
```json
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"content": [
{
"type": "text",
"text": "Error calling tool: Device not found"
}
],
"isError": true
}
}
```
**Common Error Types**:
- `401/403` - Authentication failure
- `400` - Invalid parameters or missing required fields
- `404` - Resource not found (device, scan results, etc.)
- `500` - Internal server error
---
## Notes
* MCP endpoints require the same API token authentication as REST endpoints
* All MCP tools return JSON responses wrapped in MCP protocol format
* Server-Sent Events maintain persistent connections for real-time updates
* Tool parameters match their REST endpoint equivalents
* Error responses include both HTTP status codes and descriptive messages
* MCP bridge automatically handles request/response serialization
---
## Related Documentation
* [Main API Overview](API.md) - Core REST API documentation
* [Device API](API_DEVICE.md) - Individual device management
* [Devices Collection API](API_DEVICES.md) - Bulk device operations
* [Network Tools API](API_NETTOOLS.md) - Wake-on-LAN, scans, network utilities
* [Events API](API_EVENTS.md) - Event logging and monitoring

View File

@@ -241,3 +241,12 @@ curl -X POST "http://<server_ip>:<GRAPHQL_PORT>/nettools/nmap" \
curl "http://<server_ip>:<GRAPHQL_PORT>/nettools/internetinfo" \
-H "Authorization: Bearer <API_TOKEN>"
```
---
## MCP Tools
Network tools are available as **MCP Tools** for AI assistant integration:
- `wol_wake_device`, `trigger_scan`, `get_open_ports`
📖 See [MCP Server Bridge API](API_MCP.md) for AI integration details.

View File

@@ -98,6 +98,7 @@ nav:
- Sync: API_SYNC.md
- GraphQL: API_GRAPHQL.md
- DB query: API_DBQUERY.md
- MCP: API_MCP.md
- Tests: API_TESTS.md
- SUPERSEDED OLD API Overview: API_OLD.md
- Integrations:

View File

@@ -180,7 +180,7 @@ def graphql_endpoint():
if not is_authorized():
msg = '[graphql_server] Unauthorized access attempt - make sure your GRAPHQL_PORT and API_TOKEN settings are correct.'
mylog('verbose', [msg])
return jsonify({"success": False, "message": msg, "error": "Forbidden"}), 401
return jsonify({"success": False, "message": msg, "error": "Forbidden"}), 403
# Retrieve and log request data
data = request.get_json()
@@ -301,7 +301,7 @@ def api_device_set_alias(mac):
def api_device_open_ports():
"""Get stored NMAP open ports for a target IP or MAC."""
if not is_authorized():
return jsonify({"success": False, "error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
data = request.get_json(silent=True) or {}
target = data.get('target')
@@ -393,7 +393,7 @@ def api_devices_by_status():
def api_devices_search():
"""Device search: accepts 'query' in JSON and maps to device info/search."""
if not is_authorized():
return jsonify({"error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
data = request.get_json(silent=True) or {}
query = data.get('query')
@@ -424,7 +424,7 @@ def api_devices_search():
def api_devices_latest():
"""Get latest device (most recent) - maps to DeviceInstance.getLatest()."""
if not is_authorized():
return jsonify({"error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
device_handler = DeviceInstance()
@@ -440,7 +440,7 @@ def api_devices_latest():
def api_devices_network_topology():
"""Network topology mapping."""
if not is_authorized():
return jsonify({"error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
device_handler = DeviceInstance()
@@ -564,7 +564,7 @@ def api_trigger_scan():
@app.route('/mcp/sse/openapi.json', methods=['GET'])
def api_openapi_spec():
if not is_authorized():
return jsonify({"success": False, "error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
return openapi_spec()
@@ -786,7 +786,7 @@ def api_events_recent(hours):
"""Return events from the last <hours> hours using EventInstance."""
if not is_authorized():
return jsonify({"success": False, "error": "Unauthorized"}), 401
return jsonify({"success": False, "message": "ERROR: Not authorized", "error": "Forbidden"}), 403
# Validate hours input
if hours <= 0: