Cloud Firestore Güvenlik Kurallarınızı test etme

Uygulamanızı oluştururken Cloud Firestore veritabanınıza erişimi kilitlemek isteyebilirsiniz. Fakat lansmandan önce daha incelikli Cloud Firestore Güvenlik Kurallarına ihtiyacınız olacak. Cloud Firestore emülatörü ile, uygulamanızın genel özelliklerini ve davranışını prototip oluşturma ve test etmenin yanı sıra, Cloud Firestore Güvenlik Kurallarınızın davranışını kontrol eden birim testleri yazabilirsiniz.

Hızlı başlangıç kılavuzu

Basit kurallar içeren birkaç temel test durumu için hızlı başlangıç örneğini deneyin.

Cloud Firestore Güvenlik Kurallarını Anlama

Mobil ve web istemci kitaplıklarını kullanırken sunucusuz kimlik doğrulama, yetkilendirme ve veri doğrulama için Firebase Authentication ve Cloud Firestore Güvenlik Kuralları'nı uygulayın.

Cloud Firestore Güvenlik Kuralları iki parçadan oluşur:

  1. Veritabanınızdaki dokümanları tanımlayan match ifadesi.
  2. Bu dokümanlara erişimi kontrol eden bir allow ifadesi.

Firebase Authentication, kullanıcıların kimlik bilgilerini doğrular, kullanıcı ve rol tabanlı erişim sistemleri için temel oluşturur.

Cloud Firestore mobil/web istemci kitaplığından gelen her veritabanı isteği, veri okunmadan veya yazılmadan önce güvenlik kurallarınıza göre değerlendirilir. Kurallar, belirtilen belge yollarından herhangi birine erişimi reddederse isteğin tamamı başarısız olur.

Cloud Firestore Güvenlik Kurallarını kullanmaya başlama bölümünde Cloud Firestore Güvenlik Kuralları hakkında daha fazla bilgi edinebilirsiniz.

Emülatörü yükleme

Cloud Firestore emülatörünü yüklemek için Firebase CLI kullanın ve aşağıdaki komutu çalıştırın:

firebase setup:emulators:firestore

Emülatörü çalıştırma

Çalışma dizininizde bir Firebase projesini başlatarak başlayın. Bu, Firebase CLI'ı kullanırken yaygın olarak yapılan bir ilk adımdır.

firebase init

Aşağıdaki komutu kullanarak emülatörü başlatın. Emülatör siz işlemi sonlandırana kadar çalışır:

firebase emulators:start --only firestore

Çoğu durumda emülatörü başlatmak, bir test paketi çalıştırmak ve testler çalıştırıldıktan sonra emülatörü kapatmak istersiniz. Bu işlemi emulators:exec komutunu kullanarak kolayca yapabilirsiniz:

firebase emulators:exec --only firestore "./my-test-script.sh"

Başlatıldığında emülatör varsayılan bir bağlantı noktası (8080) üzerinde çalışmayı dener. firebase.json dosyanızın "emulators" bölümünü değiştirerek emülatör bağlantı noktasını değiştirebilirsiniz:

{
  // ...
  "emulators": {
    "firestore": {
      "port": "YOUR_PORT"
    }
  }
}

Emülatörü çalıştırmadan önce

Emülatörü kullanmaya başlamadan önce aşağıdakileri göz önünde bulundurun:

  • Emülatör, başlangıçta firebase.json dosyanızın firestore.rules alanında belirtilen kuralları yükler. Cloud Firestore Güvenlik Kurallarınızı içeren yerel bir dosyanın adını bekler ve bu kuralları tüm projelere uygular. Yerel dosya yolunu belirtmez veya aşağıda açıklandığı gibi loadFirestoreRules yöntemini kullanmazsanız emülatör tüm projeleri açık kurallara sahip olarak değerlendirir.
  • Firebase SDK'larının çoğu doğrudan emülatörlerle çalışsa da Güvenlik Kuralları'nda auth ile alay etmeyi sadece @firebase/rules-unit-testing kitaplığı destekler ve birim testlerini çok daha kolay hale getirir. Ayrıca kitaplık, aşağıda listelendiği gibi tüm verileri temizleme gibi emülatöre özgü birkaç özelliği destekler.
  • Emülatörler ayrıca istemci SDK'ları aracılığıyla sağlanan üretim Firebase Auth jetonlarını da kabul edecek ve kuralları uygun şekilde değerlendirecektir. Böylece uygulamanız, entegrasyon ve manuel testlerde doğrudan emülatörlere bağlanabilecektir.

Yerel birim testlerini çalıştırma

v9 JavaScript SDK ile yerel birim testleri çalıştırma

Firebase, hem kendi sürüm 9 JavaScript SDK'sı hem de sürüm 8 SDK'sı ile bir Güvenlik Kuralları birimi test kitaplığı dağıtır. Kitaplık API'leri önemli ölçüde farklıdır. Emülatörlere bağlanmak için daha az kurulum gerektiren ve daha basit olan v9 test kitaplığını öneririz. Böylece üretim kaynaklarının yanlışlıkla kullanılmaması sağlanır. Geriye dönük uyumluluk için v8 test kitaplığını kullanıma sunmaya devam ediyoruz.

Yerel olarak çalışan emülatörle etkileşim kurmak için @firebase/rules-unit-testing modülünü kullanın. Zaman aşımları veya ECONNREFUSED hataları alıyorsanız emülatörün gerçekten çalışıp çalışmadığını tekrar kontrol edin.

async/await notasyonunu kullanabilmek için Node.js'nin yeni bir sürümünü kullanmanızı önemle tavsiye ederiz. Test etmek isteyebileceğiniz davranışların neredeyse tamamı eşzamansız işlevleri kapsar ve test modülü, Promise tabanlı kodla çalışacak şekilde tasarlanmıştır.

v9 Kural Birimi Testi kitaplığı emülatörlerden her zaman haberdar olur ve üretim kaynaklarınıza hiçbir zaman dokunmaz.

Kitaplığı, v9 modüler içe aktarma ifadelerini kullanarak içe aktarırsınız. Örnek:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment
} from "@firebase/rules-unit-testing"

// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.

İçe aktarma işleminden sonra, birim testlerinin uygulanması şunları içerir:

  • initializeTestEnvironment çağrısı ile bir RulesTestEnvironment oluşturma ve yapılandırma.
  • Kuralları tetiklemeden test verilerini ayarlamak için bunları geçici olarak atlamanızı sağlayan bir kolaylık yöntemi kullanın RulesTestEnvironment.withSecurityRulesDisabled.
  • RulesTestEnvironment.cleanup() veya RulesTestEnvironment.clearFirestore() gibi test verilerini ve ortamını temizlemek için çağrılar içeren kancalarla birlikte test paketi ve test başına öncesi/sonrası ayarlama.
  • RulesTestEnvironment.authenticatedContext ve RulesTestEnvironment.unauthenticatedContext kullanarak kimlik doğrulama durumlarını taklit eden test durumları uygulama.

Sık kullanılan yöntemler ve fayda işlevleri

Ayrıca v9 SDK'sındaki emülatöre özel test yöntemlerine de bakın.

initializeTestEnvironment() => RulesTestEnvironment

Bu işlev, kural birimi testi için bir test ortamı başlatır. Test kurulumu için önce bu işlevi çağırın. Başarılı yürütme için emülatörlerin çalışması gerekir.

İşlev, proje kimliği ve emülatör yapılandırma ayarlarından oluşan TestEnvironmentConfig tanımlayan isteğe bağlı bir nesneyi kabul eder.

let testEnv = await initializeTestEnvironment({
  projectId: "demo-project-1234",
  firestore: {
    rules: fs.readFileSync("firestore.rules", "utf8"),
  },
});

RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext

Bu yöntem, kimliği doğrulanmış bir Kimlik Doğrulama kullanıcısı gibi davranan bir RulesTestContext oluşturur. Döndürülen bağlam aracılığıyla oluşturulan isteklere sahte bir kimlik doğrulama jetonu eklenir. İsteğe bağlı olarak, Kimlik doğrulama jetonu yükleri için özel talepler veya geçersiz kılmalar tanımlayan bir nesne iletin.

initializeTestEnvironment ile yapılandırılanlar da dahil olmak üzere yapılandırılmış herhangi bir emülatör örneklerine erişmek için testlerinizde döndürülen test bağlam nesnesini kullanın.

// Assuming a Firestore app and the Firestore emulator for this example
import { setDoc } from "firebase/firestore";

const alice = testEnv.authenticatedContext("alice", { … });
// Use the Firestore instance associated with this context
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

RulesTestEnvironment.unauthenticatedContext() => RulesTestContext

Bu yöntem, Authentication aracılığıyla giriş yapılmamış bir istemci gibi davranan bir RulesTestContext oluşturur. Döndürülen bağlam aracılığıyla oluşturulan isteklere Firebase Auth jetonları eklenmez.

initializeTestEnvironment ile yapılandırılanlar da dahil olmak üzere yapılandırılmış herhangi bir emülatör örneklerine erişmek için testlerinizde döndürülen test bağlam nesnesini kullanın.

// Assuming a Cloud Storage app and the Storage emulator for this example
import { getStorage, ref, deleteObject } from "firebase/storage";

const alice = testEnv.unauthenticatedContext();

// Use the Cloud Storage instance associated with this context
const desertRef = ref(alice.storage(), 'images/desert.jpg');
await assertSucceeds(deleteObject(desertRef));

RulesTestEnvironment.withSecurityRulesDisabled()

Güvenlik Kuralları devre dışıymış gibi davranan bağlama sahip bir test kurulum işlevi çalıştırın.

Bu yöntem, Security-Rules-bypassing bağlamını alıp bir taahhüt döndüren bir geri çağırma işlevi alır. Vaat çözümlendiğinde / reddedildiğinde bağlam yok edilir.

RulesTestEnvironment.cleanup()

Bu yöntem, test ortamında oluşturulan tüm RulesTestContexts öğelerini kaldırır ve temel kaynakları temizleyerek temiz bir çıkış sağlar.

Bu yöntem, emülatörlerin durumunu hiçbir şekilde değiştirmez. Testler arasında verileri sıfırlamak için uygulama emülatörüne özgü net veri yöntemini kullanın.

assertSucceeds(pr: Promise<any>)) => Promise<any>

Bu, bir test durumu yardımcı işlevidir.

İşlev, sağlanan bir emülatör işlemini sarmalayan Promise'in hiçbir Güvenlik Kuralı ihlali olmadan çözümleneceğini iddia eder.

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

Bu, bir test durumu yardımcı işlevidir.

İşlev, sağlanan bir emülatör işlemini sarmalayan Promise'in Güvenlik Kuralları ihlali nedeniyle reddedileceğini iddia eder.

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

Emülatöre özel yöntemler

Ayrıca v9 SDK'sındaki yaygın test yöntemlerini ve yardımcı program işlevlerine de bakın.

RulesTestEnvironment.clearFirestore() => Promise<void>

Bu yöntem, Firestore veritabanındaki Firestore emülatörü için yapılandırılan projectId öğesine ait verileri temizler.

RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;

Bu yöntem, bu test bağlamı için bir Firestore örneği alır. Döndürülen Firebase JS Client SDK örneği, istemci SDK API'leriyle (v9 modüler veya v9 uyumlu) kullanılabilir.

Kural değerlendirmelerini görselleştirme

Cloud Firestore emülatörü, Firebase Güvenlik Kuralları için değerlendirme izleme dahil olmak üzere istemci isteklerini Emulator Suite kullanıcı arayüzünde görselleştirmenizi sağlar.

Her isteğin ayrıntılı değerlendirme sırasını görüntülemek için Firestore > İstekler sekmesini açın.

Güvenlik Kuralları değerlendirmelerini gösteren Firestore Emulator İstek Monitörü

Test raporları oluşturma

Bir dizi test çalıştırdıktan sonra, güvenlik kurallarınızın her birinin nasıl değerlendirildiğini gösteren test kapsamı raporlarına erişebilirsiniz.

Raporları almak için emülatör çalışırken açığa çıkan bir uç noktayı sorgulayın. Tarayıcı dostu bir sürüm için aşağıdaki URL'yi kullanın:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html

Bu işlem, kurallarınızı ifadelere ve alt ifadelere böler. Bunları, değerlendirme sayısı ve döndürülen değerlerin sayısı dahil olmak üzere daha fazla bilgi için fareyle üzerine gelebilirsiniz. Bu verilerin ham JSON sürümü için sorgunuza aşağıdaki URL'yi ekleyin:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage

Emülatör ile üretim arasındaki farklar

  1. Açıkça bir Cloud Firestore projesi oluşturmanız gerekmez. Emülatör, erişilen her örneği otomatik olarak oluşturur.
  2. Cloud Firestore emülatörü, normal Firebase Authentication akışıyla çalışmaz. Bunun yerine, Firebase Test SDK'sında rules-unit-testing kitaplığında auth alanını alan initializeTestApp() yöntemini sağladık. Bu yöntem kullanılarak oluşturulan Firebase herkese açık kullanıcı adı, sağladığınız varlık kimliği başarıyla doğrulanmış gibi davranır. null öğesini geçirirseniz kimliği doğrulanmamış kullanıcı olarak davranır (örneğin, auth != null kuralları başarısız olur).

Bilinen sorunları giderme

Cloud Firestore emülatörünü kullanırken aşağıdaki bilinen sorunlarla karşılaşabilirsiniz. Karşılaştığınız düzensiz davranışlarla ilgili sorunları gidermek için aşağıdaki yönergeleri uygulayın. Bu notlar, Güvenlik Kuralları birimi test kitaplığı göz önünde bulundurularak yazılmış olsa da genel yaklaşımlar tüm Firebase SDK'ları için geçerlidir.

Test davranışı tutarsız

Testleriniz, testlerde herhangi bir değişiklik yapılmadan bile zaman zaman başarılı ve başarısız oluyorsa bunların doğru bir şekilde sıralandığını doğrulamanız gerekebilir. Emülatörle kurulan etkileşimlerin çoğu eşzamansız olduğundan, tüm eşzamansız kodların doğru sıralandığından emin olun. Zincirleme vaatlerle veya await notasyonunu serbest bir şekilde kullanarak sıralamayı düzeltebilirsiniz.

Özellikle aşağıdaki eşzamansız işlemleri gözden geçirin:

  • Örneğin, initializeTestEnvironment ile güvenlik kuralları ayarlanıyor.
  • Veri okuma ve yazma (örneğin, db.collection("users").doc("alice").get()).
  • assertSucceeds ve assertFails dahil olmak üzere operasyonel onaylar.

Testler yalnızca emülatörü ilk kez yüklediğinizde başarılı olur

Emülatör durum bilgili. Kendisine yazılan tüm verileri bellekte depolar. Böylece emülatör her kapatıldığında tüm veriler kaybolur. Aynı proje kimliğiyle birden fazla test çalıştırıyorsanız her test, sonraki testleri etkileyebilecek veriler üretebilir. Bu davranışı önlemek için aşağıdaki yöntemlerden birini kullanabilirsiniz:

  • Her test için benzersiz proje kimlikleri kullanın. Bunu yapmayı seçerseniz her testin parçası olarak initializeTestEnvironment öğesini çağırmanız gerekeceğini unutmayın. Kurallar yalnızca varsayılan proje kimliği için otomatik olarak yüklenir.
  • Testlerinizi, önceden yazılmış verilerle etkileşim kurmayacak şekilde yeniden yapılandırın (örneğin, her test için farklı bir koleksiyon kullanın).
  • Test sırasında yazılan tüm verileri silin.

Test kurulumu çok karmaşık

Testinizi ayarlarken verileri Cloud Firestore Güvenlik Kurallarınızın gerçekten izin vermediği şekilde değiştirmek isteyebilirsiniz. Kurallarınız test kurulumunu karmaşık hale getiriyorsa kurulum adımlarında RulesTestEnvironment.withSecurityRulesDisabled kullanmayı deneyin. Böylece okuma ve yazma işlemleri PERMISSION_DENIED hatalarını tetiklemez.

Sonrasında testiniz, RulesTestEnvironment.authenticatedContext ve unauthenticatedContext kullanarak sırasıyla kimliği doğrulanmış veya kimliği doğrulanmamış kullanıcı olarak işlemler gerçekleştirebilir. Bu sayede, Cloud Firestore Güvenlik Kurallarınızın farklı durumlara doğru şekilde izin verdiğini veya bunları reddettiğini doğrulayabilirsiniz.