Elasticsearch’te Güvenli Veri Maskeleme: Hassas Alanları Field Level Security ile Koruma
Production ortamında çalışan bir Elasticsearch cluster’ında hassas müşteri verilerini yanlışlıkla açığa çıkarmak, kariyerinizi bitirebilecek türden bir olay. GDPR, KVKK ve benzeri düzenlemeler altında çalışan ekipler için bu sadece teknik bir sorun değil, aynı zamanda yasal bir zorunluluk. Elasticsearch’ün Field Level Security (FLS) özelliği, tam da bu noktada devreye giriyor: belirli kullanıcıların hangi alanlara erişebileceğini index bazında kontrol etmenizi sağlıyor.
Bu yazıda gerçek dünya senaryoları üzerinden, bir e-ticaret platformunun müşteri verilerini nasıl maskeleyebileceğimizi adım adım inceleyeceğiz.
Field Level Security Nedir ve Neden Önemli?
Klasik yaklaşımda Elasticsearch’te rol tabanlı erişim kontrolü (RBAC) genellikle index seviyesinde kalır. Bir kullanıcıya customers index’ine okuma yetkisi verirsiniz, o kullanıcı da içindeki her şeyi görür: TC kimlik numaraları, kredi kartı bilgileri, ev adresleri… Bu kabul edilemez.
Field Level Security, bunu çözüyor. Belirli bir role sahip kullanıcı customers index’ini sorgulayabilir, ancak credit_card_number, tc_no ve home_address alanlarını göremez. Uygulama log’larını inceleyen junior bir developer, müşteri davranışlarını analiz edebilir ama PII (Personally Identifiable Information) verilerine dokunamaz.
Önemli not: Bu özellik Elasticsearch’ün X-Pack güvenlik modülü ile birlikte gelir. Elasticsearch 8.x sürümlerinde güvenlik özellikleri varsayılan olarak etkin gelir. 7.x serisi için elasticsearch.yml dosyasında aşağıdaki ayarın aktif olduğunu kontrol edin:
# elasticsearch.yml
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
Ortamı Hazırlamak
Önce demo ortamımızı kuralım. customers adında bir index oluşturuyoruz ve içine gerçekçi müşteri verileri ekliyoruz:
# Index ve mapping oluşturma
curl -X PUT "localhost:9200/customers"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"mappings": {
"properties": {
"customer_id": { "type": "keyword" },
"first_name": { "type": "text" },
"last_name": { "type": "text" },
"email": { "type": "keyword" },
"tc_no": { "type": "keyword" },
"phone": { "type": "keyword" },
"credit_card_number": { "type": "keyword" },
"credit_card_cvv": { "type": "keyword" },
"home_address": { "type": "text" },
"city": { "type": "keyword" },
"total_orders": { "type": "integer" },
"last_order_date": { "type": "date" },
"loyalty_score": { "type": "float" }
}
}
}'
Test verisi ekleyelim:
curl -X POST "localhost:9200/customers/_doc/1"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"customer_id": "C-10045",
"first_name": "Ahmet",
"last_name": "Yilmaz",
"email": "[email protected]",
"tc_no": "12345678901",
"phone": "+90 532 111 2233",
"credit_card_number": "4111111111111111",
"credit_card_cvv": "123",
"home_address": "Caferaga Mah. Moda Cad. No:15 Daire:3",
"city": "Istanbul",
"total_orders": 47,
"last_order_date": "2024-11-15",
"loyalty_score": 8.7
}'
Rol Tabanlı Alan Erişim Kontrol Planı
Gerçek dünyada farklı ekiplerin farklı veri erişim ihtiyaçları olur. Bizim senaryomuzda şu ekipler var:
- Veri Analistleri: Satın alma davranışlarını analiz eder, PII verisi görmemeli
- Müşteri Hizmetleri: Müşteriye ulaşmak için email ve telefon görmeli, TC/kredi kartı görmemeli
- Fraud Ekibi: Kredi kartı bilgilerine erişebilmeli ama CVV görmemeli
- Sistem Yöneticileri: Tüm verilere erişebilmeli
Her ekip için ayrı roller tanımlayacağız.
Veri Analistleri Rolü
Bu rol sadece istatistiksel verilere erişebilir:
curl -X PUT "localhost:9200/_security/role/data_analyst_role"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"indices": [
{
"names": ["customers"],
"privileges": ["read"],
"field_security": {
"grant": [
"customer_id",
"city",
"total_orders",
"last_order_date",
"loyalty_score"
]
}
}
]
}'
Dikkat edin: grant listesine sadece görülmesine izin verilen alanlar yazılıyor. tc_no, email, phone, home_address, credit_card_number ve credit_card_cvv alanları bu kullanıcı için adeta yokmuş gibi davranacak.
Müşteri Hizmetleri Rolü
curl -X PUT "localhost:9200/_security/role/customer_service_role"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"indices": [
{
"names": ["customers"],
"privileges": ["read"],
"field_security": {
"grant": [
"customer_id",
"first_name",
"last_name",
"email",
"phone",
"city",
"total_orders",
"last_order_date",
"loyalty_score"
]
}
}
]
}'
Müşteri hizmetleri temsilcisi, müşteriyi arayabilmek için telefon ve email’e erişebilir, ama TC kimlik numarası veya kredi kartı bilgileri bu kullanıcının ekranında hiçbir zaman görünmez.
Fraud Ekibi Rolü
curl -X PUT "localhost:9200/_security/role/fraud_team_role"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"indices": [
{
"names": ["customers", "transactions", "fraud_flags"],
"privileges": ["read"],
"field_security": {
"grant": ["*"],
"except": ["credit_card_cvv", "tc_no"]
}
}
]
}'
Burada farklı bir yaklaşım kullandık. grant: ["*"] ile tüm alanları açtık, except ile sadece CVV ve TC numarasını çıkardık. Fraud ekibi kredi kartı numarasını görmeli (dolandırıcılık tespiti için) ama CVV’yi hiçbir zaman görmemeli.
Kullanıcı Oluşturma ve Rol Atama
Rolleri tanımladıktan sonra kullanıcıları oluşturup rolleri atıyoruz:
# Veri analisti kullanıcısı
curl -X PUT "localhost:9200/_security/user/analyst_mehmet"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"password": "StrongPass2024!",
"roles": ["data_analyst_role"],
"full_name": "Mehmet Analyst",
"email": "[email protected]"
}'
# Müşteri hizmetleri kullanıcısı
curl -X PUT "localhost:9200/_security/user/cs_ayse"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"password": "StrongPass2024!",
"roles": ["customer_service_role"],
"full_name": "Ayse CS",
"email": "[email protected]"
}'
# Fraud ekibi kullanıcısı
curl -X PUT "localhost:9200/_security/user/fraud_kemal"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"password": "StrongPass2024!",
"roles": ["fraud_team_role"],
"full_name": "Kemal Fraud",
"email": "[email protected]"
}'
Maskelemeyi Test Etmek
Şimdi her kullanıcının aynı sorguya farklı sonuçlar döndürdüğünü görelim:
# Veri analisti olarak sorgu
curl -X GET "localhost:9200/customers/_search"
-H 'Content-Type: application/json'
-u analyst_mehmet:StrongPass2024!
-d '{
"query": { "match_all": {} },
"_source": true
}'
# Beklenen çıktı - hassas alanlar YOK:
# {
# "customer_id": "C-10045",
# "city": "Istanbul",
# "total_orders": 47,
# "last_order_date": "2024-11-15",
# "loyalty_score": 8.7
# }
# Fraud ekibi olarak aynı sorgu - credit_card_number VAR, cvv YOK:
curl -X GET "localhost:9200/customers/_search"
-H 'Content-Type: application/json'
-u fraud_kemal:StrongPass2024!
-d '{
"query": { "match_all": {} }
}'
Eğer analyst_mehmet kullanıcısı direkt olarak tc_no alanını sorgulama yaparsa ne olur? Elasticsearch sessizce bu alanı yok sayar, hata vermez. Bu davranışı bilmek önemli: FLS hata fırlatmaz, sadece ilgili alanı yanıttan çıkarır.
Document Level Security ile Birleştirmek
FLS’yi Document Level Security (DLS) ile birleştirdiğinizde çok daha güçlü bir erişim kontrolü elde edersiniz. Diyelim ki müşteri hizmetleri temsilcileri sadece kendi bölgelerindeki müşterilere erişebilsin:
curl -X PUT "localhost:9200/_security/role/cs_istanbul_role"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"indices": [
{
"names": ["customers"],
"privileges": ["read"],
"query": "{"term": {"city": "Istanbul"}}",
"field_security": {
"grant": [
"customer_id",
"first_name",
"last_name",
"email",
"phone",
"city",
"total_orders",
"loyalty_score"
]
}
}
]
}'
Bu rolle giriş yapan bir kullanıcı, hem sadece Istanbul müşterilerini görür, hem de hassas alanlar maskelenir. Çift katmanlı koruma.
Kibana ile Entegrasyon
Kibana üzerinden veri analizi yapan ekipler için Space ve Role kombinasyonu kritik önem taşır. Kibana’daki roller Elasticsearch rolleriyle senkronize çalışır. Kibana’da bir data analyst kullanıcısı Discover ekranını açtığında, FLS kuralları devreye girer ve field listesinde tc_no veya credit_card_number alanları görünmez bile.
Kibana için özel roller tanımlarken şuna dikkat edin:
curl -X PUT "localhost:9200/_security/role/kibana_analyst_role"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"cluster": [],
"indices": [
{
"names": ["customers", ".kibana*"],
"privileges": ["read", "view_index_metadata"],
"field_security": {
"grant": [
"customer_id",
"city",
"total_orders",
"last_order_date",
"loyalty_score"
]
}
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_discover.read", "feature_visualize.read"],
"resources": ["space:default"]
}
]
}'
Rollerin Doğruluğunu Denetlemek
Bir süre sonra “kim hangi alanlara erişebiliyor?” sorusunun cevabını bulmak zorunda kalırsınız. Özellikle audit için bu bilgi hayat kurtarır:
# Belirli bir kullanıcının rollerini ve yetkilerini kontrol et
curl -X GET "localhost:9200/_security/user/analyst_mehmet"
-u elastic:your_password
# Bir rolün detaylarını görüntüle
curl -X GET "localhost:9200/_security/role/data_analyst_role"
-u elastic:your_password
# Kullanıcının belirli bir eylem için yetkisi var mı?
curl -X POST "localhost:9200/_security/user/analyst_mehmet/_has_privileges"
-H 'Content-Type: application/json'
-u elastic:your_password
-d '{
"index": [
{
"names": ["customers"],
"privileges": ["read"]
}
]
}'
Dikkat Edilmesi Gereken Noktalar
Pratikte FLS kullanırken karşılaşabileceğiniz durumlar:
- Aggregation davranışı: Bir alan FLS ile kısıtlanmışsa, o alan üzerinde aggregation da çalışmaz. Veri analistiniz
tc_noüzerinde distinct count almaya çalışırsa sıfır sonuç gelir, hata değil.
- Wildcard kullanımı:
grant: ["*"]tüm alanları açar. Yeni bir hassas alan eklediğinizdeexceptlistesini güncellemeyi unutmayın. Bu nedenle “whitelist” yaklaşımı (sadece izin verilenler) production için genellikle daha güvenlidir.
- Nested objeler:
address.streetgibi nested alanlar için noktalı notasyon kullanılır.grant: ["address.city"]diyebilirsiniz,address.streetyine gizli kalır.
- Performans etkisi: FLS, sorgu başına küçük bir overhead getirir. Milyonlarca doküman üzerinde çalışan sorgularda bu genellikle ihmal edilebilir düzeyde kalır, ama yoğun sorgu trafiğinde benchmark yapmakta fayda var.
- Reindex işlemleri: Bir kullanıcı FLS kısıtlamasıyla reindex veya ingest pipeline işlemi yapmaya çalışırsa, sadece erişebildiği alanlar kopyalanır. Bu sessiz veri kaybına yol açabilir, dikkat.
- Cache davranışı: Elasticsearch FLS rollerini cache’ler. Bir rolü güncellediğinizde etkisinin görünmesi için birkaç saniye bekleyebilirsiniz. Test ortamında kafanız karışmasın.
KVKK Uyum Senaryosu
Türkiye’de faaliyet gösteren bir şirket olarak KVKK kapsamında kişisel verilerin işlenmesini belgelemeniz gerekiyor. FLS bu noktada size somut bir kanıt sunar: “TC kimlik numarasına sadece şu roller erişebilir” diyebilirsiniz ve bunu API ile ispatlayabilirsiniz.
Düzenli olarak şu kontrolü otomatize edin:
#!/bin/bash
# kvkk_audit.sh - Hassas alanlara kimlerin erişebildiğini raporla
ES_HOST="https://localhost:9200"
ES_USER="elastic"
ES_PASS="your_password"
SENSITIVE_FIELDS=("tc_no" "credit_card_number" "credit_card_cvv" "home_address")
echo "=== KVKK Hassas Alan Erisim Raporu ==="
echo "Tarih: $(date)"
echo ""
# Tüm rolleri çek
ROLES=$(curl -s -u $ES_USER:$ES_PASS "$ES_HOST/_security/role" | python3 -c "import sys,json; roles=json.load(sys.stdin); [print(r) for r in roles]")
for ROLE in $ROLES; do
ROLE_DATA=$(curl -s -u $ES_USER:$ES_PASS "$ES_HOST/_security/role/$ROLE")
echo "Rol: $ROLE"
for FIELD in "${SENSITIVE_FIELDS[@]}"; do
if echo "$ROLE_DATA" | grep -q "$FIELD"; then
echo " [DIKKAT] $FIELD alani bu rolde erisime ACIK olabilir"
fi
done
echo ""
done
Sonuç
Field Level Security, Elasticsearch’te veri maskelemenin en temiz ve yönetilebilir yolu. Uygulama katmanında “bu kullanıcı bu alanı göremez” mantığını yazmak yerine, bu kontrolü veritabanı motorunun kendisine bırakıyorsunuz. Bu, uygulama kodunda yapılacak bir hata yüzünden hassas verinin sızdırılması riskini dramatik biçimde azaltır.
Pratikte başarılı bir FLS implementasyonu için şu adımları takip edin: önce veri sınıflandırması yapın (hangi alanlar PII, hangileri değil), sonra ekiplerin gerçek ihtiyaçlarını netleştirin, rolleri “minimum yetki” prensibiyle tasarlayın ve düzenli audit scriptleriyle bu yapının bozulmadığını kontrol altında tutun.
Kibana, reindex ve aggregation davranışları konusundaki ince noktaları başından bilmek, ileride saatlerce debug yapmaktan sizi kurtarır. Production’a almadan önce mutlaka her rolü simüle ederek test edin. Ve unutmayın: FLS bir şifrelemedir değil, bir erişim kontrolüdür. Elasticsearch node’larına direkt dosya sistemi erişimi olan biri için bu kontroller geçerli olmaz; disk şifreleme ve network güvenliği ayrı bir katman olarak mutlaka uygulanmalıdır.
