Firestore Veri Güvenliği (Security Rules)

Yunus Kaygun
PiriLabs
Published in
5 min readAug 17, 2018

Bu yazıda Firestore veritabanının nasıl güvenli hale getirileceğini inceleyeceğiz. Eğer Firestore hakkında giriş seviyesinde bilgi sahibi olmak istiyorsanız, Google Cloud Firestore Nedir? yazısını okuyabilirsiniz.

Firestore’da veritabanını ilk oluşturduğunuzda, varsayılan olarak erişim public (genele açık) olarak ayarlanmaktadır. Eğer bu şekilde projenizi yayınlarsanız kısa zamanda veritabanınızın ele geçirilmesi, silinmesi mümkündür. Bu problemi giderebilmek için Firebase güvenlik kuralları oluşturmamız gerekiyor. Kullanıcıların Firestore’a yapacağı bütün istekler öncelikle tanımladığınız güvenlik kurallarından geçecek. Eğer Kuralları sağlıyorsa istek veritabanına ulaşacaktır. Kuralı sağlamıyorsa veritabanına erişim sağlanmadan reddedilecektir.

Firestore Kurallarına Üstteki Sekmeden Erişebilirsiniz.

Yazma Kurallarına Giriş

Bütün kurallar match sözcüğü kullanılarak meydana gelir. Şimdi temel bir kural tanımlayalım. Eğer kullanıcı login olduysa tüm okuma yazma işlemlerini yapabilsin;

service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}

Yukarıda ki kural eğer kullanıcı login olduysa tüm dökümanlar için okuma ve yazma işlemlerine izin ver anlamına gelmekte.

document=** tüm dökümanlar için bu işlemi uygula anlamına gelmektedir.

Kuralları Test Edelim

Firestore’un sağladığı bir avantaj da kuralları test etmemiz için bize sunduğu similatör. Buraya gerekli koşulları ve durumları girerek kuralların nasıl tepki verdiğini test edebiliyoruz.
Örneğin kullanıcı login iken, kullanıcı login değilken, okuma, yazma, silme gibi işlemleri test edebiliyoruz. Ayrıca Get, List, Create, Delete, Update gibi farklı işlemlerde test edebiliyoruz.

Firestore Kural Similatörü

Kuralları Deploy Etmek

Firebase kurallarını deploy etmeniz gerekmektedir. Aksi halde kurallar geçerli olmayacaktır.
Firebase kurallarını 2 şekilde deploy edebilirsiniz.
1. Firebase console kullarak deploy etmek
Rules (kurallar) tabına tıklayarak buraya kurallarımızı tanımlıyoruz.
Daha sonra publish (yayınla) düğmesine tıklayarak aktif etmiş oluyoruz.

2. Firebase CLI kullanarak kuralları yayınlamak
Bu yöntemde ise kuralları projemizde tutuyoruz. Versiyon kontrol sisteminde saklayabiliyoruz. istediğimizde değiştirerek firebase CLI kullanarak publish ediyoruz.
Kullanımı:

// .proje klasöründe .rules dosyası oluşturuyoruz
firebase init firestore
// Bu dosyaya kurallarımızı tanımlıyoruz.
// Deploy ediyoruz
firebase deploy — only firestore:rules

Basit Okuma Yazma Kuralları

Şimdi adım adım yazma kurallarını öğrenmeye başlayalım. Örneğin Cities koleksiyonunda ki tüm dokümanları için if şartına göre okuma yazma izinlerini ver;

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read: if <condition>;
allow write: if <condition>;
}
}
}

burada match /cities/{city} ifadesi yerine match /cities/ist şeklinde kullanarak döküman bazlı yetkilendirme de yapabiliriz. ist ise dökümanın id’si anlamına gelmektedir.

Tanecikli Yapı Kullanmak

Firestore’da kurallarımızı daha detaylı tanımlayabiliriz. Read işlemlerini 2'ye, Write işlemlerini ise 3'e ayırarak detaylı tanımlama yapabilmekteyiz.

Read
- get: tek bir döküman getirme işlemi
- list: query ile koleksiyondan çoklu veri listeleme işlemi

Write
- create: yeni bir döküman oluşturma işlemi
- update: döküman düzenleme işlemi
- delete: doküman silme

Örnek bir kural tanımlayarak bu bilgileri pekiştirelim; Aşağıdaki örnekte ayrı ayrı kurallar tanımlanmıştır;

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow get: if <condition>;
allow list: if <condition>;
}
match /cities/{city} {
allow create: if <condition>;
allow update: if <condition>;
allow delete: if <condition>;
}
}
}

Alt Koleksiyonlarda Kural Tanımlamak

Firestore iç içe koleksiyon yapısını desteklemektedir. Her koleksiyonun dokümanları ve her dokümanın da alt koleksiyonları olabilmektedir. Bazı durumlarda sadece alt koleksiyonların yetkisini kısıtlamak isteyebiliriz. Veya sadece alt koleksiyona erişim yetkisi verdirmek isteyebiliriz. Bu durumda kuralları da iç içe tanımlıyoruz.

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read, write: if <condition>;
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}

Not: Eğer iç içe tüm hiyerarşiye aynı yetkiyi vermek istiyorsanız match /cities/{city}/{document=**} şeklinde ** kullanabilirsiniz.

Aşağıdaki örnekte ise City dökümanlarını kısıtla fakat onun altındaki alt dökümanlara izin ver demiş oluyoruz.

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read, write: if false;
}
match /cities/{document=**} {
allow read, write: if true;
}
}
}

Kurallara Şartlar Yazmak

Kural tanımlarken yukarıdaki örneklerde şart kısımlarını if <condition>; yazarak geçtik. Şimdi bu şartları nasıl belirtebileceğimizi görelim.

1- Login Kontrolü

Kuralarınıza eğer kullanıcı login olduysa işlem yapabilsin gibi bir kısıt eklemek isteyebilirsiniz. Bunu kulanabilmek için yine Firebase’in bir ürünü olan Firebase Authenticationı kullanmanız gerekiyor. Şimdi kısıtların nasıl kullanıldığını görelim Mesela sadece login olan kullanıcılar okuma yazma yapabilsin;

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read, write: if request.auth.uid != null;
}
}
}

Başka bir örnek daha yapalım. Login olan kulanıcılar okuma yapabilsin, userId kendisi olan kullanıcılar yazma işlemi yapabilsin. Yani kullanıcılar sadece kendi eklediği dokumana yazabilir.

service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}

2- Veri Doğrulama

Bazen de dokümanımızda ki verilerin durumuna göre kural belirmek isteyebiliriz.
Mesela dokümanımızda ki visibility alanı public ise erişim sağlanabilsin gibi bir kural yazmak istersek:

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read: if resource.data.visibility == ‘public’;
}
}
}

Burada kullandığımız resource.data sayesinde okuyacağımız dokümanlara erişmiş oluyoruz.
Eğer yazma işlemi yapacaksak gönderilen veride de belirli alanları kontrol etmek isteyebiliriz. Bunun için:

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow update: if request.resource.data.price > 0
}
}
}

Yukarıdaki kural dizisinde fiyat sıfırdan küçükse işlem engellenecektir. Burada request.resource.data ile yazmak için gönderilen dokümana erişmiş oluyoruz.

3- Diğer Dökümanlara Erişerek Kontrol Sağlamak

Bazen de başka koleksiyonlarda veya dokümanlara erişerek veri kontrolü yapmamız gerekebilir. Mesela işlem yapan kullanıcının Admin olup olmadığını kontrol etmek istiyoruz. Bunun için users koleksiyonunda role alanını kontrol edeceğiz. Bu kuralı şöyle tanımlayabiliriz:

service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
// Eğer okuma isteği yapan kullanıcı users koleksiyonunda mevcutsa izin ver
allow read: if exists(/databases/$(database)/documents/users/$(request.auth.uid))
// Eğer yazma isteği yapan kullanıcının rolü Admin ise izin ver
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == ‘Admin’
}
}
}

Özel Fonksiyon Tanımlamak

Sürekli kullandığınız şartlar varsa bunları fonksiyon olarak tanımlayıp birçok yerde kullanabilirsiniz.
Mesela kullanıcı login olduysa ve adminse gibi bir kontrol yapacak fonksiyon tanımlayıp kulanmak istersek:

service cloud.firestore {
match /databases/{database}/documents {
function signedInOrPublic() {
return request.auth.uid != null ||
resource.data.visibility == ‘public’;
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}

Bir yazının daha sonuna geldik :) Yazıda birçok yerde Firebase dokümantasyonundan örnekler aldım. Detaylı bilgi için Firebase Dokumanlarını inceleyebilirsiniz.

--

--