Add read-only Sentinel MCP server
This commit is contained in:
70
infra/mcp-server/README.md
Normal file
70
infra/mcp-server/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# OfficeCom Sentinel MCP
|
||||
|
||||
Dieser Container stellt sichere, **schreibgeschuetzte** Abfragen der OfficeCom-Sentinel-Daten fuer KI-Agenten bereit. Er nutzt das offizielle Python-MCP-SDK mit Streamable HTTP unter `/mcp`.
|
||||
|
||||
## Sicherheitsmodell
|
||||
|
||||
- Der Dienst wird im ersten Schritt nur auf `127.0.0.1:8091` des n8n-Hosts gebunden. Er wird nicht ueber `sentinel.officecom.biz` veroeffentlicht.
|
||||
- Jeder MCP-Aufruf verlangt einen eigenen Bearer-Token, prueft `Host` sowie vorhandene `Origin`-Header und wird ohne Aufrufparameter protokolliert.
|
||||
- Der PostgreSQL-Zugang ist ein dedizierter Login mit `default_transaction_read_only=on`, einem 5-Sekunden-Statement-Timeout und ausschliesslich `SELECT`-Rechten.
|
||||
- Die Werkzeuge haben feste, parametrisierte Abfragen und feste Ergebnisgrenzen. Es gibt kein Werkzeug fuer SQL, Schreiboperationen, Rohbeweise, Befehlszeilen oder Zugangsdaten.
|
||||
- Die Antwort auf `get_device_security` und `search_security_events` enthaelt standardmaessig keine Kontonamen. Konten werden nur auf ausdrueckliche Tool-Anforderung ergaenzt.
|
||||
|
||||
## Verfuegbare Tools
|
||||
|
||||
| Tool | Zweck |
|
||||
| --- | --- |
|
||||
| `security_overview` | Gesamtlage, Abdeckung und dringende Systeme |
|
||||
| `get_organization_status` | Status eines NinjaOne-Organisations-IDs |
|
||||
| `get_device_security` | Bereinigte Sicherheitslage eines Systems |
|
||||
| `search_security_events` | Zeitlich und mengenmaessig begrenzte Ereigniszusammenfassungen |
|
||||
| `get_network_paths` | Beobachtete Quell-IP-zu-System-Pfade |
|
||||
| `get_weekly_report` | Letzte woechentliche Kennzahlen ohne Bericht-HTML |
|
||||
|
||||
Zusaetzlich gibt es die Resource `ocsentinel://read-only-policy` und den Prompt `incident_triage`.
|
||||
|
||||
## Einmalig: Datenbankrolle anlegen
|
||||
|
||||
Auf dem PostgreSQL-Container als Datenbankadministrator ausfuehren. Das Passwort in diesem Befehl durch ein langes, zufaelliges Kennwort ersetzen und danach nur in der lokalen `.env` hinterlegen.
|
||||
|
||||
```sql
|
||||
CREATE ROLE ocsentinel_mcp LOGIN PASSWORD 'replace-with-a-long-random-password'
|
||||
NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;
|
||||
GRANT CONNECT ON DATABASE ocsentinel TO ocsentinel_mcp;
|
||||
GRANT USAGE ON SCHEMA ocsentinel TO ocsentinel_mcp;
|
||||
GRANT SELECT ON ocsentinel.device, ocsentinel.scan_report,
|
||||
ocsentinel.weekly_organization_report TO ocsentinel_mcp;
|
||||
GRANT SELECT ON ocsentinel.current_device_status,
|
||||
ocsentinel.organization_summary TO ocsentinel_mcp;
|
||||
```
|
||||
|
||||
Pruefung:
|
||||
|
||||
```sql
|
||||
SET ROLE ocsentinel_mcp;
|
||||
SELECT * FROM ocsentinel.organization_summary;
|
||||
INSERT INTO ocsentinel.device (machine_name, machine_name_key) VALUES ('must-fail', 'must-fail');
|
||||
```
|
||||
|
||||
Die letzte Anweisung muss scheitern.
|
||||
|
||||
## Dockge-Bereitstellung
|
||||
|
||||
1. Den Ordner `infra/mcp-server` als neuen Dockge-Stack auf dem n8n-Host ablegen.
|
||||
2. `.env.example` nach `.env` kopieren, Datenbankpasswort und einen zweiten langen Zufallstoken setzen.
|
||||
3. In `MCP_ALLOWED_HOSTS` nur die echten, erlaubten Host-Header lassen. Fuer den SSH-Tunnel sind `localhost:8091` und `127.0.0.1:8091` korrekt.
|
||||
4. Stack starten. Der Endpunkt ist lokal: `http://127.0.0.1:8091/mcp`.
|
||||
|
||||
Der Container hat keinen veroeffentlichten Zugriff auf das Internet. Fuer einen Arbeitsplatz wird ein Tunnel genutzt:
|
||||
|
||||
```powershell
|
||||
ssh -L 8091:127.0.0.1:8091 oc@172.16.41.197 -p 1022
|
||||
```
|
||||
|
||||
Danach ist der lokale MCP-Endpunkt `http://localhost:8091/mcp`. Der MCP-Client muss den Header `Authorization: Bearer <MCP_AUTH_TOKEN>` mitsenden.
|
||||
|
||||
## Betrieb
|
||||
|
||||
- Logs: `docker logs ocsentinel-mcp --tail 100`.
|
||||
- Niemals den Bearer-Token in einem Git-Repository, Screenshot oder Prompt speichern.
|
||||
- Fuer einen spaeteren externen Zugriff wird ein separater OAuth-geschuetzter Reverse Proxy benoetigt. Der aktuelle Token-Modus ist ausschliesslich fuer den privaten Tunnel und vertrauenswuerdige Agenten gedacht.
|
||||
Reference in New Issue
Block a user