Files
timebank-cc-public/scripts/check-elasticsearch-security.sh
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

153 lines
6.2 KiB
Bash
Executable File

#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}==========================================${NC}"
echo -e "${BLUE} Elasticsearch Security Check${NC}"
echo -e "${BLUE}==========================================${NC}\n"
# Check if Elasticsearch is running
if ! systemctl is-active --quiet elasticsearch; then
echo -e "${YELLOW}⚠ Elasticsearch is not running${NC}"
exit 0
fi
echo -e "${GREEN}✓ Elasticsearch is running${NC}\n"
# Check listening interfaces
echo -e "${BLUE}Checking network bindings...${NC}"
LISTEN_OUTPUT=$(ss -tlnp 2>/dev/null | grep 9200)
if [ -z "$LISTEN_OUTPUT" ]; then
echo -e "${RED}✗ Elasticsearch not found listening on port 9200${NC}\n"
exit 1
fi
echo "$LISTEN_OUTPUT"
echo ""
# Check if bound to localhost only
# Accept: 127.0.0.1, ::1, and ::ffff:127.0.0.1 (IPv6-mapped IPv4)
if echo "$LISTEN_OUTPUT" | grep -qE "127.0.0.1:9200|::1\]:9200|::ffff:127.0.0.1\]:9200"; then
if echo "$LISTEN_OUTPUT" | grep -qE "0.0.0.0:9200|\*:9200"; then
echo -e "${RED}✗ DANGER: Elasticsearch is bound to ALL interfaces (0.0.0.0)${NC}"
echo -e "${RED} This means it's accessible from the network/internet!${NC}\n"
EXPOSED=true
else
echo -e "${GREEN}✓ SAFE: Elasticsearch is bound to localhost only${NC}"
if echo "$LISTEN_OUTPUT" | grep -q "::ffff:127.0.0.1"; then
echo -e "${GREEN} (Including IPv6-mapped IPv4 localhost)${NC}\n"
else
echo ""
fi
EXPOSED=false
fi
else
if echo "$LISTEN_OUTPUT" | grep -qE "0.0.0.0:9200|\*:9200"; then
echo -e "${RED}✗ DANGER: Elasticsearch is bound to ALL interfaces (0.0.0.0)${NC}"
echo -e "${RED} This means it's accessible from the network/internet!${NC}\n"
EXPOSED=true
else
echo -e "${YELLOW}⚠ WARNING: Elasticsearch might be bound to a specific network interface${NC}\n"
EXPOSED=true
fi
fi
# Check configuration file
echo -e "${BLUE}Checking configuration file...${NC}"
if [ -f /etc/elasticsearch/elasticsearch.yml ]; then
NETWORK_HOST=$(grep "^network.host:" /etc/elasticsearch/elasticsearch.yml 2>/dev/null | awk '{print $2}')
SECURITY_ENABLED=$(grep "^xpack.security.enabled:" /etc/elasticsearch/elasticsearch.yml 2>/dev/null | awk '{print $2}')
if [ -n "$NETWORK_HOST" ]; then
echo -e "network.host: ${YELLOW}$NETWORK_HOST${NC}"
if [ "$NETWORK_HOST" = "127.0.0.1" ] || [ "$NETWORK_HOST" = "localhost" ]; then
echo -e "${GREEN}✓ Configuration: Bound to localhost${NC}"
elif [ "$NETWORK_HOST" = "0.0.0.0" ]; then
echo -e "${RED}✗ Configuration: Bound to ALL interfaces - INSECURE!${NC}"
else
echo -e "${YELLOW}⚠ Configuration: Bound to specific interface${NC}"
fi
else
echo -e "${YELLOW}⚠ network.host not explicitly set (using default)${NC}"
fi
if [ -n "$SECURITY_ENABLED" ]; then
echo -e "xpack.security.enabled: ${YELLOW}$SECURITY_ENABLED${NC}"
if [ "$SECURITY_ENABLED" = "true" ]; then
echo -e "${GREEN}✓ Security: Authentication enabled${NC}"
else
echo -e "${YELLOW}⚠ Security: Authentication disabled${NC}"
if [ "$NETWORK_HOST" = "127.0.0.1" ] || [ "$NETWORK_HOST" = "localhost" ]; then
echo -e "${GREEN} (OK for localhost-only setup)${NC}"
else
echo -e "${RED} (DANGEROUS if accessible from network!)${NC}"
fi
fi
else
echo -e "${YELLOW}⚠ xpack.security.enabled not set (default: false)${NC}"
fi
echo ""
else
echo -e "${RED}✗ Cannot access /etc/elasticsearch/elasticsearch.yml${NC}"
echo -e "${YELLOW} (Run with sudo to read config file)${NC}\n"
fi
# Test local access
echo -e "${BLUE}Testing local access...${NC}"
LOCAL_RESPONSE=$(curl -s http://localhost:9200 2>&1)
if echo "$LOCAL_RESPONSE" | grep -q "\"cluster_name\""; then
echo -e "${GREEN}✓ Accessible locally on localhost:9200${NC}\n"
else
echo -e "${RED}✗ Cannot access locally${NC}\n"
fi
# Get network interfaces
echo -e "${BLUE}Network interfaces:${NC}"
ip addr show | grep "inet " | grep -v "127.0.0.1" | awk '{print " " $2}'
echo ""
# Try to test external access (if we have an external IP)
EXTERNAL_IP=$(ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $2}' | cut -d'/' -f1)
if [ -n "$EXTERNAL_IP" ]; then
echo -e "${BLUE}Testing external access from $EXTERNAL_IP...${NC}"
EXTERNAL_RESPONSE=$(curl -s --connect-timeout 2 "http://$EXTERNAL_IP:9200" 2>&1)
if echo "$EXTERNAL_RESPONSE" | grep -q "\"cluster_name\""; then
echo -e "${RED}✗✗✗ DANGER: Elasticsearch IS ACCESSIBLE from $EXTERNAL_IP ✗✗✗${NC}"
echo -e "${RED} Anyone on your network can access your database!${NC}\n"
EXPOSED=true
elif echo "$EXTERNAL_RESPONSE" | grep -q "Connection refused"; then
echo -e "${GREEN}✓ SAFE: Not accessible from $EXTERNAL_IP${NC}\n"
else
echo -e "${YELLOW}⚠ Unable to test (got: $EXTERNAL_RESPONSE)${NC}\n"
fi
fi
# Final verdict
echo -e "${BLUE}==========================================${NC}"
if [ "$EXPOSED" = true ]; then
echo -e "${RED} SECURITY RISK DETECTED!${NC}"
echo -e "${BLUE}==========================================${NC}\n"
echo -e "${RED}Action Required:${NC}"
echo -e "1. Stop Elasticsearch: ${YELLOW}sudo systemctl stop elasticsearch${NC}"
echo -e "2. Edit config: ${YELLOW}sudo nano /etc/elasticsearch/elasticsearch.yml${NC}"
echo -e "3. Set: ${YELLOW}network.host: 127.0.0.1${NC}"
echo -e "4. Set: ${YELLOW}xpack.security.enabled: true${NC}"
echo -e "5. Restart: ${YELLOW}sudo systemctl start elasticsearch${NC}"
echo -e "\nSee ${BLUE}references/ELASTICSEARCH_SETUP.md${NC} for detailed security guide\n"
exit 1
else
echo -e "${GREEN} System appears secure${NC}"
echo -e "${BLUE}==========================================${NC}\n"
if [ "$SECURITY_ENABLED" != "true" ]; then
echo -e "${YELLOW}Recommendation: Enable authentication for additional security${NC}"
echo -e "See ${BLUE}references/ELASTICSEARCH_SETUP.md${NC} for instructions\n"
fi
exit 0
fi