Configure Elasticsearch 8 with X-Pack security to authenticate users against LDAP and Active Directory servers. This tutorial covers LDAP realm configuration, role-based access control, and troubleshooting authentication issues.
Prerequisites
- Root or sudo access
- Active Directory or LDAP server access
- Java 11 or higher
- Minimum 4GB RAM
- Network connectivity to LDAP server
What this solves
Elasticsearch 8's X-Pack security module provides built-in LDAP authentication that integrates with Active Directory and other LDAP servers. This eliminates the need to manage separate user accounts in Elasticsearch while providing centralized authentication and role-based access control. You'll configure secure authentication for your existing corporate directory infrastructure.
Step-by-step configuration
Update system packages and install Java
Elasticsearch requires Java 11 or higher. Update your system and install the required dependencies.
sudo apt update && sudo apt upgrade -y
sudo apt install -y openjdk-11-jdk curl wget gnupg
Add Elasticsearch repository and install
Add the official Elasticsearch repository to install the latest version 8 with X-Pack security enabled by default.
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update
sudo apt install -y elasticsearch
Configure basic Elasticsearch settings
Set up basic cluster configuration and memory settings for optimal performance. This configuration works for both single-node and multi-node setups.
cluster.name: production-cluster
node.name: node-1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
Security settings
xpack.security.enabled: true
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
Set JVM heap size
Configure JVM memory based on your system resources. Set heap size to half of available RAM, maximum 32GB.
-Xms2g
-Xmx2g
Start Elasticsearch and set built-in user passwords
Enable and start Elasticsearch, then configure passwords for built-in users including the elastic superuser.
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
sudo systemctl status elasticsearch
Wait for Elasticsearch to start, then set passwords for built-in users:
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
Configure LDAP authentication realm
Add LDAP realm configuration to authenticate against your Active Directory or LDAP server. This configuration supports both Active Directory and standard LDAP servers.
# LDAP Authentication Configuration
xpack.security.authc.realms.ldap.ldap1:
order: 0
url: "ldaps://ldap.example.com:636"
bind_dn: "cn=elasticsearch,ou=service-accounts,dc=example,dc=com"
bind_password: "ServiceAccountPassword123!"
user_search:
base_dn: "ou=users,dc=example,dc=com"
filter: "(cn={0})"
attribute: cn
group_search:
base_dn: "ou=groups,dc=example,dc=com"
filter: "(member={0})"
unmapped_groups_as_roles: false
ssl.verification_mode: certificate
ssl.certificate_authorities: ["/etc/elasticsearch/certs/ca.crt"]
cache.ttl: 20m
cache.max_users: 100000
Active Directory specific configuration
xpack.security.authc.realms.ldap.ad1:
order: 1
url: "ldaps://ad.example.com:636"
bind_dn: "elasticsearch@example.com"
bind_password: "ADServicePassword123!"
user_search:
base_dn: "CN=Users,DC=example,DC=com"
filter: "(&(objectClass=user)(sAMAccountName={0}))"
attribute: sAMAccountName
group_search:
base_dn: "CN=Users,DC=example,DC=com"
filter: "(&(objectClass=group)(member={0}))"
unmapped_groups_as_roles: false
ssl.verification_mode: certificate
ssl.certificate_authorities: ["/etc/elasticsearch/certs/ad-ca.crt"]
cache.ttl: 20m
cache.max_users: 100000
Download and configure SSL certificates
Download SSL certificates from your LDAP servers to enable secure connections. Create the certificate directory and set proper permissions.
sudo mkdir -p /etc/elasticsearch/certs
sudo chown elasticsearch:elasticsearch /etc/elasticsearch/certs
sudo chmod 750 /etc/elasticsearch/certs
Download certificates from your LDAP servers:
# For standard LDAP server
echo -n | openssl s_client -connect ldap.example.com:636 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee /etc/elasticsearch/certs/ca.crt
For Active Directory server
echo -n | openssl s_client -connect ad.example.com:636 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee /etc/elasticsearch/certs/ad-ca.crt
Set proper ownership and permissions
sudo chown elasticsearch:elasticsearch /etc/elasticsearch/certs/*.crt
sudo chmod 644 /etc/elasticsearch/certs/*.crt
Create role mapping configuration
Map LDAP groups to Elasticsearch roles to implement role-based access control (RBAC). This defines what permissions users from each LDAP group will have.
# Map LDAP groups to Elasticsearch roles
superuser:
- "CN=Elasticsearch-Admins,OU=Groups,DC=example,DC=com"
- "cn=elasticsearch-admins,ou=groups,dc=example,dc=com"
kibana_admin:
- "CN=Kibana-Admins,OU=Groups,DC=example,DC=com"
- "cn=kibana-admins,ou=groups,dc=example,dc=com"
kibana_user:
- "CN=Kibana-Users,OU=Groups,DC=example,DC=com"
- "cn=kibana-users,ou=groups,dc=example,dc=com"
logstash_writer:
- "CN=Logstash-Writers,OU=Groups,DC=example,DC=com"
- "cn=logstash-writers,ou=groups,dc=example,dc=com"
reading_user:
- "CN=Elasticsearch-Readers,OU=Groups,DC=example,DC=com"
- "cn=elasticsearch-readers,ou=groups,dc=example,dc=com"
Custom roles for specific indices
log_reader:
- "CN=Log-Analysts,OU=Groups,DC=example,DC=com"
- "cn=log-analysts,ou=groups,dc=example,dc=com"
metrics_reader:
- "CN=Metrics-Team,OU=Groups,DC=example,DC=com"
- "cn=metrics-team,ou=groups,dc=example,dc=com"
Define custom roles with specific permissions
Create custom roles that define specific permissions for different user groups. This provides fine-grained access control over indices and operations.
curl -X POST "localhost:9200/_security/role/log_reader" -H 'Content-Type: application/json' -u elastic -d'
{
"cluster": ["monitor"],
"indices": [
{
"names": ["logs-", "filebeat-"],
"privileges": ["read", "view_index_metadata"]
}
]
}'
curl -X POST "localhost:9200/_security/role/metrics_reader" -H 'Content-Type: application/json' -u elastic -d'
{
"cluster": ["monitor"],
"indices": [
{
"names": ["metrics-", "metricbeat-"],
"privileges": ["read", "view_index_metadata"]
}
]
}'
curl -X POST "localhost:9200/_security/role/reading_user" -H 'Content-Type: application/json' -u elastic -d'
{
"cluster": ["monitor"],
"indices": [
{
"names": ["*"],
"privileges": ["read", "view_index_metadata"]
}
]
}'
Restart Elasticsearch and test configuration
Restart Elasticsearch to apply the LDAP configuration and verify that the service starts correctly with the new authentication settings.
sudo systemctl restart elasticsearch
sudo systemctl status elasticsearch
Check Elasticsearch logs for any configuration errors:
sudo tail -f /var/log/elasticsearch/production-cluster.log
Test LDAP authentication
Test authentication using LDAP credentials to verify the configuration is working correctly.
# Test authentication with LDAP user
curl -X GET "localhost:9200/_security/_authenticate" -u ldapuser:ldappassword
Test role mapping
curl -X GET "localhost:9200/_security/user/_has_privileges" -H 'Content-Type: application/json' -u ldapuser:ldappassword -d'
{
"cluster": ["monitor"],
"index": [
{
"names": ["logs-*"],
"privileges": ["read"]
}
]
}'
List current user privileges
curl -X GET "localhost:9200/_security/_authenticate" -u ldapuser:ldappassword
Verify your setup
Confirm that LDAP authentication is working correctly and users can access Elasticsearch with their directory credentials.
# Check Elasticsearch cluster health
curl -X GET "localhost:9200/_cluster/health" -u elastic
Verify LDAP realm is active
curl -X GET "localhost:9200/_security/_authenticate" -u elastic
Test LDAP user authentication
curl -X GET "localhost:9200/_security/_authenticate" -u your-ldap-username:your-ldap-password
Check role mappings
curl -X GET "localhost:9200/_security/role_mapping" -u elastic
Verify user can access permitted indices
curl -X GET "localhost:9200/logs-*/_search?size=1" -u ldap-user:ldap-password
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Authentication fails with LDAP users | Wrong bind DN or search base | Use ldapsearch to test: ldapsearch -H ldaps://ldap.example.com:636 -D "bind_dn" -W -b "base_dn" "(cn=testuser)" |
| SSL/TLS connection errors | Missing or invalid SSL certificates | Verify certificate: openssl x509 -in /etc/elasticsearch/certs/ca.crt -text -noout |
| Users have no roles assigned | Group mappings don't match LDAP groups | Check user's groups: curl -X GET "localhost:9200/_security/_authenticate" -u ldap-user |
| Elasticsearch won't start after config changes | YAML syntax errors in configuration | Check logs: sudo journalctl -u elasticsearch -n 50 |
| LDAP authentication very slow | DNS resolution issues or network latency | Add IP addresses to /etc/hosts or increase cache TTL in config |
| Permission denied accessing certificate files | Wrong file ownership or permissions | Fix ownership: sudo chown elasticsearch:elasticsearch /etc/elasticsearch/certs/* |
Next steps
- Setup centralized log aggregation with Elasticsearch 8, Logstash 8, and Kibana 8 (ELK Stack)
- Configure Elasticsearch 8 cluster with multiple nodes for high availability and scalability
- Configure Kibana LDAP authentication and RBAC with Active Directory
- Implement Elasticsearch index lifecycle management and retention policies
- Setup Elasticsearch SSL/TLS encryption and advanced security hardening
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Global variables
LDAP_URL=""
BIND_DN=""
USER_BASE_DN=""
GROUP_BASE_DN=""
DOMAIN=""
# Usage message
usage() {
echo "Usage: $0 --ldap-url <ldap://domain.com> --bind-dn <cn=bind,dc=domain,dc=com> --user-base-dn <ou=users,dc=domain,dc=com> --group-base-dn <ou=groups,dc=domain,dc=com> --domain <domain.com>"
echo ""
echo "Example: $0 --ldap-url ldap://ad.company.com --bind-dn 'cn=elasticsearch,cn=Users,dc=company,dc=com' --user-base-dn 'ou=Users,dc=company,dc=com' --group-base-dn 'ou=Groups,dc=company,dc=com' --domain company.com"
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--ldap-url)
LDAP_URL="$2"
shift 2
;;
--bind-dn)
BIND_DN="$2"
shift 2
;;
--user-base-dn)
USER_BASE_DN="$2"
shift 2
;;
--group-base-dn)
GROUP_BASE_DN="$2"
shift 2
;;
--domain)
DOMAIN="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
usage
;;
esac
done
# Validate required arguments
if [[ -z "$LDAP_URL" || -z "$BIND_DN" || -z "$USER_BASE_DN" || -z "$GROUP_BASE_DN" || -z "$DOMAIN" ]]; then
echo -e "${RED}All arguments are required${NC}"
usage
fi
# Cleanup function
cleanup() {
echo -e "${RED}Installation failed. Cleaning up...${NC}"
systemctl stop elasticsearch 2>/dev/null || true
if [[ "$PKG_MGR" == "apt" ]]; then
apt remove -y elasticsearch 2>/dev/null || true
else
$PKG_INSTALL remove elasticsearch 2>/dev/null || true
fi
}
trap cleanup ERR
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
echo -e "${GREEN}[1/8] Detecting distribution...${NC}"
# Auto-detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
JAVA_PKG="openjdk-11-jdk"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
JAVA_PKG="java-11-openjdk-devel"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
JAVA_PKG="java-11-openjdk-devel"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
echo -e "${GREEN}Detected: $PRETTY_NAME (Package manager: $PKG_MGR)${NC}"
echo -e "${GREEN}[2/8] Updating system packages...${NC}"
$PKG_UPDATE
echo -e "${GREEN}[3/8] Installing Java and dependencies...${NC}"
$PKG_INSTALL $JAVA_PKG curl wget gnupg
echo -e "${GREEN}[4/8] Adding Elasticsearch repository...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list
apt update
else
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo << 'EOF'
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF
fi
echo -e "${GREEN}[5/8] Installing Elasticsearch...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL elasticsearch
else
$PKG_INSTALL --enablerepo=elasticsearch elasticsearch
fi
echo -e "${GREEN}[6/8] Configuring Elasticsearch LDAP authentication...${NC}"
# Backup original config
cp /etc/elasticsearch/elasticsearch.yml /etc/elasticsearch/elasticsearch.yml.backup
# Configure Elasticsearch with LDAP
cat >> /etc/elasticsearch/elasticsearch.yml << EOF
# LDAP Authentication Configuration
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.authc.realms.ldap.ldap1:
order: 0
url: "$LDAP_URL"
bind_dn: "$BIND_DN"
user_search:
base_dn: "$USER_BASE_DN"
filter: "(cn={0})"
group_search:
base_dn: "$GROUP_BASE_DN"
filter: "(member={0})"
files:
role_mapping: "/etc/elasticsearch/role_mapping.yml"
unmapped_groups_as_roles: false
EOF
# Create role mapping file
cat > /etc/elasticsearch/role_mapping.yml << EOF
superuser:
- "cn=elasticsearch_admin,${GROUP_BASE_DN}"
- "cn=domain admins,${GROUP_BASE_DN}"
kibana_admin:
- "cn=elasticsearch_kibana,${GROUP_BASE_DN}"
monitoring_user:
- "cn=elasticsearch_monitoring,${GROUP_BASE_DN}"
viewer:
- "cn=elasticsearch_read,${GROUP_BASE_DN}"
EOF
# Set proper permissions
chown root:elasticsearch /etc/elasticsearch/elasticsearch.yml
chown root:elasticsearch /etc/elasticsearch/role_mapping.yml
chmod 660 /etc/elasticsearch/elasticsearch.yml
chmod 660 /etc/elasticsearch/role_mapping.yml
echo -e "${GREEN}[7/8] Starting and enabling Elasticsearch...${NC}"
systemctl daemon-reload
systemctl enable elasticsearch
systemctl start elasticsearch
# Wait for Elasticsearch to start
echo -e "${YELLOW}Waiting for Elasticsearch to start...${NC}"
for i in {1..30}; do
if curl -s http://localhost:9200 >/dev/null 2>&1; then
break
fi
sleep 2
if [[ $i -eq 30 ]]; then
echo -e "${RED}Elasticsearch failed to start within 60 seconds${NC}"
exit 1
fi
done
echo -e "${GREEN}[8/8] Configuring firewall...${NC}"
if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "Status: active"; then
ufw allow 9200/tcp
ufw allow 9300/tcp
elif command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active firewalld >/dev/null 2>&1; then
firewall-cmd --permanent --add-port=9200/tcp
firewall-cmd --permanent --add-port=9300/tcp
firewall-cmd --reload
fi
echo -e "${GREEN}Installation completed successfully!${NC}"
echo ""
echo -e "${YELLOW}Important notes:${NC}"
echo "1. Set the bind user password in the keystore:"
echo " sudo /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.authc.realms.ldap.ldap1.secure_bind_password"
echo ""
echo "2. Create the following groups in your LDAP/AD:"
echo " - elasticsearch_admin (full access)"
echo " - elasticsearch_kibana (Kibana access)"
echo " - elasticsearch_monitoring (monitoring access)"
echo " - elasticsearch_read (read-only access)"
echo ""
echo "3. Restart Elasticsearch after setting the password:"
echo " sudo systemctl restart elasticsearch"
echo ""
echo "4. Test the configuration:"
echo " curl -u username:password http://localhost:9200/_cluster/health"
echo ""
echo "Configuration files:"
echo "- Main config: /etc/elasticsearch/elasticsearch.yml"
echo "- Role mapping: /etc/elasticsearch/role_mapping.yml"
echo "- Logs: /var/log/elasticsearch/"
Review the script before running. Execute with: bash install.sh