Files
LogWhispererAI/workflows/test_workflow.sh
Luca Sacchi Ricciardi 3c406ef405 feat: create n8n workflow for secure log ingestion
Implement LogWhisperer_Ingest workflow for Sprint 2 Feature 2:

Workflow Components:
- Webhook trigger: POST /webhook/logwhisperer/ingest
- HMAC-SHA256 validation with timing-safe comparison
- Anti-replay protection (5min timestamp window)
- Data validation: UUID client_id, severity levels, non-empty logs
- PostgreSQL storage with logs table auto-creation
- Conditional routing for critical severity logs

Security Features:
- HMAC signature verification (X-LogWhisperer-Signature header)
- Timestamp validation preventing replay attacks
- Input sanitization before DB insert
- Environment variable LOGWHISPERER_SECRET for shared secret

Documentation:
- workflows/logwhisperer_ingest.json: Export JSON workflow
- workflows/README.md: Installation and usage guide
- workflows/INTEGRATION.md: Bash script integration guide
- workflows/REPORT.md: Implementation report
- workflows/test_workflow.sh: Automated test suite

Metodo Sacchi Applied:
- Safety First: HMAC validation before any processing
- Little Often: Modular nodes, each with single responsibility
- Double Check: Test suite validates all security requirements

Next Steps:
- Configure LOGWHISPERER_SECRET in n8n environment
- Import workflow to n8n instance
- Test end-to-end with secure_logwhisperer.sh
2026-04-02 19:01:40 +02:00

251 lines
6.1 KiB
Bash
Executable File

#!/bin/bash
#
# LogWhisperer AI - Workflow Test Script
# Verifica che il workflow n8n risponda correttamente
#
set -euo pipefail
N8N_URL="${N8N_URL:-http://192.168.254.12:5678}"
WEBHOOK_PATH="/webhook/logwhisperer/ingest"
CLIENT_SECRET="${CLIENT_SECRET:-test-secret-32-chars-long-minimum}"
# Colori per output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Funzione per generare HMAC
generate_hmac() {
local payload="$1"
local timestamp="$2"
local secret="$3"
printf '%s:%s' "$timestamp" "$payload" | \
openssl dgst -sha256 -hmac "$secret" | \
sed 's/^.* //'
}
# Test 1: HMAC Valido
test_valid_hmac() {
log_info "Test 1: Invio log con HMAC valido..."
local timestamp
timestamp=$(date +%s)
local payload
payload=$(cat <<EOF
{
"client_id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "test-server",
"source": "/var/log/syslog",
"severity": "critical",
"raw_log": "Apr 2 10:30:00 kernel: Out of memory",
"matched_pattern": "OOM"
}
EOF
)
local signature
signature=$(generate_hmac "$payload" "$timestamp" "$CLIENT_SECRET")
local response
response=$(curl -s -w "\n%{http_code}" -X POST "${N8N_URL}${WEBHOOK_PATH}" \
-H "Content-Type: application/json" \
-H "X-LogWhisperer-Signature: ${timestamp}:${signature}" \
-H "X-LogWhisperer-Timestamp: ${timestamp}" \
-d "$payload" || echo "000")
local http_code
http_code=$(echo "$response" | tail -n1)
local body
body=$(echo "$response" | sed '$d')
if [[ "$http_code" == "200" ]]; then
log_info "✓ Test 1 PASSATO: Risposta 200 OK"
echo " Risposta: $body"
return 0
else
log_error "✗ Test 1 FALLITO: Atteso 200, ricevuto $http_code"
echo " Risposta: $body"
return 1
fi
}
# Test 2: HMAC Invalido
test_invalid_hmac() {
log_info "Test 2: Invio log con HMAC invalido..."
local timestamp
timestamp=$(date +%s)
local payload
payload=$(cat <<EOF
{
"client_id": "550e8400-e29b-41d4-a716-446655440000",
"severity": "critical",
"raw_log": "test error"
}
EOF
)
local response
response=$(curl -s -w "\n%{http_code}" -X POST "${N8N_URL}${WEBHOOK_PATH}" \
-H "Content-Type: application/json" \
-H "X-LogWhisperer-Signature: invalid-signature" \
-H "X-LogWhisperer-Timestamp: ${timestamp}" \
-d "$payload" || echo "000")
local http_code
http_code=$(echo "$response" | tail -n1)
if [[ "$http_code" == "401" ]]; then
log_info "✓ Test 2 PASSATO: Risposta 401 Unauthorized (atteso)"
return 0
else
log_error "✗ Test 2 FALLITO: Atteso 401, ricevuto $http_code"
return 1
fi
}
# Test 3: Dati invalidi (client_id non UUID)
test_invalid_data() {
log_info "Test 3: Invio log con dati invalidi (client_id non UUID)..."
local timestamp
timestamp=$(date +%s)
local payload
payload=$(cat <<EOF
{
"client_id": "not-a-uuid",
"severity": "critical",
"raw_log": "test error"
}
EOF
)
local signature
signature=$(generate_hmac "$payload" "$timestamp" "$CLIENT_SECRET")
local response
response=$(curl -s -w "\n%{http_code}" -X POST "${N8N_URL}${WEBHOOK_PATH}" \
-H "Content-Type: application/json" \
-H "X-LogWhisperer-Signature: ${timestamp}:${signature}" \
-H "X-LogWhisperer-Timestamp: ${timestamp}" \
-d "$payload" || echo "000")
local http_code
http_code=$(echo "$response" | tail -n1)
if [[ "$http_code" == "400" ]]; then
log_info "✓ Test 3 PASSATO: Risposta 400 Bad Request (atteso)"
return 0
else
log_error "✗ Test 3 FALLITO: Atteso 400, ricevuto $http_code"
return 1
fi
}
# Test 4: Severity=medium (non dovrebbe triggerare AI)
test_medium_severity() {
log_info "Test 4: Invio log con severity=medium..."
local timestamp
timestamp=$(date +%s)
local payload
payload=$(cat <<EOF
{
"client_id": "550e8400-e29b-41d4-a716-446655440001",
"hostname": "test-server",
"source": "/var/log/syslog",
"severity": "medium",
"raw_log": "Normal operation log",
"matched_pattern": "INFO"
}
EOF
)
local signature
signature=$(generate_hmac "$payload" "$timestamp" "$CLIENT_SECRET")
local response
response=$(curl -s -w "\n%{http_code}" -X POST "${N8N_URL}${WEBHOOK_PATH}" \
-H "Content-Type: application/json" \
-H "X-LogWhisperer-Signature: ${timestamp}:${signature}" \
-H "X-LogWhisperer-Timestamp: ${timestamp}" \
-d "$payload" || echo "000")
local http_code
http_code=$(echo "$response" | tail -n1)
if [[ "$http_code" == "200" ]]; then
log_info "✓ Test 4 PASSATO: Risposta 200 OK (no AI trigger)"
return 0
else
log_error "✗ Test 4 FALLITO: Atteso 200, ricevuto $http_code"
return 1
fi
}
# Main
main() {
echo "=========================================="
echo "LogWhisperer AI - Workflow Test Suite"
echo "Target: ${N8N_URL}"
echo "=========================================="
echo ""
# Verifica dipendenze
if ! command -v curl &> /dev/null; then
log_error "curl non trovato. Installare curl."
exit 1
fi
if ! command -v openssl &> /dev/null; then
log_error "openssl non trovato. Installare openssl."
exit 1
fi
local failed=0
# Esegui test
test_valid_hmac || failed=$((failed + 1))
echo ""
test_invalid_hmac || failed=$((failed + 1))
echo ""
test_invalid_data || failed=$((failed + 1))
echo ""
test_medium_severity || failed=$((failed + 1))
echo ""
# Report finale
echo "=========================================="
if [[ $failed -eq 0 ]]; then
log_info "Tutti i test PASSATI! ✓"
exit 0
else
log_error "$failed test FALLITI! ✗"
exit 1
fi
}
main "$@"