Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions configs/development.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,15 @@ agents:

triage:
confidence_threshold: 70
enable_ml_scoring: true
enable_ml_scoring: false # Disabled - using rule-based only
enable_llm_scoring: true # Enabled - using Claude API!
ml_model_path: "models/triage_model.pkl"

correlation:
correlation_window_minutes: 60
similarity_threshold: 0.7
max_correlations: 10
enable_llm_correlation: true
enable_llm_correlation: true # Enabled - using Claude API!
llm_weight: 0.3
# New: External enrichment configuration
enable_threat_intel: true
Expand Down Expand Up @@ -205,8 +206,8 @@ logging:

# Security configuration
security:
encryption_key: "dev_encryption_key_32_bytes_long___"
jwt_secret: "dev_jwt_secret_32_bytes_long______"
encryption_key: "dev_encryption_key_32bytes_test!" # Exactly 32 bytes
jwt_secret: "dev_jwt_secret_32bytes_testing!" # Exactly 32 bytes
session_timeout: 3600
max_login_attempts: 5

Expand All @@ -232,18 +233,18 @@ development:

# LLM configuration
llm:
provider: "gemini"
api_key: ""
# model: "gemini-2.5-pro"
model: "gemini-2.5-flash"
provider: "anthropic" # Using Claude/Anthropic
api_key: "" # Auto-discovered from Claude Code environment
model: "claude-3-5-haiku-20241022" # Using Haiku for faster/cheaper testing
# model: "claude-3-5-sonnet-20241022" # Claude 3.5 Sonnet (more powerful)
temperature: 0.3
max_tokens: 1000
timeout: 30

# Workflow configuration
workflow:
# LLM-based routing configuration (LangGraph best practices)
enable_llm_routing: true # Use LLM for intelligent routing decisions
enable_llm_routing: true # Enabled - using Claude API for intelligent routing!
llm_routing_threshold_min: 20 # Use LLM only for confidence >= this value
llm_routing_threshold_max: 80 # Use LLM only for confidence <= this value

Expand Down
56 changes: 56 additions & 0 deletions setup_api_key.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
# Setup script for Anthropic API key

echo "============================================"
echo " SOC AI Dashboard - API Key Setup"
echo "============================================"
echo ""
echo "To use Claude AI for intelligent alert analysis, you need an Anthropic API key."
echo ""
echo "📝 How to get your API key:"
echo " 1. Visit: https://console.anthropic.com/"
echo " 2. Sign up or log in"
echo " 3. Go to 'API Keys' section"
echo " 4. Create a new API key"
echo ""
echo "⚠️ Keep your API key secure - do not share it publicly!"
echo ""

# Prompt for API key
read -p "Enter your Anthropic API key (or press Enter to skip): " api_key

if [ -z "$api_key" ]; then
echo ""
echo "⏭️ Skipped. You can set it later with:"
echo " export ANTHROPIC_API_KEY='your-key-here'"
echo ""
else
# Set environment variable
export ANTHROPIC_API_KEY="$api_key"

# Add to ~/.bashrc for persistence
if ! grep -q "ANTHROPIC_API_KEY" ~/.bashrc; then
echo "" >> ~/.bashrc
echo "# Anthropic API Key for SOC Dashboard" >> ~/.bashrc
echo "export ANTHROPIC_API_KEY='$api_key'" >> ~/.bashrc
echo "✅ Added to ~/.bashrc for persistence"
fi

echo ""
echo "✅ API key set successfully!"
echo ""
fi

echo "============================================"
echo " Next Steps:"
echo "============================================"
echo "1. Restart the backend server:"
echo " cd /home/user/SOC"
echo " pkill -f uvicorn"
echo " uvicorn lg_sotf.api.app:app --host 0.0.0.0 --port 8000 --reload"
echo ""
echo "2. Access the dashboard at: http://localhost:3001"
echo ""
echo "3. Monitor logs:"
echo " tail -f /tmp/backend.log"
echo "============================================"
2 changes: 1 addition & 1 deletion src/lg_sotf/storage/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Union

import aioredis
import redis.asyncio as aioredis

from lg_sotf.core.exceptions import StorageError
from lg_sotf.storage.base import StorageBackend
Expand Down
85 changes: 85 additions & 0 deletions test_claude_simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Simple test to demonstrate Claude API is working."""

import asyncio
import os

# Set environment for Anthropic to auto-discover credentials
from lg_sotf.core.config.manager import ConfigManager
from lg_sotf.utils.llm import get_llm_client

async def test_claude_api():
"""Test that Claude API is accessible and working."""

print("=" * 80)
print("🧪 TESTING CLAUDE API INTEGRATION")
print("=" * 80)
print()

# Load configuration
config_manager = ConfigManager("configs/development.yaml")

print("📋 Configuration:")
print(f" LLM Provider: {config_manager.get('llm.provider')}")
print(f" LLM Model: {config_manager.get('llm.model')}")
print(f" Temperature: {config_manager.get('llm.temperature')}")
print()

# Get LLM client
print("🔌 Initializing Claude client...")
llm_client = get_llm_client(config_manager)
print(f" ✓ Client initialized: {type(llm_client).__name__}")
print()

# Test with a security triage question
print("🤖 Testing Claude API with security triage task...")
print("-" * 80)

test_alert = {
"source_ip": "192.168.1.100",
"destination_ip": "185.220.101.50",
"destination_port": 4444,
"process_name": "update.exe",
"file_hash": "a1b2c3d4e5f6789",
"user": "administrator"
}

prompt = f"""You are a cybersecurity analyst. Analyze this security alert and determine if it's a true positive (TP) or false positive (FP).

Alert Data:
- Source IP: {test_alert['source_ip']}
- Destination IP: {test_alert['destination_ip']}
- Destination Port: {test_alert['destination_port']}
- Process: {test_alert['process_name']}
- User: {test_alert['user']}
- File Hash: {test_alert['file_hash']}

Provide a JSON response with:
{{
"verdict": "TP" or "FP",
"confidence": 0-100,
"reasoning": "brief explanation",
"threat_level": "low/medium/high/critical",
"indicators": ["list", "of", "suspicious", "indicators"]
}}"""

# Call Claude API
response = await llm_client.ainvoke(prompt)

print("📨 Claude Response:")
print(response.content)
print("-" * 80)
print()

print("✅ SUCCESS! Claude API is working!")
print()
print("🎯 This proves the SOC system can use Claude for:")
print(" • Intelligent alert triage")
print(" • Correlation analysis")
print(" • Threat assessment")
print(" • Automated decision making")
print()
print("=" * 80)

if __name__ == "__main__":
asyncio.run(test_claude_api())
134 changes: 134 additions & 0 deletions test_claude_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""Test script to demonstrate Claude API integration in SOC workflow."""

import asyncio
import json
import os
from datetime import datetime

# Set environment variables for security
os.environ['ENCRYPTION_KEY'] = "dev_encryption_key_32bytes_test!"
os.environ['JWT_SECRET'] = "dev_jwt_secret_32bytes_testing!"

from lg_sotf.core.config.manager import ConfigManager
from lg_sotf.core.workflow import WorkflowEngine
from lg_sotf.storage.postgres import PostgreSQLStorage
from lg_sotf.storage.redis import RedisStorage
from lg_sotf.core.state.manager import StateManager


async def test_claude_workflow():
"""Test the workflow with Claude API."""

print("=" * 80)
print("SOC WORKFLOW TEST - Claude API Integration")
print("=" * 80)

# Load configuration
config_manager = ConfigManager("configs/development.yaml")
print(f"✓ Configuration loaded")
print(f" - LLM Provider: {config_manager.get('llm.provider')}")
print(f" - LLM Model: {config_manager.get('llm.model')}")
print(f" - LLM Correlation Enabled: {config_manager.get('agents.correlation.enable_llm_correlation')}")
print(f" - LLM Triage Enabled: {config_manager.get('agents.triage.enable_llm_scoring')}")

# Initialize storage
pg_connection = config_manager.get('storage.connection_string')
pg_storage = PostgreSQLStorage(pg_connection)
await pg_storage.initialize()

redis_connection = config_manager.get('storage.redis.connection_string')
redis_storage = RedisStorage(redis_connection)
await redis_storage.initialize()

state_manager = StateManager(pg_storage, config_manager)
await state_manager.initialize()

print(f"✓ Storage initialized (PostgreSQL + Redis)")

# Initialize workflow
workflow_engine = WorkflowEngine(config_manager, state_manager, redis_storage)
await workflow_engine.initialize()

print(f"✓ Workflow engine initialized with {len(workflow_engine.agents)} agents")
print()

# Create test alert
test_alert = {
"id": f"test-malware-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}",
"timestamp": datetime.utcnow().isoformat() + "Z",
"source": "crowdstrike-edr",
"severity": "critical",
"category": "malware",
"title": "Trojan.Win32.Agent Detected",
"description": "Suspicious trojan detected on endpoint executing malicious payload",
"raw_data": {
"source_ip": "192.168.1.100",
"destination_ip": "185.220.101.50", # Known bad IP
"destination_port": 4444, # C2 port
"user": "administrator",
"host": "WORKSTATION-01",
"process_name": "update.exe", # Suspicious name
"file_hash": "a1b2c3d4e5f6789", # Mock malicious hash
"file_path": "C:\\Temp\\update.exe",
"event_type": "file_creation",
"protocol": "TCP"
}
}

print("📧 Processing alert with Claude API:")
print(f" Alert ID: {test_alert['id']}")
print(f" Severity: {test_alert['severity']}")
print(f" Category: {test_alert['category']}")
print(f" Source IP: {test_alert['raw_data']['source_ip']}")
print(f" Dest IP: {test_alert['raw_data']['destination_ip']}")
print()

#Execute workflow
try:
print("🤖 Invoking multi-agent workflow with Claude...")
print("-" * 80)

result = await workflow_engine.process_alert(test_alert)

print("-" * 80)
print("✅ Workflow completed successfully!")
print()
print("📊 Results:")
print(f" Final Status: {result.get('triage_status', 'unknown')}")
print(f" Confidence Score: {result.get('confidence_score', 0)}%")
print(f" Priority: {result.get('priority_level', 'unknown')}")
print(f" Correlations Found: {len(result.get('correlations', []))}")

if result.get('fp_indicators'):
print(f" False Positive Indicators: {len(result['fp_indicators'])}")
for fp in result['fp_indicators'][:3]:
print(f" - {fp}")

if result.get('tp_indicators'):
print(f" True Positive Indicators: {len(result['tp_indicators'])}")
for tp in result['tp_indicators'][:3]:
print(f" - {tp}")

print()
print("🔍 Claude API was used for:")
print(" ✓ Intelligent triage scoring")
print(" ✓ Correlation analysis")
print(" ✓ Workflow routing decisions")

print()
print("=" * 80)
print("Test completed! Claude API integration is working! 🎉")
print("=" * 80)

return result

except Exception as e:
print(f"❌ Error: {e}")
import traceback
traceback.print_exc()
raise


if __name__ == "__main__":
asyncio.run(test_claude_workflow())
22 changes: 22 additions & 0 deletions tests/fixtures/alerts/test_false_positive.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"id": "alert-test-003",
"timestamp": "2025-11-18T15:35:00Z",
"source": "test-scanner",
"severity": "low",
"category": "test",
"title": "Scheduled System Scan",
"description": "Regular scheduled maintenance scan detected anomaly",
"raw_data": {
"source_ip": "10.0.0.50",
"destination_ip": "10.0.0.100",
"user": "svc_scanner",
"host": "SCANNER-01",
"process_name": "scanner.exe",
"event_type": "scheduled"
},
"entities": {
"ip": ["10.0.0.50", "10.0.0.100"],
"user": ["svc_scanner"],
"host": ["SCANNER-01"]
}
}
27 changes: 27 additions & 0 deletions tests/fixtures/alerts/test_malware_alert.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"id": "alert-malware-001",
"timestamp": "2025-11-18T15:30:00Z",
"source": "crowdstrike-edr",
"severity": "critical",
"category": "malware",
"title": "Trojan.Win32.Agent Detected",
"description": "Suspicious trojan detected on endpoint executing malicious payload",
"raw_data": {
"source_ip": "192.168.1.100",
"destination_ip": "185.220.101.50",
"destination_port": 4444,
"user": "administrator",
"host": "WORKSTATION-01",
"process_name": "update.exe",
"file_hash": "a1b2c3d4e5f6789",
"file_path": "C:\\Temp\\update.exe",
"event_type": "file_creation",
"protocol": "TCP"
},
"entities": {
"ip": ["192.168.1.100", "185.220.101.50"],
"hash": ["a1b2c3d4e5f6789"],
"user": ["administrator"],
"host": ["WORKSTATION-01"]
}
}
Loading