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:
parent
f3cea01792
commit
d351ae515a
@ -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
|
||||
# =============================================================================
|
||||
|
||||
@ -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**
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
@ -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)")"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user