Configure Kibana 8 advanced security with field-level restrictions and role-based access control

Advanced 45 min Apr 12, 2026 255 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Implement comprehensive security controls in Kibana 8 with field-level restrictions, document-level security, and role-based access control for production Elasticsearch deployments.

Prerequisites

  • Elasticsearch 8 installed and running
  • Kibana 8 installed
  • Administrative access to the server
  • Basic understanding of Elasticsearch and Kibana

What this solves

Kibana 8 advanced security enables granular access control for Elasticsearch data through field-level restrictions, document-level security, and role-based access control (RBAC). This configuration prevents unauthorized users from viewing sensitive fields, restricts access to specific documents based on queries, and manages user permissions through customizable roles and spaces.

Step-by-step configuration

Install required packages

Update your system and install curl for API interactions with Elasticsearch.

sudo apt update
sudo apt install -y curl jq
sudo dnf update -y
sudo dnf install -y curl jq

Configure Elasticsearch security foundation

Enable security features in Elasticsearch configuration to support advanced authentication and authorization.

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
xpack.license.self_generated.type: basic

Restart Elasticsearch service

Apply the security configuration changes by restarting Elasticsearch.

sudo systemctl restart elasticsearch
sudo systemctl status elasticsearch

Set up built-in user passwords

Generate passwords for Elasticsearch built-in users including kibana_system for Kibana authentication.

sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Note: Save all generated passwords securely. You'll need the kibana_system password for Kibana configuration.

Configure Kibana authentication

Set up Kibana to authenticate with Elasticsearch using the kibana_system user credentials.

server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["https://localhost:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "YOUR_KIBANA_SYSTEM_PASSWORD"
elasticsearch.ssl.certificateAuthorities: ["/etc/elasticsearch/certs/http_ca.crt"]
xpack.security.encryptionKey: "something_at_least_32_characters_long"
xpack.encryptedSavedObjects.encryptionKey: "something_at_least_32_characters_long"
xpack.reporting.encryptionKey: "something_at_least_32_characters_long"

Copy Elasticsearch CA certificate

Copy the Elasticsearch CA certificate to Kibana's accessible location for SSL verification.

sudo cp /etc/elasticsearch/certs/http_ca.crt /etc/kibana/
sudo chown kibana:kibana /etc/kibana/http_ca.crt
sudo chmod 644 /etc/kibana/http_ca.crt

Start Kibana service

Enable and start Kibana with the security configuration.

sudo systemctl enable --now kibana
sudo systemctl status kibana

Create custom roles with field-level security

Define a role that restricts access to specific fields in your indices. This role denies access to sensitive fields like SSN and credit card numbers.

curl -X PUT "https://localhost:9200/_security/role/sales_analyst" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "cluster": [],
    "indices": [
      {
        "names": ["sales-", "customer-"],
        "privileges": ["read"],
        "field_security": {
          "except": ["ssn", "credit_card", "salary", "personal_info.*"]
        },
        "query": {
          "bool": {
            "must": {
              "range": {
                "@timestamp": {
                  "gte": "now-90d"
                }
              }
            }
          }
        }
      }
    ],
    "applications": [],
    "run_as": [],
    "metadata": {
      "description": "Sales analyst with field restrictions and 90-day data access"
    },
    "transient_metadata": {
      "enabled": true
    }
  }'

Create role with document-level security

Configure a role that restricts access to documents based on a query filter, limiting users to see only data from their region.

curl -X PUT "https://localhost:9200/_security/role/regional_manager" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "cluster": [],
    "indices": [
      {
        "names": ["sales-", "orders-"],
        "privileges": ["read", "view_index_metadata"],
        "field_security": {
          "grant": ["*"],
          "except": ["internal_notes", "cost_price"]
        },
        "query": {
          "template": {
            "source": {
              "term": {
                "region.keyword": "{{#toJson}}_user.metadata.region{{/toJson}}"
              }
            }
          }
        }
      }
    ],
    "metadata": {
      "description": "Regional manager with territory-based document filtering"
    }
  }'

Create read-only analyst role

Set up a basic read-only role for analysts with access to specific index patterns and Kibana features.

curl -X PUT "https://localhost:9200/_security/role/data_analyst" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "cluster": ["monitor"],
    "indices": [
      {
        "names": ["logs-", "metrics-"],
        "privileges": ["read", "view_index_metadata"]
      }
    ],
    "applications": [
      {
        "application": "kibana-.kibana",
        "privileges": ["feature_discover.read", "feature_visualize.read", "feature_dashboard.read"],
        "resources": ["*"]
      }
    ]
  }'

Create users with custom roles

Create users and assign them the custom roles with field and document-level restrictions.

# Create sales analyst user
curl -X POST "https://localhost:9200/_security/user/jane_analyst" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "password": "SecurePass123!",
    "roles": ["sales_analyst", "kibana_user"],
    "full_name": "Jane Smith",
    "email": "jane.smith@example.com",
    "metadata": {
      "department": "Sales Analytics"
    }
  }'

Create regional manager user

curl -X POST "https://localhost:9200/_security/user/bob_manager" \ -H "Content-Type: application/json" \ -u "elastic:YOUR_ELASTIC_PASSWORD" \ --cacert /etc/elasticsearch/certs/http_ca.crt \ -d '{ "password": "SecurePass456!", "roles": ["regional_manager", "kibana_user"], "full_name": "Bob Johnson", "email": "bob.johnson@example.com", "metadata": { "department": "Regional Management", "region": "west" } }'

Configure Kibana spaces for role isolation

Create dedicated Kibana spaces for different user groups to provide additional isolation.

curl -X POST "http://localhost:5601/api/spaces/space" \
  -H "Content-Type: application/json" \
  -H "kbn-xsrf: true" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  -d '{
    "id": "sales-analytics",
    "name": "Sales Analytics",
    "description": "Space for sales team analysis and reporting",
    "color": "#0078A0",
    "initials": "SA",
    "disabledFeatures": ["ml", "apm", "infrastructure"],
    "imageUrl": ""
  }'

curl -X POST "http://localhost:5601/api/spaces/space" \
  -H "Content-Type: application/json" \
  -H "kbn-xsrf: true" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  -d '{
    "id": "operations",
    "name": "Operations",
    "description": "Operational monitoring and system metrics",
    "color": "#D36086",
    "initials": "OP",
    "disabledFeatures": ["canvas", "graph"],
    "imageUrl": ""
  }'

Set up API keys for programmatic access

Create API keys with specific privileges for applications that need to access Elasticsearch data programmatically.

curl -X POST "https://localhost:9200/_security/api_key" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "name": "analytics_app_key",
    "expiration": "365d",
    "role_descriptors": {
      "analytics_access": {
        "cluster": ["monitor"],
        "indices": [
          {
            "names": ["analytics-*"],
            "privileges": ["read"],
            "field_security": {
              "except": ["sensitive_data", "pii"]
            }
          }
        ]
      }
    },
    "metadata": {
      "application": "analytics-dashboard",
      "environment": "production"
    }
  }'

Configure role mapping for LDAP integration

Set up role mapping to automatically assign roles based on LDAP group membership for enterprise environments.

curl -X POST "https://localhost:9200/_security/role_mapping/sales_team_mapping" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "roles": ["sales_analyst", "kibana_user"],
    "rules": {
      "field": {
        "groups": "cn=sales,ou=groups,dc=example,dc=com"
      }
    },
    "enabled": true,
    "metadata": {
      "description": "Map LDAP sales group to sales analyst role"
    }
  }'

curl -X POST "https://localhost:9200/_security/role_mapping/manager_mapping" \
  -H "Content-Type: application/json" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "roles": ["regional_manager", "kibana_user"],
    "rules": {
      "all": [
        {
          "field": {
            "groups": "cn=managers,ou=groups,dc=example,dc=com"
          }
        },
        {
          "field": {
            "dn": "*,ou=regional,dc=example,dc=com"
          }
        }
      ]
    },
    "enabled": true
  }'

Test field-level security restrictions

Verify that field-level security is working by testing data access with restricted users.

# Test with sales analyst user (should not see restricted fields)
curl -X GET "https://localhost:9200/sales-*/_search?pretty" \
  -H "Content-Type: application/json" \
  -u "jane_analyst:SecurePass123!" \
  --cacert /etc/elasticsearch/certs/http_ca.crt \
  -d '{
    "query": {
      "match_all": {}
    },
    "size": 5
  }'

Test with full access user (should see all fields)

curl -X GET "https://localhost:9200/sales-*/_search?pretty" \ -H "Content-Type: application/json" \ -u "elastic:YOUR_ELASTIC_PASSWORD" \ --cacert /etc/elasticsearch/certs/http_ca.crt \ -d '{ "query": { "match_all": {} }, "size": 5 }'

Verify your setup

Test your Kibana security configuration and verify that roles and restrictions are working correctly.

# Check Elasticsearch cluster health
curl -X GET "https://localhost:9200/_cluster/health?pretty" \
  -u "elastic:YOUR_ELASTIC_PASSWORD" \
  --cacert /etc/elasticsearch/certs/http_ca.crt

List all security roles

curl -X GET "https://localhost:9200/_security/role?pretty" \ -u "elastic:YOUR_ELASTIC_PASSWORD" \ --cacert /etc/elasticsearch/certs/http_ca.crt

Check Kibana status

curl -X GET "http://localhost:5601/api/status" \ -H "kbn-xsrf: true" \ -u "elastic:YOUR_ELASTIC_PASSWORD"

List created users

curl -X GET "https://localhost:9200/_security/user?pretty" \ -u "elastic:YOUR_ELASTIC_PASSWORD" \ --cacert /etc/elasticsearch/certs/http_ca.crt

Verify API key creation

curl -X GET "https://localhost:9200/_security/api_key?pretty" \ -u "elastic:YOUR_ELASTIC_PASSWORD" \ --cacert /etc/elasticsearch/certs/http_ca.crt

Common issues

Symptom Cause Fix
Kibana shows authentication error Wrong kibana_system password in config Update password in /etc/kibana/kibana.yml and restart Kibana
SSL certificate verification failed Missing or wrong CA certificate path Copy /etc/elasticsearch/certs/http_ca.crt to Kibana directory
User cannot see expected fields Field security restrictions too broad Check role field_security configuration and adjust grant/except arrays
Document-level security not working Query template syntax error Validate JSON query syntax and user metadata mapping
Role mapping not applying LDAP group DN mismatch Verify LDAP configuration and group distinguished names
API key authentication fails Incorrect API key encoding Use base64 encoding: echo -n "id:key" | base64

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.