ELK Stack Güvenlik: TLS ve X-Pack Yapılandırması
Production’da ELK kuruyorsunuz, her şey güzel çalışıyor, loglar akıyor, Kibana açık… Sonra birisi size soruyor: “Bu verilere kimler erişebiliyor?” İşte o an gerçekten düşünmeye başlıyorsunuz. Elasticsearch varsayılan kurulumda kimlik doğrulama yok, TLS yok, her şey açık. Geliştirme ortamı için belki kabul edilebilir, ama production’da bu bir felakete davetiye çıkarmak demek. Bu yazıda ELK Stack’i güvenli hale getirmenin pratik yollarını, yani TLS yapılandırmasını ve X-Pack güvenlik özelliklerini ele alacağız.
Neden ELK Güvenliği Ciddiye Alınmalı
Shodan üzerinde gezindiğinizde binlerce açık Elasticsearch instance’ı görürsünüz. Bunların önemli bir kısmı Türkiye’deki şirketlere ait. Müşteri verileri, uygulama logları, hatta bazen şifreler açıkta. 2019’da bir araştırma yaklaşık 15.000 açık Elasticsearch sunucusunu tespit etmişti ve bu rakam hâlâ endişe verici seviyelerde.
ELK güvenliği temelde üç katmandan oluşuyor:
- Ağ katmanı: TLS ile şifrelenmiş iletişim
- Kimlik doğrulama: X-Pack ile kullanıcı yönetimi
- Yetkilendirme: Role-based access control (RBAC)
Elasticsearch 8.x ile birlikte güvenlik varsayılan olarak etkinleştirildi, ancak 7.x kullanan pek çok production ortamı hâlâ mevcut. Her iki versiyonu da ele alacağız.
Ortam Hazırlığı ve Sertifika Altyapısı
Önce ne ile çalıştığınızı netleştirelim. Tek node’lu bir yapıdan üç node’lu bir cluster’a kadar adımlar aynı, sadece ölçek değişiyor. Ben burada üç node’lu bir yapı üzerinden anlatacağım çünkü production’da genellikle böyle karşılaşıyorsunuz.
Node’larımız şunlar olsun:
- es-node1.internal (192.168.1.10)
- es-node2.internal (192.168.1.11)
- es-node3.internal (192.168.1.12)
- Kibana: kibana.internal (192.168.1.20)
- Logstash: logstash.internal (192.168.1.30)
İlk adım, Elasticsearch’ün kendi CA aracını kullanarak sertifika altyapısı kurmak. elasticsearch-certutil gerçekten kullanışlı bir araç, openssl ile uğraşmak zorunda kalmıyorsunuz.
# Önce instances.yml dosyası oluşturuyoruz
cat > /tmp/instances.yml << 'EOF'
instances:
- name: es-node1
dns:
- es-node1.internal
- localhost
ip:
- 192.168.1.10
- 127.0.0.1
- name: es-node2
dns:
- es-node2.internal
- localhost
ip:
- 192.168.1.11
- 127.0.0.1
- name: es-node3
dns:
- es-node3.internal
- localhost
ip:
- 192.168.1.12
- 127.0.0.1
- name: kibana
dns:
- kibana.internal
ip:
- 192.168.1.20
- name: logstash
dns:
- logstash.internal
ip:
- 192.168.1.30
EOF
# CA oluştur
/usr/share/elasticsearch/bin/elasticsearch-certutil ca
--out /tmp/elastic-ca.p12
--pass "your-ca-password-here"
# Tüm node'lar için sertifika üret
/usr/share/elasticsearch/bin/elasticsearch-certutil cert
--ca /tmp/elastic-ca.p12
--ca-pass "your-ca-password-here"
--in /tmp/instances.yml
--out /tmp/elastic-certificates.zip
--pass ""
Zip’i açtığınızda her instance için ayrı bir p12 dosyası göreceksiniz. Bu dosyaları ilgili sunuculara dağıtmanız gerekiyor.
# Sertifikaları açıp doğru konumlara kopyalayın
cd /tmp && unzip elastic-certificates.zip
# es-node1 için
scp /tmp/es-node1/es-node1.p12 [email protected]:/etc/elasticsearch/certs/
scp /tmp/elastic-ca.p12 [email protected]:/etc/elasticsearch/certs/
# Kibana için PEM formatına dönüştürmek gerekebilir
openssl pkcs12 -in /tmp/kibana/kibana.p12 -nocerts -nodes
-out /etc/kibana/certs/kibana.key
openssl pkcs12 -in /tmp/kibana/kibana.p12 -clcerts -nokeys
-out /etc/kibana/certs/kibana.crt
openssl pkcs12 -in /tmp/elastic-ca.p12 -cacerts -nokeys -chain
-out /etc/kibana/certs/ca.crt
Elasticsearch TLS Yapılandırması
Sertifikalar yerleştirildikten sonra elasticsearch.yml dosyasını güncelleme zamanı. Her node’da bazı değerler farklı olacak, bunu gözden kaçırmayın.
# /etc/elasticsearch/elasticsearch.yml - es-node1 için
cluster.name: production-elk
node.name: es-node1
network.host: 192.168.1.10
http.port: 9200
transport.port: 9300
discovery.seed_hosts:
- 192.168.1.10:9300
- 192.168.1.11:9300
- 192.168.1.12:9300
cluster.initial_master_nodes:
- es-node1
- es-node2
- es-node3
# X-Pack Güvenlik
xpack.security.enabled: true
# Transport katmanı TLS (node-to-node iletişim)
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/es-node1.p12
xpack.security.transport.ssl.truststore.path: certs/elastic-ca.p12
# HTTP katmanı TLS (client-to-node iletişim)
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: certs/es-node1.p12
xpack.security.http.ssl.truststore.path: certs/elastic-ca.p12
Keystore şifrelerini dosyaya düz metin olarak yazmak yerine Elasticsearch’ün güvenli keystore’unu kullanın:
# Şifreleri güvenli keystore'a ekle
/usr/share/elasticsearch/bin/elasticsearch-keystore add
xpack.security.transport.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore add
xpack.security.transport.ssl.truststore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore add
xpack.security.http.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore add
xpack.security.http.ssl.truststore.secure_password
# Servisi yeniden başlat
systemctl restart elasticsearch
# Cluster sağlığını kontrol et
curl -k -u elastic:changeme https://192.168.1.10:9200/_cluster/health?pretty
Built-in Kullanıcı Şifrelerini Ayarlama
Elasticsearch ilk açıldığında built-in kullanıcılar oluşturulur ama şifreleri yoktur. elasticsearch-setup-passwords aracı burada devreye giriyor.
# Otomatik rastgele şifre oluştur (production için önerilir)
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
-u "https://es-node1.internal:9200"
# Ya da interaktif mod ile kendi şifrelerinizi belirleyin
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
-u "https://es-node1.internal:9200"
Bu komut şu kullanıcılar için şifre ister:
- elastic: Süper kullanıcı, günlük işlemler için kullanmayın
- kibana_system: Kibana’nın Elasticsearch’e bağlanması için
- logstash_system: Logstash monitoring için (veri yazmak için değil)
- beats_system: Beats monitoring için
- apm_system: APM server için
- remote_monitoring_user: Metricbeat gibi dış monitoring araçları için
Çıktıyı güvenli bir yere kaydedin. Bir daha göremeyeceksiniz.
Kibana TLS ve Kimlik Doğrulama Yapılandırması
# /etc/kibana/kibana.yml
server.name: kibana
server.host: "0.0.0.0"
server.port: 5601
# Kibana HTTPS
server.ssl.enabled: true
server.ssl.certificate: /etc/kibana/certs/kibana.crt
server.ssl.key: /etc/kibana/certs/kibana.key
# Elasticsearch bağlantısı
elasticsearch.hosts:
- "https://192.168.1.10:9200"
- "https://192.168.1.11:9200"
- "https://192.168.1.12:9200"
elasticsearch.username: "kibana_system"
elasticsearch.password: "kibana-system-password-buraya"
# CA sertifikası
elasticsearch.ssl.certificateAuthorities: ["/etc/kibana/certs/ca.crt"]
elasticsearch.ssl.verificationMode: certificate
# Kibana için encryption key (session yönetimi)
xpack.security.encryptionKey: "en-az-32-karakter-rastgele-bir-deger"
xpack.encryptedSavedObjects.encryptionKey: "baska-bir-32-karakter-deger-buraya"
xpack.reporting.encryptionKey: "ucuncu-bir-32-karakter-deger-buraya"
Encryption key’ler için rastgele değer üretmek kolay:
openssl rand -base64 32
Her çalıştırışta farklı bir değer alırsınız. Bu değerleri bir şifre yöneticisinde saklayın.
Logstash TLS Yapılandırması
Logstash hem Elasticsearch’e yazarken hem de Beats’ten veri alırken TLS kullanmalı. İki ayrı yapılandırma gerekiyor.
# /etc/logstash/conf.d/input-beats.conf
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/logstash/certs/logstash.crt"
ssl_key => "/etc/logstash/certs/logstash.key"
ssl_certificate_authorities => ["/etc/logstash/certs/ca.crt"]
ssl_verify_mode => "force_peer"
}
}
# /etc/logstash/conf.d/output-elasticsearch.conf
output {
elasticsearch {
hosts => [
"https://192.168.1.10:9200",
"https://192.168.1.11:9200",
"https://192.168.1.12:9200"
]
# Logstash için özel kullanıcı (aşağıda oluşturacağız)
user => "logstash_writer"
password => "${LOGSTASH_WRITER_PASSWORD}"
ssl => true
ssl_certificate_verification => true
cacert => "/etc/logstash/certs/ca.crt"
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
}
}
Şifreyi environment variable olarak saklamak için Logstash keystore kullanın:
# Logstash keystore oluştur
/usr/share/logstash/bin/logstash-keystore create
# Şifreyi ekle
/usr/share/logstash/bin/logstash-keystore add LOGSTASH_WRITER_PASSWORD
RBAC ile Kullanıcı ve Rol Yönetimi
Built-in kullanıcıları günlük operasyonlarda kullanmak kötü bir pratik. Amaca özel roller ve kullanıcılar oluşturun. Örneğin Logstash’ın indeks oluşturabilmesi ve veri yazabilmesi için özel bir rol:
# logstash_writer rolü oluştur
curl -X PUT "https://es-node1.internal:9200/_security/role/logstash_writer"
-u elastic:elastic-password
-H "Content-Type: application/json"
-d '{
"cluster": ["manage_index_templates", "monitor", "manage_ilm"],
"indices": [
{
"names": ["logstash-*", "filebeat-*", "metricbeat-*"],
"privileges": ["write", "create", "create_index", "manage", "manage_ilm"]
}
]
}'
# logstash_writer kullanıcısı oluştur
curl -X PUT "https://es-node1.internal:9200/_security/user/logstash_writer"
-u elastic:elastic-password
-H "Content-Type: application/json"
-d '{
"password": "guclu-bir-sifre-buraya",
"roles": ["logstash_writer"],
"full_name": "Logstash Writer Service Account",
"email": "[email protected]"
}'
Geliştirici ekibi için read-only bir rol örneği:
curl -X PUT "https://es-node1.internal:9200/_security/role/dev_readonly"
-u elastic:elastic-password
-H "Content-Type: application/json"
-d '{
"cluster": ["monitor"],
"indices": [
{
"names": ["logstash-*", "filebeat-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["read"],
"resources": ["*"]
}
]
}'
Filebeat TLS Yapılandırması
Logları toplayan agent’lar da güvenli bağlanmalı. Filebeat için:
# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/*.log
- /var/log/app/*.log
output.logstash:
hosts: ["logstash.internal:5044"]
ssl.certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
ssl.certificate: "/etc/filebeat/certs/filebeat.crt"
ssl.key: "/etc/filebeat/certs/filebeat.key"
# Monitoring için (opsiyonel)
monitoring:
enabled: true
elasticsearch:
hosts: ["https://es-node1.internal:9200"]
username: beats_system
password: "${BEATS_SYSTEM_PASSWORD}"
ssl.certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
Sertifika Yenileme Süreci
Sertifikaların süresi dolduğunda panik yaşamamak için yenileme sürecini önceden planlayın. Elasticsearch 8.x ile rolling restart ile online yenileme mümkün.
# Mevcut sertifika bitiş tarihini kontrol et
openssl pkcs12 -in /etc/elasticsearch/certs/es-node1.p12
-nokeys -passin pass: |
openssl x509 -noout -enddate
# Yeni sertifikaları üret (aynı CA ile)
/usr/share/elasticsearch/bin/elasticsearch-certutil cert
--ca /tmp/elastic-ca.p12
--ca-pass "your-ca-password-here"
--in /tmp/instances.yml
--out /tmp/elastic-certificates-renewed.zip
--pass ""
--days 365
# Node'ları rolling restart ile yenile
# Önce cluster'ı yavaşlat
curl -X PUT "https://es-node1.internal:9200/_cluster/settings"
-u elastic:password
-H "Content-Type: application/json"
-d '{"persistent": {"cluster.routing.allocation.enable": "primaries"}}'
# Node'u kapat, sertifikayı değiştir, yeniden başlat
# Cluster yeşile döndükten sonra bir sonraki node'a geç
Güvenlik Denetim Logları
Kimin neye eriştiğini takip etmek compliance açısından kritik. X-Pack audit logging’i etkinleştirin:
# elasticsearch.yml'e ekleyin
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include:
- authentication_success
- authentication_failed
- access_denied
- connection_denied
- anonymous_access_denied
- run_as_denied
- index_template_deleted
- user_deleted
- role_deleted
Audit logları /var/log/elasticsearch/_audit.json konumuna yazılır. Bu logları da ELK’ye alın, tabii farklı bir index’e.
Yaygın Sorunlar ve Çözümleri
Üretimde en çok karşılaştığınız sorunlara bakalım.
Certificate verify failed hatası: En sık görülen sorun. Sertifikayı oluştururken IP veya hostname eksik bırakmışsınızdır. openssl x509 -in sertifika.crt -text -noout | grep -A2 "Subject Alternative" ile SAN’ları kontrol edin.
PKIX path building failed: Java’nın trust store’una CA sertifikasını eklememişsinizdir. Truststore ayarlarını kontrol edin.
connection refused after TLS enabled: elasticsearch.yml’de network.host ayarını kontrol edin. localhost yerine gerçek IP veya 0.0.0.0 olmalı.
Kibana cannot connect to Elasticsearch: kibana.yml’deki elasticsearch.ssl.verificationMode değerini geçici olarak none yapıp hatanın devam edip etmediğini test edin. Sorun sertifikada değilse kullanıcı/şifre kombinasyonunu kontrol edin.
# Hızlı bağlantı testi
curl -v --cacert /etc/kibana/certs/ca.crt
-u kibana_system:kibana-password
"https://es-node1.internal:9200/_cluster/health"
# TLS el sıkışma detayları
openssl s_client -connect es-node1.internal:9200
-CAfile /etc/elasticsearch/certs/ca.crt
Sonuç
ELK güvenliği tek seferlik bir iş değil. Sertifika yenileme takvimi oluşturun, kullanıcı erişimlerini düzenli gözden geçirin, audit loglarını izleyin. X-Pack ile gelen özellikler lisans kısıtlamalarına göre değişiyor; basic lisans ile TLS ve temel kimlik doğrulama kullanabiliyorsunuz, ileri düzey RBAC ve LDAP entegrasyonu için platinum gerekiyor.
Burada anlattıklarım Elasticsearch 7.x ve 8.x için geçerli, ancak bazı konfigürasyon parametreleri versiyona göre farklılık gösterebiliyor. Resmi dökümantasyonu referans alın ama temel yaklaşım değişmiyor: transport TLS, HTTP TLS, kimlik doğrulama ve minimum yetki prensibi. Bu dördünü doğru kurarsanız açık Elasticsearch kabusu sizi etkilemez.
Son olarak, tüm bu yapılandırmayı Ansible veya Terraform ile otomatize edin. Elle yapılandırılan güvenlik ayarları tutarsızlığa, tutarsızlık da güvenlik açıklarına yol açar. Infrastructure as Code burada sadece kolaylık değil, güvenliğin bir parçası.
