Appearance
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
Docker Installation (Recommended)
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"
}'
Case Search
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: