feat(ai): Integrate MCP server and threat-analyst with AI Gateway

Route AI requests through the AI Gateway for data sovereignty compliance.

Changes:
- secubox-mcp-server: ai.sh now prefers AI Gateway (port 4050), falls back to LocalAI
- secubox-threat-analyst: UCI config adds ai_gateway_url option
- threat-analyst CLI shows both Gateway and LocalAI status
- analyzer.sh and appliers.sh use ai_url (Gateway preferred)
- README updated with AI Gateway integration section

The AI Gateway ensures threat data (IPs, MACs, logs) is classified as
LOCAL_ONLY and never leaves the device, supporting ANSSI CSPN compliance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-28 17:59:20 +01:00
parent f3cea01792
commit d351ae515a
6 changed files with 78 additions and 16 deletions

View File

@ -1,19 +1,38 @@
# SecuBox MCP Tool: AI-Powered Security Analysis
# Uses LocalAI for threat analysis, CVE lookups, and filter suggestions
# Routes through AI Gateway for data classification and sovereignty compliance
# AI Gateway endpoint (handles classification, sanitization, provider routing)
AI_GATEWAY_API="http://127.0.0.1:4050/v1"
# Fallback to direct LocalAI if gateway unavailable
LOCALAI_API="http://127.0.0.1:8081/v1"
LOCALAI_MODEL="tinyllama-1.1b-chat-v1.0.Q4_K_M"
# Check if LocalAI is available
# Check if AI Gateway is available (preferred)
ai_gateway_available() {
wget -q -O /dev/null --timeout=2 "http://127.0.0.1:4050/health" 2>/dev/null
}
# Check if LocalAI is available (fallback)
localai_available() {
wget -q -O /dev/null --timeout=2 "${LOCALAI_API}/models" 2>/dev/null
}
# Call LocalAI for completion
localai_complete() {
# Call AI via Gateway (handles classification/sanitization) or direct LocalAI
ai_complete() {
local prompt="$1"
local max_tokens="${2:-512}"
# Determine API endpoint (Gateway preferred, LocalAI fallback)
local api_endpoint="$AI_GATEWAY_API"
if ! ai_gateway_available; then
if localai_available; then
api_endpoint="$LOCALAI_API"
else
return 1
fi
fi
local request=$(cat <<EOF
{"model":"$LOCALAI_MODEL","messages":[{"role":"system","content":"You are a cybersecurity analyst for SecuBox, an OpenWrt-based security appliance. Provide concise, actionable security analysis."},{"role":"user","content":"$prompt"}],"max_tokens":$max_tokens,"temperature":0.3}
EOF
@ -21,13 +40,18 @@ EOF
local response=$(echo "$request" | wget -q -O - --post-data=- \
--header="Content-Type: application/json" \
"${LOCALAI_API}/chat/completions" 2>/dev/null)
"${api_endpoint}/chat/completions" 2>/dev/null)
if [ -n "$response" ]; then
echo "$response" | jsonfilter -e '@.choices[0].message.content' 2>/dev/null
fi
}
# Backwards compatibility alias
localai_complete() {
ai_complete "$@"
}
# =============================================================================
# AI TOOLS
# =============================================================================

View File

@ -59,6 +59,10 @@ UCI config: `/etc/config/threat-analyst`
config threat-analyst 'main'
option enabled '1'
option interval '300' # Analysis interval (seconds)
# AI Gateway (preferred) - handles data classification & sovereignty
option ai_gateway_url 'http://127.0.0.1:4050'
# LocalAI (fallback) - direct connection if gateway unavailable
option localai_url 'http://127.0.0.1:8081'
option localai_model 'tinyllama-1.1b-chat-v1.0.Q4_K_M'
@ -71,6 +75,15 @@ config threat-analyst 'main'
option max_rules_per_cycle '5' # Max rules per cycle
```
## AI Gateway Integration
Threat Analyst routes AI requests through the AI Gateway for data sovereignty compliance:
1. **Gateway (preferred)**: Handles data classification and PII sanitization before routing to providers
2. **LocalAI (fallback)**: Direct on-device inference if gateway is unavailable
The AI Gateway ensures threat data (IPs, MACs, logs) stays LOCAL_ONLY and never leaves the device.
## LuCI Dashboard
Navigate to: **SecuBox → Security → Threat Analyst**

View File

@ -1,6 +1,9 @@
config threat-analyst 'main'
option enabled '1'
option interval '300'
# AI Gateway (preferred) - handles classification, sanitization, provider routing
option ai_gateway_url 'http://127.0.0.1:4050'
# LocalAI (fallback) - direct connection if gateway unavailable
option localai_url 'http://127.0.0.1:8081'
option localai_model 'tinyllama-1.1b-chat-v1.0.Q4_K_M'

View File

@ -48,6 +48,7 @@ uci_get() { uci -q get "${CONFIG}.$1"; }
load_config() {
enabled=$(uci_get main.enabled)
interval=$(uci_get main.interval)
ai_gateway_url=$(uci_get main.ai_gateway_url)
localai_url=$(uci_get main.localai_url)
localai_model=$(uci_get main.localai_model)
auto_apply_mitmproxy=$(uci_get main.auto_apply_mitmproxy)
@ -60,6 +61,16 @@ load_config() {
[ -z "$interval" ] && interval=300
[ -z "$min_confidence" ] && min_confidence=70
[ -z "$max_rules" ] && max_rules=5
[ -z "$ai_gateway_url" ] && ai_gateway_url="http://127.0.0.1:4050"
# Select AI endpoint (prefer Gateway, fallback to LocalAI)
if wget -q -O /dev/null --timeout=2 "${ai_gateway_url}/health" 2>/dev/null; then
ai_url="${ai_gateway_url}/v1"
ai_provider="gateway"
else
ai_url="${localai_url}/v1"
ai_provider="localai"
fi
mkdir -p "$STATE_DIR"
}
@ -74,17 +85,28 @@ cmd_status() {
echo ""
echo "Enabled: $([ "$enabled" = "1" ] && echo "Yes" || echo "No")"
echo "Interval: ${interval}s"
echo "LocalAI: $localai_url"
echo "Model: $localai_model"
echo ""
# Check LocalAI availability
# Check AI Gateway availability (preferred)
echo "AI Gateway: $ai_gateway_url"
if wget -q -O /dev/null --timeout=2 "${ai_gateway_url}/health" 2>/dev/null; then
echo "Gateway Status: ONLINE"
else
echo "Gateway Status: OFFLINE"
fi
# Check LocalAI availability (fallback)
echo "LocalAI: $localai_url"
if wget -q -O /dev/null --timeout=2 "${localai_url}/v1/models" 2>/dev/null; then
echo "LocalAI Status: ONLINE"
else
echo "LocalAI Status: OFFLINE"
fi
echo ""
echo "Active AI: $ai_provider ($ai_url)"
echo ""
echo "Auto-apply:"
echo " mitmproxy: $([ "$auto_apply_mitmproxy" = "1" ] && echo "Yes" || echo "No (queued)")"

View File

@ -1,5 +1,5 @@
# SecuBox Threat Analyst - Analyzer Module
# Collects and analyzes threats using LocalAI
# Collects and analyzes threats using AI Gateway (or LocalAI fallback)
# =============================================================================
# HELPER FUNCTIONS
@ -143,9 +143,9 @@ merge_json_arrays() {
analyze_threats() {
local threats="$1"
# Check LocalAI availability
if ! wget -q -O /dev/null --timeout=3 "${localai_url}/v1/models" 2>/dev/null; then
log_warn "LocalAI not available at $localai_url"
# Check AI availability (ai_url set by load_config: Gateway or LocalAI)
if ! wget -q -O /dev/null --timeout=3 "${ai_url}/models" 2>/dev/null; then
log_warn "AI not available at $ai_url"
return 1
fi
@ -176,7 +176,7 @@ Provide actionable, specific recommendations. Format filter patterns as code sni
local response=$(echo "$request" | wget -q -O - --post-data=- \
--header="Content-Type: application/json" \
"${localai_url}/v1/chat/completions" 2>/dev/null)
"${ai_url}/chat/completions" 2>/dev/null)
if [ -n "$response" ]; then
echo "$response" | jsonfilter -e '@.choices[0].message.content' 2>/dev/null

View File

@ -207,9 +207,9 @@ apply_all_pending() {
chat_query() {
local query="$1"
# Check LocalAI
if ! wget -q -O /dev/null --timeout=3 "${localai_url}/v1/models" 2>/dev/null; then
echo '{"error":"LocalAI not available"}'
# Check AI availability (ai_url set by load_config: Gateway or LocalAI)
if ! wget -q -O /dev/null --timeout=3 "${ai_url}/models" 2>/dev/null; then
echo '{"error":"AI not available"}'
return 1
fi
@ -232,7 +232,7 @@ EOF
local response=$(echo "$request" | wget -q -O - --post-data=- \
--header="Content-Type: application/json" \
"${localai_url}/v1/chat/completions" 2>/dev/null)
"${ai_url}/chat/completions" 2>/dev/null)
if [ -n "$response" ]; then
local content=$(echo "$response" | jsonfilter -e '@.choices[0].message.content' 2>/dev/null)