Set up secure Kibana authentication using Active Directory LDAP with role-based access control to manage user permissions and streamline enterprise login workflows. This tutorial covers Elasticsearch security configuration, LDAP realm setup, and user role mappings.
Prerequisites
- Active Directory server access
- Administrative privileges
- Basic understanding of LDAP concepts
- Elasticsearch 8 cluster
What this solves
This tutorial helps you integrate Kibana with Active Directory LDAP authentication and implement role-based access control (RBAC). You need this when managing enterprise Kibana deployments where users must authenticate against existing AD infrastructure and have different permission levels based on their organizational roles.
Prerequisites
Before starting this configuration, ensure you have a working Elasticsearch 8 cluster with X-Pack security enabled. If you haven't set this up yet, follow our Elasticsearch 8 SSL/TLS encryption and security hardening guide.
Step-by-step configuration
Install Elasticsearch and Kibana packages
Start by installing the required Elastic Stack components with X-Pack security features.
wget -qO - 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 kibana
Configure Elasticsearch security settings
Enable X-Pack security and configure the basic security settings in Elasticsearch.
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
cluster.initial_master_nodes: ["node-1"]
http.host: 0.0.0.0
Generate SSL certificates and setup cluster security
Create the necessary SSL certificates and initialize the Elasticsearch security configuration.
sudo /usr/share/elasticsearch/bin/elasticsearch-certutil ca --silent --pem -out /tmp/ca.zip
sudo unzip /tmp/ca.zip -d /tmp/
sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --pem --ca-cert /tmp/ca/ca.crt --ca-key /tmp/ca/ca.key -out /tmp/certs.zip
sudo unzip /tmp/certs.zip -d /tmp/
sudo mkdir -p /etc/elasticsearch/certs
sudo cp /tmp/ca/ca.crt /tmp/instance/instance.crt /tmp/instance/instance.key /etc/elasticsearch/certs/
sudo /usr/share/elasticsearch/bin/elasticsearch-keystore create
sudo /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
sudo /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
sudo chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs
sudo chmod 600 /etc/elasticsearch/certs/*
Start Elasticsearch and set built-in user passwords
Enable and start Elasticsearch, then configure passwords for the built-in users.
sudo systemctl enable --now elasticsearch
sudo systemctl status elasticsearch
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
Configure LDAP realm in Elasticsearch
Add the LDAP realm configuration to enable Active Directory authentication.
xpack.security.authc.realms.ldap.ldap1:
order: 0
url: "ldaps://dc1.example.com:636"
bind_dn: "CN=kibana-service,OU=Service Accounts,DC=example,DC=com"
user_search:
base_dn: "OU=Users,DC=example,DC=com"
filter: "(&(objectClass=user)(sAMAccountName={0}))"
group_search:
base_dn: "OU=Groups,DC=example,DC=com"
filter: "(&(objectClass=group)(member={0}))"
ssl:
verification_mode: certificate
certificate_authorities: ["/etc/elasticsearch/certs/ca.crt"]
files:
role_mapping: "/etc/elasticsearch/role_mapping.yml"
Add LDAP bind password to Elasticsearch keystore
Securely store the LDAP service account password in the Elasticsearch keystore.
sudo /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.authc.realms.ldap.ldap1.secure_bind_password
sudo systemctl restart elasticsearch
Create role mappings for LDAP groups
Define how Active Directory groups map to Elasticsearch roles for proper access control.
kibana_admin:
- "CN=Kibana-Admins,OU=Groups,DC=example,DC=com"
- "CN=IT-Administrators,OU=Groups,DC=example,DC=com"
kibana_user:
- "CN=Kibana-Users,OU=Groups,DC=example,DC=com"
- "CN=Analytics-Team,OU=Groups,DC=example,DC=com"
logstash_writer:
- "CN=Logstash-Writers,OU=Groups,DC=example,DC=com"
monitoring_user:
- "CN=Monitoring-Team,OU=Groups,DC=example,DC=com"
reporting_user:
- "CN=Report-Viewers,OU=Groups,DC=example,DC=com"
Create custom Elasticsearch roles
Define specific roles with appropriate permissions for different user types.
curl -X POST "localhost:9200/_security/role/kibana_user" -u elastic -H "Content-Type: application/json" -d '
{
"cluster": [],
"indices": [
{
"names": [ "logstash-", "filebeat-", "metricbeat-*" ],
"privileges": [ "read", "view_index_metadata" ]
},
{
"names": [ ".kibana*" ],
"privileges": [ "manage", "read", "index", "delete" ]
}
]
}'
curl -X POST "localhost:9200/_security/role/monitoring_user" -u elastic -H "Content-Type: application/json" -d '
{
"cluster": [ "monitor" ],
"indices": [
{
"names": [ ".monitoring-*" ],
"privileges": [ "read", "view_index_metadata" ]
}
]
}'
Configure Kibana for LDAP authentication
Set up Kibana to use Elasticsearch security and enable LDAP authentication.
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.ssl.certificateAuthorities: ["/etc/elasticsearch/certs/ca.crt"]
elasticsearch.ssl.verificationMode: certificate
xpack.security.enabled: true
xpack.security.encryptionKey: "something_at_least_32_characters_long_for_session_encryption"
xpack.security.sessionTimeout: 600000
server.ssl.enabled: true
server.ssl.certificate: "/etc/kibana/certs/kibana.crt"
server.ssl.key: "/etc/kibana/certs/kibana.key"
Set Kibana system user password
Configure the Kibana system password in the Kibana keystore for secure communication with Elasticsearch.
sudo /usr/share/kibana/bin/kibana-keystore create
sudo /usr/share/kibana/bin/kibana-keystore add elasticsearch.password
sudo chown -R kibana:kibana /etc/kibana/kibana.keystore
Generate Kibana SSL certificates
Create SSL certificates for Kibana web interface encryption.
sudo mkdir -p /etc/kibana/certs
sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --pem --ca-cert /tmp/ca/ca.crt --ca-key /tmp/ca/ca.key --dns localhost --dns $(hostname) --ip 127.0.0.1 --ip $(hostname -I | awk '{print $1}') -out /tmp/kibana-certs.zip
sudo unzip /tmp/kibana-certs.zip -d /tmp/
sudo cp /tmp/instance/instance.crt /etc/kibana/certs/kibana.crt
sudo cp /tmp/instance/instance.key /etc/kibana/certs/kibana.key
sudo cp /tmp/ca/ca.crt /etc/kibana/certs/ca.crt
sudo chown -R kibana:kibana /etc/kibana/certs
sudo chmod 600 /etc/kibana/certs/*
Configure space-based access control
Set up Kibana spaces for better organization and access control across different teams.
curl -X POST "localhost:5601/api/spaces/space" -u elastic -H "Content-Type: application/json" -H "kbn-xsrf: true" -d '
{
"id": "analytics",
"name": "Analytics Team",
"description": "Space for analytics team dashboards and visualizations",
"color": "#54B399",
"initials": "AT"
}'
curl -X POST "localhost:5601/api/spaces/space" -u elastic -H "Content-Type: application/json" -H "kbn-xsrf: true" -d '
{
"id": "security",
"name": "Security Operations",
"description": "Space for security monitoring and incident response",
"color": "#D36086",
"initials": "SO"
}'
Start and enable Kibana service
Enable Kibana to start automatically and verify the service is running properly.
sudo systemctl enable --now kibana
sudo systemctl status kibana
sudo tail -f /var/log/kibana/kibana.log
Configure firewall rules
Open the necessary ports for Kibana and Elasticsearch communication.
sudo ufw allow 5601/tcp comment "Kibana HTTPS"
sudo ufw allow 9200/tcp comment "Elasticsearch API"
sudo ufw reload
Configure user role assignments
Assign roles to specific users
Configure individual user role assignments for users who need specific permissions beyond their group membership.
curl -X POST "localhost:9200/_security/role_mapping/individual_admins" -u elastic -H "Content-Type: application/json" -d '
{
"roles": [ "kibana_admin", "superuser" ],
"rules": {
"any": [
{ "field": { "username": "jsmith" } },
{ "field": { "username": "admin@example.com" } }
]
},
"enabled": true
}'
Create department-specific index patterns
Set up index pattern permissions to restrict data access based on user roles.
curl -X POST "localhost:9200/_security/role/hr_analyst" -u elastic -H "Content-Type: application/json" -d '
{
"cluster": [],
"indices": [
{
"names": [ "hr-logs-", "employee-metrics-" ],
"privileges": [ "read", "view_index_metadata" ],
"query": {
"term": {
"department": "hr"
}
}
}
]
}'
curl -X POST "localhost:9200/_security/role/finance_viewer" -u elastic -H "Content-Type: application/json" -d '
{
"cluster": [],
"indices": [
{
"names": [ "financial-", "audit-logs-" ],
"privileges": [ "read" ],
"query": {
"bool": {
"must": [
{ "range": { "@timestamp": { "gte": "now-90d" } } }
]
}
}
}
]
}'
Test LDAP authentication
Test LDAP connectivity
Verify that Elasticsearch can successfully connect to your Active Directory server.
curl -X POST "localhost:9200/_security/user/_authenticate" -u testuser@example.com
curl -X GET "localhost:9200/_security/_authenticate" -u elastic
Verify role mappings
Check that LDAP groups are correctly mapped to Elasticsearch roles.
curl -X GET "localhost:9200/_security/role_mapping" -u elastic
curl -X GET "localhost:9200/_security/role_mapping/kibana_admin" -u elastic
Verify your setup
Test your LDAP authentication configuration by accessing Kibana and verifying user permissions.
sudo systemctl status elasticsearch
sudo systemctl status kibana
curl -k -X GET "https://localhost:9200/_cluster/health" -u elastic
curl -k -X GET "https://localhost:5601/api/status" -u elastic
tail -n 50 /var/log/elasticsearch/elasticsearch.log | grep -i ldap
Open your browser and navigate to https://your-server-ip:5601. You should see the Kibana login page where users can authenticate with their Active Directory credentials.
Troubleshoot LDAP authentication issues
Enable debug logging
Add debug logging to troubleshoot LDAP authentication problems.
curl -X PUT "localhost:9200/_cluster/settings" -u elastic -H "Content-Type: application/json" -d '
{
"persistent": {
"logger.org.elasticsearch.xpack.security.authc.ldap": "DEBUG",
"logger.org.elasticsearch.xpack.security.authc.Realms": "DEBUG"
}
}'
sudo tail -f /var/log/elasticsearch/elasticsearch.log | grep -i ldap
Test LDAP bind manually
Use ldapsearch to verify your LDAP connection parameters outside of Elasticsearch.
sudo apt install -y ldap-utils
ldapsearch -x -H ldaps://dc1.example.com:636 -D "CN=kibana-service,OU=Service Accounts,DC=example,DC=com" -W -b "OU=Users,DC=example,DC=com" "(&(objectClass=user)(sAMAccountName=testuser))"
ldapsearch -x -H ldaps://dc1.example.com:636 -D "CN=kibana-service,OU=Service Accounts,DC=example,DC=com" -W -b "OU=Groups,DC=example,DC=com" "(&(objectClass=group)(member=CN=testuser,OU=Users,DC=example,DC=com))"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| LDAP authentication fails | Incorrect bind DN or password | Verify service account credentials with ldapsearch |
| Users can't access Kibana | Role mapping not configured | Check role mappings with curl -X GET "localhost:9200/_security/role_mapping" |
| SSL certificate errors | Missing or invalid CA certificate | Import AD CA certificate to /etc/elasticsearch/certs/ |
| Elasticsearch startup fails | Keystore permissions incorrect | sudo chown elasticsearch:elasticsearch /etc/elasticsearch/elasticsearch.keystore |
| Kibana can't connect to Elasticsearch | Wrong kibana_system password | Reset password with curl -X POST "localhost:9200/_security/user/kibana_system/_password" |
| Groups not found in LDAP | Incorrect group search base | Verify group DN with ldapsearch and update group_search.base_dn |
Next steps
- Set up centralized log aggregation with ELK Stack to start collecting and analyzing logs
- Configure advanced Kibana security with field-level restrictions for granular data access control
- Set up Kibana alerting and monitoring with Elasticsearch Watcher for proactive monitoring
- Configure Elasticsearch cross-cluster replication for disaster recovery
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'
# Logging functions
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Usage message
usage() {
echo "Usage: $0 <ldap_server> <bind_dn> <bind_password> <search_base>"
echo "Example: $0 ldap.company.com 'CN=kibana-svc,OU=Service Accounts,DC=company,DC=com' 'password123' 'OU=Users,DC=company,DC=com'"
exit 1
}
# Check arguments
if [ $# -ne 4 ]; then
usage
fi
LDAP_SERVER="$1"
BIND_DN="$2"
BIND_PASSWORD="$3"
SEARCH_BASE="$4"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
log_error "This script must be run as root"
exit 1
fi
# Cleanup function
cleanup() {
log_error "Script failed. Check logs above for details."
systemctl stop elasticsearch kibana 2>/dev/null || true
}
trap cleanup ERR
# 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"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf makecache"
;;
fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf makecache"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum makecache"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution"
exit 1
fi
log_info "Detected distribution: $ID"
# Check required tools
echo "[1/8] Checking prerequisites..."
command -v curl >/dev/null 2>&1 || { $PKG_INSTALL curl; }
command -v gpg >/dev/null 2>&1 || { $PKG_INSTALL gnupg; }
# Install Elastic repository
echo "[2/8] Adding Elastic repository..."
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
$PKG_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=1
autorefresh=1
type=rpm-md
EOF
$PKG_UPDATE
fi
# Install Elasticsearch and Kibana
echo "[3/8] Installing Elasticsearch and Kibana..."
$PKG_INSTALL elasticsearch kibana
# Configure Elasticsearch for LDAP
echo "[4/8] Configuring Elasticsearch for LDAP authentication..."
ES_CONFIG="/etc/elasticsearch/elasticsearch.yml"
# Backup original config
cp "$ES_CONFIG" "${ES_CONFIG}.backup"
# Add LDAP realm configuration
cat >> "$ES_CONFIG" << EOF
# LDAP Authentication Configuration
xpack.security.enabled: true
xpack.security.authc.realms.ldap.ldap1:
order: 1
url: "ldaps://${LDAP_SERVER}:636"
bind_dn: "${BIND_DN}"
bind_password: "${BIND_PASSWORD}"
user_search:
base_dn: "${SEARCH_BASE}"
filter: "(sAMAccountName={0})"
group_search:
base_dn: "${SEARCH_BASE}"
filter: "(objectClass=group)"
unmapped_groups_as_roles: false
ssl:
verification_mode: certificate
EOF
# Set proper permissions
chown root:elasticsearch "$ES_CONFIG"
chmod 660 "$ES_CONFIG"
# Configure Kibana
echo "[5/8] Configuring Kibana..."
KIBANA_CONFIG="/etc/kibana/kibana.yml"
cp "$KIBANA_CONFIG" "${KIBANA_CONFIG}.backup"
cat >> "$KIBANA_CONFIG" << 'EOF'
# Kibana LDAP Configuration
server.host: "0.0.0.0"
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.ssl.verificationMode: certificate
xpack.security.enabled: true
xpack.security.encryptionKey: "something_at_least_32_characters_long"
xpack.security.session.idleTimeout: "1h"
xpack.security.session.lifespan: "30d"
EOF
chown root:kibana "$KIBANA_CONFIG"
chmod 660 "$KIBANA_CONFIG"
# Start and enable services
echo "[6/8] Starting Elasticsearch and Kibana services..."
systemctl daemon-reload
systemctl enable elasticsearch kibana
systemctl start elasticsearch
# Wait for Elasticsearch to start
echo "Waiting for Elasticsearch to start..."
timeout=60
while [ $timeout -gt 0 ]; do
if curl -s http://localhost:9200 >/dev/null 2>&1; then
break
fi
sleep 2
timeout=$((timeout - 2))
done
if [ $timeout -le 0 ]; then
log_error "Elasticsearch failed to start"
exit 1
fi
# Reset elastic password and get kibana_system password
echo "[7/8] Setting up Elasticsearch security..."
ELASTIC_PASSWORD=$(openssl rand -base64 32)
echo "y" | /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -s
/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic --batch > /tmp/elastic_password
ELASTIC_PASSWORD=$(grep "New value:" /tmp/elastic_password | awk '{print $3}')
KIBANA_PASSWORD=$(/usr/share/elasticsearch/bin/elasticsearch-reset-password -u kibana_system --batch | grep "New value:" | awk '{print $3}')
# Update Kibana config with password
sed -i "s/elasticsearch.username: \"kibana_system\"/elasticsearch.username: \"kibana_system\"\nelasticsearch.password: \"${KIBANA_PASSWORD}\"/" "$KIBANA_CONFIG"
# Configure firewall
if command -v ufw >/dev/null 2>&1; then
ufw allow 5601/tcp
ufw allow 9200/tcp
elif command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-port=5601/tcp
firewall-cmd --permanent --add-port=9200/tcp
firewall-cmd --reload
fi
# Start Kibana
systemctl start kibana
# Verification
echo "[8/8] Verifying installation..."
sleep 10
if systemctl is-active --quiet elasticsearch; then
log_info "Elasticsearch is running"
else
log_error "Elasticsearch is not running"
exit 1
fi
if systemctl is-active --quiet kibana; then
log_info "Kibana is running"
else
log_error "Kibana is not running"
exit 1
fi
# Clean up temporary files
rm -f /tmp/elastic_password
log_info "Installation completed successfully!"
log_info "Elasticsearch elastic user password: $ELASTIC_PASSWORD"
log_info "Kibana will be available at: http://$(hostname -I | awk '{print $1}'):5601"
log_info "Configure role mappings in Elasticsearch to complete LDAP integration"
Review the script before running. Execute with: bash install.sh