71 lines
3.6 KiB
Markdown
71 lines
3.6 KiB
Markdown
# 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.
|