Skip to content

TheHive Cheat Sheet

Overview

TheHive is a scalable, open-source security incident response platform designed for SOCs, CSIRTs, CERTs and any information security practitioner dealing with security incidents that need to be investigated and acted upon swiftly.

🚀 Installation

bash
# Create directory structure
mkdir -p /opt/thehive
cd /opt/thehive

# Download docker-compose file
wget https://raw.githubusercontent.com/TheHive-Project/TheHive/master/docker/thehive/docker-compose.yml

# Create data directories
mkdir -p data/elasticsearch data/thehive

# Set permissions
sudo chown -R 1000:1000 data/

# Start services
docker-compose up -d

# Check status
docker-compose ps

Manual Installation (Ubuntu/Debian)

bash
# Add TheHive repository
wget -qO- https://raw.githubusercontent.com/TheHive-Project/TheHive/master/PGP-PUBLIC-KEY | sudo apt-key add -
echo 'deb https://deb.thehive-project.org release main' | sudo tee -a /etc/apt/sources.list.d/thehive-project.list

# Update package list
sudo apt-get update

# Install Java 8
sudo apt-get install openjdk-8-jre-headless

# Install Elasticsearch
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
sudo apt-get update
sudo apt-get install elasticsearch

# Configure Elasticsearch
sudo vi /etc/elasticsearch/elasticsearch.yml
# Add:
# cluster.name: hive
# thread_pool.search.queue_size: 100000
# path.logs: "/var/log/elasticsearch"
# path.data: "/var/lib/elasticsearch"
# http.host: 127.0.0.1
# transport.host: 127.0.0.1
# http.port: 9200
# discovery.type: single-node

# Start Elasticsearch
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch

# Install TheHive
sudo apt-get install thehive4

# Configure TheHive
sudo vi /etc/thehive/application.conf

CentOS/RHEL Installation

bash
# Add TheHive repository
sudo rpm --import https://raw.githubusercontent.com/TheHive-Project/TheHive/master/PGP-PUBLIC-KEY
sudo tee /etc/yum.repos.d/thehive-project.repo > /dev/null << 'EOF'
[thehive-project]
enabled=1
priority=1
name=TheHive-Project RPM repository
baseurl=https://rpm.thehive-project.org/release/noarch
gpgcheck=1
EOF

# Install Java 8
sudo yum install java-1.8.0-openjdk-headless

# Install Elasticsearch
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
sudo tee /etc/yum.repos.d/elasticsearch.repo > /dev/null << 'EOF'
[elasticsearch]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF

sudo yum install --enablerepo=elasticsearch elasticsearch

# Install TheHive
sudo yum install thehive4

🔧 Configuration

Basic Configuration

bash
# TheHive configuration file
sudo vi /etc/thehive/application.conf

# Basic configuration
include file("/etc/thehive/secret.conf")

## Database configuration
db.janusgraph {
  storage {
    backend: berkeleyje
    directory: /opt/thp/thehive/database
  }
  index.search {
    backend: elasticsearch
    hostname: ["127.0.0.1"]
    index-name: thehive
  }
}

## Attachment storage configuration
storage {
  provider: localfs
  localfs.location: /opt/thp/thehive/files
}

## Authentication configuration
auth {
  providers: [
    {name: session}
    {name: basic, realm: thehive}
    {name: local}
    {name: key}
  ]
}

## Cortex configuration
play.modules.enabled += org.thp.thehive.connector.cortex.CortexModule
cortex {
  servers: [
    {
      name: local
      url: "http://127.0.0.1:9001"
      auth {
        type: "bearer"
        key: "API_KEY"
      }
    }
  ]
  refreshDelay: 1 minute
  maxRetryOnError: 3
  statusCheckInterval: 1 minute
}

## MISP configuration
play.modules.enabled += org.thp.thehive.connector.misp.MispModule
misp {
  interval: 1 hour
  servers: [
    {
      name: "MISP-SERVER"
      url: "https://misp.example.com"
      auth {
        type: key
        key: "MISP_API_KEY"
      }
      wsConfig {}
    }
  ]
}

## Notification configuration
notification.webhook.endpoints = [
  {
    name: local
    url: "http://127.0.0.1:5000/"
    version: 0
    wsConfig: {}
    includedTheHiveOrganisations: ["*"]
    excludedTheHiveOrganisations: []
  }
]

## Service configuration
http.address: 0.0.0.0
http.port: 9000
play.http.secret.key: "CHANGE_ME_PLEASE"

# Secret configuration
sudo vi /etc/thehive/secret.conf

# Add secret key
play.http.secret.key="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1)"

Database Configuration

bash
# Elasticsearch configuration for TheHive
sudo vi /etc/elasticsearch/elasticsearch.yml

# Cluster settings
cluster.name: thehive
node.name: thehive-node-1

# Network settings
network.host: 127.0.0.1
http.port: 9200
discovery.type: single-node

# Memory settings
bootstrap.memory_lock: true

# Thread pool settings
thread_pool.search.queue_size: 100000
thread_pool.write.queue_size: 10000

# Index settings
indices.query.bool.max_clause_count: 100000

# Configure JVM heap
sudo vi /etc/elasticsearch/jvm.options
# Set heap size to 50% of available RAM
-Xms4g
-Xmx4g

# Start Elasticsearch
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch

# Verify Elasticsearch
curl -X GET "localhost:9200/_cluster/health?pretty"

SSL/TLS Configuration

bash
# Generate SSL certificate
sudo openssl req -x509 -newkey rsa:4096 -keyout /etc/thehive/thehive-key.pem -out /etc/thehive/thehive-cert.pem -days 365 -nodes

# Configure HTTPS in TheHive
sudo vi /etc/thehive/application.conf

# Add HTTPS configuration
https {
  port: 9443
  keyStore {
    path: "/etc/thehive/thehive.p12"
    type: "PKCS12"
    password: "changeme"
  }
}

# Convert PEM to PKCS12
sudo openssl pkcs12 -export -out /etc/thehive/thehive.p12 -inkey /etc/thehive/thehive-key.pem -in /etc/thehive/thehive-cert.pem

# Set permissions
sudo chown thehive:thehive /etc/thehive/thehive*
sudo chmod 600 /etc/thehive/thehive*

👥 User Management

Initial Setup

bash
# Start TheHive
sudo systemctl start thehive

# Access web interface
http://localhost:9000

# Default admin credentials
Username: admin@thehive.local
Password: secret

# Change admin password immediately
# Navigate to Admin -> Users -> admin@thehive.local -> Edit

User Creation via API

bash
# Get API key
API_KEY="your-api-key"
THEHIVE_URL="http://localhost:9000"

# Create user
curl -X POST "$THEHIVE_URL/api/user" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "login": "analyst@company.com",
    "name": "Security Analyst",
    "roles": ["read", "write"],
    "password": "TempPassword123!"
  }'

# Create organization
curl -X POST "$THEHIVE_URL/api/organisation" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Security Team",
    "description": "Main security organization"
  }'

# Assign user to organization
curl -X POST "$THEHIVE_URL/api/organisation/Security%20Team/user/analyst@company.com" \
  -H "Authorization: Bearer $API_KEY"

Role Management

bash
# Available roles
# - read: Read-only access
# - write: Read and write access
# - admin: Full administrative access

# Update user roles
curl -X PATCH "$THEHIVE_URL/api/user/analyst@company.com" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "roles": ["read", "write", "admin"]
  }'

📋 Case Management

Creating Cases

bash
# Create case via API
curl -X POST "$THEHIVE_URL/api/case" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Suspicious Network Activity",
    "description": "Unusual traffic patterns detected",
    "severity": 2,
    "tlp": 2,
    "pap": 2,
    "tags": ["network", "suspicious", "investigation"],
    "customFields": {
      "businessUnit": {
        "string": "IT Department"
      }
    }
  }'

# Create case with template
curl -X POST "$THEHIVE_URL/api/case" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Malware Incident",
    "description": "Potential malware infection detected",
    "severity": 3,
    "tlp": 3,
    "template": "malware-investigation"
  }'

Case Updates

bash
# Update case status
curl -X PATCH "$THEHIVE_URL/api/case/CASE_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "InProgress"
  }'

# Add tags to case
curl -X PATCH "$THEHIVE_URL/api/case/CASE_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["malware", "endpoint", "critical"]
  }'

# Assign case
curl -X PATCH "$THEHIVE_URL/api/case/CASE_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "assignee": "analyst@company.com"
  }'
bash
# Search cases
curl -X POST "$THEHIVE_URL/api/case/_search" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "_and": [
        {"status": "Open"},
        {"severity": {"_gte": 2}}
      ]
    }
  }'

# Search by date range
curl -X POST "$THEHIVE_URL/api/case/_search" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "_and": [
        {"createdAt": {"_gte": 1609459200000}},
        {"createdAt": {"_lt": 1612137600000}}
      ]
    }
  }'

📝 Task Management

Creating Tasks

bash
# Create task
curl -X POST "$THEHIVE_URL/api/case/CASE_ID/task" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Analyze Network Logs",
    "description": "Review firewall and proxy logs for suspicious activity",
    "status": "Waiting",
    "assignee": "analyst@company.com"
  }'

# Create task with due date
curl -X POST "$THEHIVE_URL/api/case/CASE_ID/task" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Containment Actions",
    "description": "Isolate affected systems",
    "status": "InProgress",
    "dueDate": 1640995200000
  }'

Task Updates

bash
# Update task status
curl -X PATCH "$THEHIVE_URL/api/case/task/TASK_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "Completed"
  }'

# Add task log
curl -X POST "$THEHIVE_URL/api/case/task/TASK_ID/log" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Completed analysis of network logs. Found 15 suspicious connections.",
    "startDate": 1640995200000,
    "status": "Ok"
  }'

🔍 Observable Management

Adding Observables

bash
# Add IP observable
curl -X POST "$THEHIVE_URL/api/case/CASE_ID/artifact" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dataType": "ip",
    "data": "192.168.1.100",
    "message": "Suspicious IP address from network logs",
    "tlp": 2,
    "ioc": true,
    "sighted": true,
    "tags": ["suspicious", "network"]
  }'

# Add file hash observable
curl -X POST "$THEHIVE_URL/api/case/CASE_ID/artifact" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dataType": "hash",
    "data": "d41d8cd98f00b204e9800998ecf8427e",
    "message": "MD5 hash of suspicious file",
    "tlp": 3,
    "ioc": true,
    "tags": ["malware", "hash"]
  }'

# Add domain observable
curl -X POST "$THEHIVE_URL/api/case/CASE_ID/artifact" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dataType": "domain",
    "data": "malicious-domain.com",
    "message": "C2 domain identified in traffic",
    "tlp": 2,
    "ioc": true,
    "tags": ["c2", "domain"]
  }'

Observable Analysis

bash
# Run analyzer on observable
curl -X POST "$THEHIVE_URL/api/connector/cortex/analyzer/ANALYZER_ID/artifact/OBSERVABLE_ID" \
  -H "Authorization: Bearer $API_KEY"

# Get analysis results
curl -X GET "$THEHIVE_URL/api/connector/cortex/job/JOB_ID" \
  -H "Authorization: Bearer $API_KEY"

# Get observable details
curl -X GET "$THEHIVE_URL/api/case/artifact/OBSERVABLE_ID" \
  -H "Authorization: Bearer $API_KEY"

🔗 Cortex Integration

Cortex Configuration

bash
# Configure Cortex in TheHive
sudo vi /etc/thehive/application.conf

# Add Cortex configuration
play.modules.enabled += org.thp.thehive.connector.cortex.CortexModule
cortex {
  servers: [
    {
      name: local
      url: "http://127.0.0.1:9001"
      auth {
        type: "bearer"
        key: "CORTEX_API_KEY"
      }
      wsConfig {
        ssl {
          loose {
            acceptAnyCertificate: true
            allowWeakProtocols: true
          }
        }
      }
    }
  ]
  refreshDelay: 1 minute
  maxRetryOnError: 3
  statusCheckInterval: 1 minute
}

Running Analyzers

bash
# List available analyzers
curl -X GET "$THEHIVE_URL/api/connector/cortex/analyzer" \
  -H "Authorization: Bearer $API_KEY"

# Run VirusTotal analyzer
curl -X POST "$THEHIVE_URL/api/connector/cortex/analyzer/VirusTotal_GetReport_3_0/artifact/OBSERVABLE_ID" \
  -H "Authorization: Bearer $API_KEY"

# Run multiple analyzers
curl -X POST "$THEHIVE_URL/api/connector/cortex/analyzer/_search" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "dataTypeList": ["ip"]
    }
  }' | jq -r '.[].id' | while read analyzer_id; do
    curl -X POST "$THEHIVE_URL/api/connector/cortex/analyzer/$analyzer_id/artifact/OBSERVABLE_ID" \
      -H "Authorization: Bearer $API_KEY"
  done

📊 MISP Integration

MISP Configuration

bash
# Configure MISP in TheHive
sudo vi /etc/thehive/application.conf

# Add MISP configuration
play.modules.enabled += org.thp.thehive.connector.misp.MispModule
misp {
  interval: 1 hour
  servers: [
    {
      name: "MISP-PROD"
      url: "https://misp.company.com"
      auth {
        type: key
        key: "MISP_API_KEY"
      }
      wsConfig {
        ssl {
          loose {
            acceptAnyCertificate: false
          }
        }
      }
      purpose: ImportAndExport
      caseTemplate: "misp-event"
      tags: ["misp", "threat-intel"]
      max: 100
      age: 7 days
      includedTheHiveOrganisations: ["*"]
      excludedTheHiveOrganisations: []
    }
  ]
}

MISP Operations

bash
# Export case to MISP
curl -X POST "$THEHIVE_URL/api/connector/misp/export/case/CASE_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "server": "MISP-PROD",
    "organisation": "Security Team",
    "sharing": 1,
    "tlp": 2,
    "tags": ["investigation", "incident"]
  }'

# Import MISP event
curl -X POST "$THEHIVE_URL/api/connector/misp/import/event/EVENT_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "server": "MISP-PROD",
    "organisation": "Security Team"
  }'

📈 Reporting and Analytics

Case Statistics

bash
# Get case statistics
curl -X POST "$THEHIVE_URL/api/case/_stats" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "status": "Resolved"
    },
    "stats": [
      {"_field": "severity"},
      {"_field": "resolutionStatus"},
      {"_field": "tags"}
    ]
  }'

# Get cases by time range
curl -X POST "$THEHIVE_URL/api/case/_search" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "_and": [
        {"createdAt": {"_gte": "2023-01-01T00:00:00Z"}},
        {"createdAt": {"_lt": "2023-12-31T23:59:59Z"}}
      ]
    },
    "range": "all"
  }'

Custom Reports

bash
# Generate monthly report
curl -X POST "$THEHIVE_URL/api/case/_search" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "_and": [
        {"createdAt": {"_gte": "2023-10-01T00:00:00Z"}},
        {"createdAt": {"_lt": "2023-11-01T00:00:00Z"}}
      ]
    },
    "range": "all"
  }' | jq '{
    total_cases: length,
    by_severity: group_by(.severity) | map({severity: .[0].severity, count: length}),
    by_status: group_by(.status) | map({status: .[0].status, count: length})
  }'

🔧 Automation Scripts

Python Case Management

python
#!/usr/bin/env python3
import requests
import json
from datetime import datetime, timedelta

class TheHiveAPI:
    def __init__(self, url, api_key):
        self.url = url.rstrip('/')
        self.api_key = api_key
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }
    
    def create_case(self, title, description, severity=2, tlp=2, tags=None):
        """Create a new case"""
        data = {
            'title': title,
            'description': description,
            'severity': severity,
            'tlp': tlp,
            'tags': tags or []
        }
        
        response = requests.post(
            f'{self.url}/api/case',
            headers=self.headers,
            json=data
        )
        
        if response.status_code == 201:
            return response.json()
        else:
            raise Exception(f"Failed to create case: {response.text}")
    
    def add_observable(self, case_id, data_type, data, message="", ioc=False, tags=None):
        """Add observable to case"""
        observable_data = {
            'dataType': data_type,
            'data': data,
            'message': message,
            'ioc': ioc,
            'tags': tags or []
        }
        
        response = requests.post(
            f'{self.url}/api/case/{case_id}/artifact',
            headers=self.headers,
            json=observable_data
        )
        
        if response.status_code == 201:
            return response.json()
        else:
            raise Exception(f"Failed to add observable: {response.text}")
    
    def create_task(self, case_id, title, description="", assignee=None):
        """Create task in case"""
        task_data = {
            'title': title,
            'description': description,
            'status': 'Waiting'
        }
        
        if assignee:
            task_data['assignee'] = assignee
        
        response = requests.post(
            f'{self.url}/api/case/{case_id}/task',
            headers=self.headers,
            json=task_data
        )
        
        if response.status_code == 201:
            return response.json()
        else:
            raise Exception(f"Failed to create task: {response.text}")
    
    def search_cases(self, query):
        """Search cases"""
        response = requests.post(
            f'{self.url}/api/case/_search',
            headers=self.headers,
            json={'query': query}
        )
        
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"Failed to search cases: {response.text}")
    
    def get_case_stats(self):
        """Get case statistics"""
        # Get cases from last 30 days
        thirty_days_ago = int((datetime.now() - timedelta(days=30)).timestamp() * 1000)
        
        query = {
            'createdAt': {'_gte': thirty_days_ago}
        }
        
        cases = self.search_cases(query)
        
        stats = {
            'total_cases': len(cases),
            'by_severity': {},
            'by_status': {},
            'by_assignee': {}
        }
        
        for case in cases:
            # Count by severity
            severity = case.get('severity', 'Unknown')
            stats['by_severity'][severity] = stats['by_severity'].get(severity, 0) + 1
            
            # Count by status
            status = case.get('status', 'Unknown')
            stats['by_status'][status] = stats['by_status'].get(status, 0) + 1
            
            # Count by assignee
            assignee = case.get('assignee', 'Unassigned')
            stats['by_assignee'][assignee] = stats['by_assignee'].get(assignee, 0) + 1
        
        return stats

def main():
    # Initialize API client
    api = TheHiveAPI('http://localhost:9000', 'YOUR_API_KEY')
    
    # Example: Create incident case
    case = api.create_case(
        title="Suspicious Email Investigation",
        description="Phishing email reported by user",
        severity=2,
        tags=["phishing", "email", "investigation"]
    )
    
    case_id = case['_id']
    print(f"Created case: {case_id}")
    
    # Add observables
    api.add_observable(
        case_id,
        'mail',
        'suspicious@malicious-domain.com',
        'Sender email address',
        ioc=True,
        tags=['sender', 'email']
    )
    
    api.add_observable(
        case_id,
        'domain',
        'malicious-domain.com',
        'Suspicious domain',
        ioc=True,
        tags=['domain', 'c2']
    )
    
    # Create tasks
    api.create_task(
        case_id,
        'Analyze Email Headers',
        'Review email headers for routing information'
    )
    
    api.create_task(
        case_id,
        'Check Domain Reputation',
        'Verify domain reputation in threat intelligence feeds'
    )
    
    print("Case setup completed")
    
    # Get statistics
    stats = api.get_case_stats()
    print("\nCase Statistics (Last 30 days):")
    print(json.dumps(stats, indent=2))

if __name__ == "__main__":
    main()

Bash Monitoring Script

bash
#!/bin/bash
# TheHive Health Check and Monitoring Script

THEHIVE_URL="http://localhost:9000"
API_KEY="YOUR_API_KEY"
LOG_FILE="/var/log/thehive-monitor.log"
EMAIL="admin@company.com"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# Check TheHive service status
check_thehive_status() {
    log_message "Checking TheHive service status..."
    
    if systemctl is-active --quiet thehive; then
        log_message "✓ TheHive service is running"
        return 0
    else
        log_message "✗ TheHive service is not running"
        echo "TheHive service is down on $(hostname)" | mail -s "TheHive Alert" $EMAIL
        return 1
    fi
}

# Check TheHive API connectivity
check_api_connectivity() {
    log_message "Checking TheHive API connectivity..."
    
    response=$(curl -s -o /dev/null -w "%{http_code}" \
        -H "Authorization: Bearer $API_KEY" \
        "$THEHIVE_URL/api/status")
    
    if [ "$response" = "200" ]; then
        log_message "✓ TheHive API is accessible"
        return 0
    else
        log_message "✗ TheHive API is not accessible (HTTP $response)"
        echo "TheHive API is not accessible on $(hostname)" | mail -s "TheHive API Alert" $EMAIL
        return 1
    fi
}

# Check Elasticsearch connectivity
check_elasticsearch() {
    log_message "Checking Elasticsearch connectivity..."
    
    response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:9200/_cluster/health")
    
    if [ "$response" = "200" ]; then
        log_message "✓ Elasticsearch is accessible"
        return 0
    else
        log_message "✗ Elasticsearch is not accessible (HTTP $response)"
        echo "Elasticsearch is not accessible on $(hostname)" | mail -s "TheHive ES Alert" $EMAIL
        return 1
    fi
}

# Check disk usage
check_disk_usage() {
    log_message "Checking disk usage..."
    
    usage=$(df /opt/thp | tail -1 | awk '{print $5}' | sed 's/%//')
    
    if [ $usage -gt 80 ]; then
        log_message "⚠ Disk usage is ${usage}%"
        echo "TheHive disk usage is ${usage}% on $(hostname)" | mail -s "TheHive Disk Alert" $EMAIL
    else
        log_message "✓ Disk usage is ${usage}%"
    fi
}

# Check recent cases
check_recent_cases() {
    log_message "Checking recent case activity..."
    
    # Get cases created in last 24 hours
    yesterday=$(date -d "yesterday" +%s)000
    
    case_count=$(curl -s \
        -H "Authorization: Bearer $API_KEY" \
        -H "Content-Type: application/json" \
        -X POST "$THEHIVE_URL/api/case/_search" \
        -d "{\"query\":{\"createdAt\":{\"_gte\":$yesterday}}}" | \
        jq '. | length')
    
    if [ "$case_count" != "null" ] && [ "$case_count" -ge 0 ]; then
        log_message "✓ $case_count cases created in last 24 hours"
    else
        log_message "⚠ Unable to retrieve case statistics"
    fi
}

# Generate health report
generate_report() {
    log_message "Generating health report..."
    
    report_file="/tmp/thehive-health-report.txt"
    
    echo "TheHive Health Report - $(date)" > $report_file
    echo "=================================" >> $report_file
    echo "" >> $report_file
    
    # Service status
    if systemctl is-active --quiet thehive; then
        echo "TheHive Service: RUNNING" >> $report_file
    else
        echo "TheHive Service: STOPPED" >> $report_file
    fi
    
    # API status
    api_response=$(curl -s -o /dev/null -w "%{http_code}" \
        -H "Authorization: Bearer $API_KEY" \
        "$THEHIVE_URL/api/status")
    echo "API Status: HTTP $api_response" >> $report_file
    
    # Elasticsearch status
    es_response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:9200/_cluster/health")
    echo "Elasticsearch Status: HTTP $es_response" >> $report_file
    
    # Disk usage
    usage=$(df /opt/thp | tail -1 | awk '{print $5}')
    echo "Disk Usage: $usage" >> $report_file
    
    # Case statistics
    yesterday=$(date -d "yesterday" +%s)000
    case_count=$(curl -s \
        -H "Authorization: Bearer $API_KEY" \
        -H "Content-Type: application/json" \
        -X POST "$THEHIVE_URL/api/case/_search" \
        -d "{\"query\":{\"createdAt\":{\"_gte\":$yesterday}}}" | \
        jq '. | length' 2>/dev/null || echo "N/A")
    echo "Cases (24h): $case_count" >> $report_file
    
    log_message "Health report generated: $report_file"
}

# Main execution
main() {
    log_message "Starting TheHive health check..."
    
    check_thehive_status
    check_api_connectivity
    check_elasticsearch
    check_disk_usage
    check_recent_cases
    generate_report
    
    log_message "Health check completed"
}

# Run main function
main "$@"

🔍 Troubleshooting

Common Issues

bash
# TheHive won't start
sudo systemctl status thehive
sudo journalctl -u thehive -f

# Check configuration syntax
sudo /opt/thehive/bin/thehive -Dconfig.file=/etc/thehive/application.conf

# Database connection issues
curl -X GET "localhost:9200/_cluster/health?pretty"
sudo tail -f /var/log/thehive/application.log

# Permission issues
sudo chown -R thehive:thehive /opt/thp/
sudo chmod -R 750 /opt/thp/

# Memory issues
sudo vi /etc/thehive/application.conf
# Add: play.server.akka.max-header-value-length = 16k

Performance Issues

bash
# High CPU usage
top -p $(pgrep -f thehive)

# Memory issues
free -h
sudo cat /proc/meminfo

# Database performance
curl -X GET "localhost:9200/_nodes/stats?pretty"
curl -X GET "localhost:9200/_cluster/stats?pretty"

# Network issues
sudo netstat -tlnp | grep 9000
sudo tcpdump -i any port 9000

📖 Best Practices

Security

  • Change default passwords and API keys
  • Use HTTPS for web interface
  • Implement proper firewall rules
  • Regular security updates
  • Monitor access logs

Performance

  • Tune Elasticsearch configuration
  • Implement proper indexing strategy
  • Monitor resource usage
  • Use SSD storage for database
  • Regular maintenance and cleanup

Operations

  • Regular backup of data and configuration
  • Implement monitoring and alerting
  • Document incident response procedures
  • Train staff on TheHive usage
  • Regular testing of integrations

⚠️ Security Notice: TheHive should only be used for authorized incident response activities. Ensure compliance with organizational policies and legal requirements.

📚 Additional Resources: