Güvenlik — Authentication, Authorization, TLS
Giriş — Authentication, Authorization, TLS/SSL ve RBAC
Bir bankanın güvenlik sistemini düşün. Kapıdan girmek için kimlik gösterirsin (authentication — kim olduğunu kanıtla). İçeri girdikten sonra her yere gidemezsin — kasaya sadece yetkili personel girer, müdürün odasına sadece randevuyla girilir (authorization — neye erişebileceğin). Ve tüm iletişim şifreli — telefon dinlenmez, kameralar güvenli, belgeler kilitli kasada (TLS/SSL — iletişim güvenliği).
Elasticsearch güvenliği de aynı üç ayak üzerinde durur. Önceki versiyonlarda güvenlik opsiyoneldi (ve pahalı bir eklentiydi). Elasticsearch 8.x ile varsayılan olarak aktif. Artık production'da güvenliksiz Elasticsearch çalıştırmak kabul edilemez.
1. Elasticsearch Güvenlik Katmanları
| Katman | Amaç | Teknoloji |
|---|---|---|
| Authentication | Kim olduğunu doğrula | Native, LDAP, SAML, OIDC, API Key |
| Authorization | Neye erişebileceğini belirle | RBAC, Field/Document Level Security |
| Encryption | İletişimi şifrele | TLS/SSL (node-to-node, client-to-node) |
| Audit Logging | Kim ne yaptı? | Audit trail |
| IP Filtering | Nereden erişebileceğini kısıtla | IP whitelist/blacklist |
2. TLS/SSL — İletişim Güvenliği
Neden TLS?
Elasticsearch node'ları arasında ve client-node arasında giden veri şifrelenmezse, network'te dinleyen biri tüm verilerinizi görebilir — query'ler, response'lar, credential'lar dahil.
Sertifika Oluşturma
# 1. Certificate Authority (CA) oluştur
bin/elasticsearch-certutil ca --out elastic-stack-ca.p12
# 2. Node sertifikaları oluştur
bin/elasticsearch-certutil cert \
--ca elastic-stack-ca.p12 \
--out elastic-certificates.p12
# 3. PEM format (opsiyonel — bazı araçlar PEM ister)
bin/elasticsearch-certutil cert \
--ca elastic-stack-ca.p12 \
--out certs \
--pem
# 4. HTTP sertifikası (client-to-node)
bin/elasticsearch-certutil httpelasticsearch.yml — TLS Konfigürasyonu
# Transport layer (node-to-node) — ZORUNLU
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
# HTTP layer (client-to-node) — ÖNERİLEN
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
xpack.security.http.ssl.truststore.path: http.p12
# PEM format kullanıyorsanız:
# xpack.security.transport.ssl.key: /etc/elasticsearch/certs/node.key
# xpack.security.transport.ssl.certificate: /etc/elasticsearch/certs/node.crt
# xpack.security.transport.ssl.certificate_authorities: /etc/elasticsearch/certs/ca.crtKeystore'a Şifre Ekleme
# P12 keystore şifresi
bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password3. Authentication — Kimlik Doğrulama
Built-in Users
Elasticsearch kurulduğunda otomatik oluşturulan kullanıcılar:
| Kullanıcı | Rolü | Kullanım |
|---|---|---|
elastic | Superuser | Admin işlemleri |
kibana_system | Kibana internal | Kibana → ES bağlantısı |
logstash_system | Logstash monitoring | Logstash monitoring |
beats_system | Beats monitoring | Beats monitoring |
apm_system | APM monitoring | APM monitoring |
remote_monitoring_user | Monitoring | Monitoring cluster |
Şifre Ayarlama
# Tüm built-in kullanıcılara otomatik şifre ata
bin/elasticsearch-setup-passwords auto
# İnteraktif şifre belirleme
bin/elasticsearch-setup-passwords interactive
# Belirli kullanıcının şifresini değiştir (API)
POST _security/user/elastic/_password
{
"password": "new-super-secret-password"
}Native User Oluşturma
// Kullanıcı oluştur
POST _security/user/john_doe
{
"password": "s3cr3tP@ssw0rd",
"roles": ["log_reader", "dashboard_viewer"],
"full_name": "John Doe",
"email": "john@company.com",
"metadata": {
"department": "engineering",
"team": "backend"
}
}
// Kullanıcı güncelle
PUT _security/user/john_doe
{
"roles": ["log_reader", "dashboard_viewer", "index_writer"],
"full_name": "John Doe",
"email": "john@company.com"
}
// Kullanıcı sil
DELETE _security/user/john_doe
// Kullanıcıları listele
GET _security/userAPI Key Authentication
Servisler arası iletişim için kullanıcı adı/şifre yerine API key daha güvenli ve pratiktir:
// API Key oluştur
POST _security/api_key
{
"name": "filebeat-key",
"expiration": "365d",
"role_descriptors": {
"filebeat_writer": {
"cluster": ["monitor", "manage_index_templates", "manage_ilm"],
"indices": [
{
"names": ["filebeat-*", "logs-*"],
"privileges": ["create_index", "create", "write", "manage"]
}
]
}
}
}
// Yanıt:
{
"id": "VuaCfGcBCdbkQm-e5aOx",
"name": "filebeat-key",
"api_key": "ui2lp2axTNmsyakw9tvNnw",
"encoded": "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw=="
}API Key kullanımı:
# Authorization header ile
curl -H "Authorization: ApiKey VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw==" \
https://es:9200/_cluster/health
# Veya id:api_key base64 encode
# base64(VuaCfGcBCdbkQm-e5aOx:ui2lp2axTNmsyakw9tvNnw)// API Key bilgilerini görüntüle
GET _security/api_key?name=filebeat-key
// API Key'i invalidate et (revoke)
DELETE _security/api_key
{
"name": "filebeat-key"
}
// Tüm API Key'leri listele
GET _security/api_keyLDAP / Active Directory Entegrasyonu
# elasticsearch.yml — LDAP realm
xpack.security.authc.realms.ldap.ldap1:
order: 1
url: "ldaps://ldap.company.com:636"
bind_dn: "cn=elasticsearch,ou=services,dc=company,dc=com"
user_search:
base_dn: "ou=users,dc=company,dc=com"
filter: "(uid={0})"
group_search:
base_dn: "ou=groups,dc=company,dc=com"
ssl:
certificate_authorities: ["/etc/elasticsearch/certs/ldap-ca.crt"]
files:
role_mapping: "/etc/elasticsearch/role_mapping.yml"# role_mapping.yml — LDAP grup → ES role mapping
developer:
- "cn=developers,ou=groups,dc=company,dc=com"
admin:
- "cn=sysadmins,ou=groups,dc=company,dc=com"
log_reader:
- "cn=all-employees,ou=groups,dc=company,dc=com"SAML / OIDC (SSO)
# elasticsearch.yml — SAML realm
xpack.security.authc.realms.saml.saml1:
order: 2
idp.metadata.path: "https://idp.company.com/metadata.xml"
idp.entity_id: "https://idp.company.com"
sp.entity_id: "https://kibana.company.com"
sp.acs: "https://kibana.company.com/api/security/saml/callback"
sp.logout: "https://kibana.company.com/logout"
attributes.principal: "nameid"
attributes.groups: "groups"4. Authorization — Yetkilendirme (RBAC)
Role-Based Access Control
RBAC ile kullanıcılara roller atanır, roller ise izinleri tanımlar.
Role Oluşturma
// Log okuyucu — sadece logları okuyabilir
POST _security/role/log_reader
{
"cluster": ["monitor"],
"indices": [
{
"names": ["logs-*", "filebeat-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_discover.read", "feature_dashboard.read"],
"resources": ["space:default"]
}
]
}
// Index yöneticisi — index oluşturabilir, yazabilir
POST _security/role/index_manager
{
"cluster": ["manage_index_templates", "manage_ilm", "monitor"],
"indices": [
{
"names": ["*"],
"privileges": ["create_index", "manage", "write", "read", "delete"]
}
]
}
// Dashboard görüntüleyici
POST _security/role/dashboard_viewer
{
"cluster": [],
"indices": [
{
"names": ["logs-*", "metrics-*"],
"privileges": ["read"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_dashboard.read"],
"resources": ["space:default"]
}
]
}
// Superuser (tehlikeli — dikkatli kullan)
POST _security/role/custom_superuser
{
"cluster": ["all"],
"indices": [
{
"names": ["*"],
"privileges": ["all"]
}
],
"run_as": ["*"]
}Cluster Privileges
| Privilege | Açıklama |
|---|---|
all | Tüm cluster işlemleri |
monitor | Cluster health, stats okuma |
manage | Cluster yönetimi |
manage_security | Kullanıcı/role yönetimi |
manage_index_templates | Index template yönetimi |
manage_ilm | ILM yönetimi |
manage_pipeline | Ingest pipeline yönetimi |
Index Privileges
| Privilege | Açıklama |
|---|---|
all | Tüm index işlemleri |
read | Arama, get, mget, field caps |
write | Index, update, delete, bulk |
create | Sadece create (yoksa oluştur) |
create_index | Index oluşturma |
delete | Document silme |
delete_index | Index silme |
manage | Index ayarları, mapping, alias |
view_index_metadata | Index metadata okuma |
monitor | Index stats, recovery |
5. Field-Level ve Document-Level Security
Field-Level Security (FLS)
Belirli field'lara erişimi kısıtlama:
POST _security/role/pii_restricted
{
"indices": [
{
"names": ["users-*"],
"privileges": ["read"],
"field_security": {
"grant": ["name", "department", "role", "created_at"],
"except": ["ssn", "salary", "phone", "address"]
}
}
]
}
// Bu role sahip kullanıcı users-* index'inden arama yaptığında:
// - name, department, role, created_at → görür
// - ssn, salary, phone, address → göremezDocument-Level Security (DLS)
Belirli document'lara erişimi kısıtlama:
// Sadece kendi departmanının verilerini görebilir
POST _security/role/department_reader
{
"indices": [
{
"names": ["employees-*"],
"privileges": ["read"],
"query": {
"bool": {
"filter": [
{ "term": { "department": "engineering" } }
]
}
}
}
]
}
// Bu role sahip kullanıcı employees-* index'inde arama yaptığında:
// Sadece department="engineering" olan document'ları görürBirleşik FLS + DLS
POST _security/role/hr_restricted
{
"indices": [
{
"names": ["employees-*"],
"privileges": ["read"],
"field_security": {
"grant": ["name", "department", "title", "start_date"]
},
"query": {
"bool": {
"must_not": [
{ "term": { "department": "executive" } }
]
}
}
}
]
}
// Executive departmanını göremez + salary/ssn gibi field'ları göremez6. Audit Logging
Audit Log Etkinleştirme
# elasticsearch.yml
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include:
- access_denied
- access_granted
- anonymous_access_denied
- authentication_failed
- connection_denied
- tampered_request
- run_as_denied
- run_as_granted
- security_config_change
# Çok fazla log oluşmaması için filtreleme
xpack.security.audit.logfile.events.exclude:
- access_granted
xpack.security.audit.logfile.events.emit_request_body: falseAudit Log Çıktısı
// /var/log/elasticsearch/<cluster-name>_audit.json
{
"@timestamp": "2024-01-15T14:30:00.000Z",
"event.action": "access_denied",
"user.name": "john_doe",
"user.roles": ["log_reader"],
"origin.address": "10.0.1.50",
"request.name": "DeleteIndexRequest",
"indices": ["production-data"],
"action": "indices:admin/delete"
}7. IP Filtering
# elasticsearch.yml
xpack.security.transport.filter.allow: ["10.0.0.0/8", "192.168.0.0/16"]
xpack.security.transport.filter.deny: _all
xpack.security.http.filter.allow: ["10.0.0.0/8", "172.16.0.0/12"]
xpack.security.http.filter.deny: _allVeya dinamik olarak:
PUT _cluster/settings
{
"persistent": {
"xpack.security.transport.filter.allow": "10.0.0.0/8",
"xpack.security.transport.filter.deny": "_all"
}
}8. Java ile Güvenlik Konfigürasyonu
SSL ile Bağlantı
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
public class SecureElasticsearchClient {
public static ElasticsearchClient create() throws Exception {
// SSL Context
KeyStore trustStore = KeyStore.getInstance("pkcs12");
try (InputStream is = Files.newInputStream(
Path.of("/etc/app/certs/elastic-ca.p12"))) {
trustStore.load(is, "changeme".toCharArray());
}
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(trustStore, null)
.build();
// Credentials
BasicCredentialsProvider credProvider = new BasicCredentialsProvider();
credProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials("app_user", "s3cret")
);
// REST Client
RestClient restClient = RestClient.builder(
new HttpHost("es-node1", 9200, "https"),
new HttpHost("es-node2", 9200, "https")
)
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credProvider)
)
.build();
// Elasticsearch Client
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}
}API Key ile Bağlantı
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
public static ElasticsearchClient createWithApiKey(
String apiKeyEncoded) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("es-node1", 9200, "https")
)
.setDefaultHeaders(new Header[]{
new BasicHeader("Authorization", "ApiKey " + apiKeyEncoded)
})
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setSSLContext(sslContext)
)
.build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}Spring Boot ile Güvenlik Konfigürasyonu
# application.yml
spring:
elasticsearch:
uris: https://es-node1:9200,https://es-node2:9200
username: app_user
password: ${ES_PASSWORD}
socket-timeout: 30s
connection-timeout: 10s@Configuration
public class ElasticsearchConfig {
@Bean
public ElasticsearchClient elasticsearchClient() throws Exception {
// SSL + API Key konfigürasyonu
// (yukarıdaki SecureElasticsearchClient pattern'ı)
return SecureElasticsearchClient.create();
}
}9. Best Practices
✅ Yap
| Konu | Öneri |
|---|---|
| TLS | Hem transport hem HTTP katmanında TLS etkinleştir |
| Minimum privilege | Her kullanıcı/servis sadece gereken izinlere sahip olsun |
| API Key | Servisler için kullanıcı/şifre yerine API key kullan |
| Audit log | Production'da her zaman açık |
| Elastic şifresi | İlk kurulumda hemen değiştir |
| Sertifika rotasyonu | Sertifikaları yıllık yenile, otomatize et |
| LDAP/SAML | Büyük organizasyonlarda SSO kullan |
❌ Yapma
| Konu | Neden |
|---|---|
| Güvenliksiz production | Herkes her şeyi okuyabilir/silebilir |
| elastic kullanıcısıyla uygulama | Superuser — tehlikeli. Uygulama-specific kullanıcı oluştur |
| Şifreleri config dosyasında | Keystore veya environment variable kullan |
| FLS/DLS olmadan PII verisi | GDPR/KVKK ihlali riski |
| Self-signed cert production'da | Geçerli CA sertifikası kullan |
10. Yaygın Hatalar ve Çözümleri
Hata 1: "SSL Handshake Failed"
# Sorun: Node'lar birbirine bağlanamıyor
# Kontrol: Sertifikalar aynı CA'dan mı?
openssl x509 -in node.crt -text -noout | grep Issuer
# CA sertifikası tüm node'larda mevcut mu?
# Sertifika süresi dolmuş mu?
openssl x509 -in node.crt -enddate -nooutHata 2: "Security Exception — action is unauthorized"
// Sorun: Kullanıcının yeterli yetkisi yok
// Kontrol: Kullanıcının rollerini kontrol et
GET _security/user/john_doe
// Rolün izinlerini kontrol et
GET _security/role/log_reader
// Çözüm: Eksik privilege'i ekle
PUT _security/role/log_reader
{
"indices": [
{
"names": ["logs-*"],
"privileges": ["read", "view_index_metadata"]
}
]
}Hata 3: "Cannot Connect — Connection Refused"
# HTTP SSL aktif ama client HTTP (SSL'siz) ile bağlanıyor
# Kontrol:
curl -k https://localhost:9200 # https ile dene
curl http://localhost:9200 # http → connection refused (doğru davranış)
# Sertifika doğrulama hatası varsa:
curl --cacert /etc/elasticsearch/certs/ca.crt https://localhost:9200Özet
TLS/SSL hem node-to-node (transport) hem client-to-node (HTTP) katmanında zorunludur — Elasticsearch 8.x'te varsayılan olarak aktif.
Authentication kullanıcı kimliğini doğrular — Native users, LDAP, SAML, OIDC ve API Key desteklenir. Servisler için API Key tercih edin.
RBAC ile roller tanımlanır ve kullanıcılara atanır — minimum privilege prensibi: her kullanıcı sadece gereken izinlere sahip olmalı.
Field-Level Security ve Document-Level Security ile hassas verilere erişimi granüler kontrol edebilirsiniz — PII verisi içeren index'lerde zorunlu.
Audit logging production'da her zaman açık olmalı — kim ne yaptı sorusuna cevap verir, güvenlik ihlallerini tespit eder.
Elastic superuser ile uygulama çalıştırmayın — uygulama-specific kullanıcı ve API key oluşturun.
AI Asistan
Sorularını yanıtlamaya hazır