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

Uygulamanızı geliştirirken Cloud Firestore veritabanınıza erişimi kısıtlamak isteyebilirsiniz. Ancak kullanıma sunmadan önce daha ayrıntılı bir plan yapmanız gerekir Cloud Firestore Security Rules. Cloud FirestoreEmülatör ile prototip oluşturmanın ve uygulamanızın genel özelliklerini ve davranışını test etmenin yanı sıra Cloud Firestore Security Rules davranışını kontrol eden birim testleri de yazabilirsiniz.

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

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

Anlama Cloud Firestore Security Rules

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 Security Rules'ı uygulayın.

Cloud Firestore Security Rules iki parçadan oluşur:

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

Firebase Authentication, kullanıcıların kimlik bilgilerini doğrular ve kullanıcı tabanlı ve role dayalı erişim sistemlerinin temelini oluşturur.

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

Cloud Firestore Security Rules hakkında daha fazla bilgiyi Cloud Firestore Security Rules'ı kullanmaya başlama başlıklı makalede bulabilirsiniz.

Emülatörü yükleme

Cloud Firestore emülatörünü yüklemek için Firebase CLI'yı 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 projesi başlatarak başlayın. Bu, Firebase CLI'yı kullanırken uygulanan yaygın bir ilk adımdır.

firebase init

Aşağıdaki komutu kullanarak emülatörü başlatın. Emülatör, 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 ardından testler çalıştı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"

Emülatör başlatıldığında varsayılan bir bağlantı noktasında (8080) çalışmaya çalışır. "emulators" dosyanızın firebase.json 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 Security Rules içeren yerel bir dosyanın adını bekler ve bu kuralları tüm projelere uygular. Yerel dosya yolunu sağlamazsanız veya aşağıda açıklandığı gibi loadFirestoreRules yöntemini kullanırsanız emülatör, tüm projeleri açık kurallara sahip olarak değerlendirir.
  • Çoğu Firebase SDK'sı doğrudan emülatörlerle çalışsa da yalnızca @firebase/rules-unit-testing kitaplığı, Security Rules'da auth sahteleme özelliğini destekler. Bu da birim testlerini çok daha kolay hale getirir. Ayrıca, kitaplık aşağıdaki listede belirtildiği gibi tüm verileri temizleme gibi emülatöre özgü birkaç özelliği de destekler.
  • Emülatörler, İstemci SDK'ları aracılığıyla sağlanan üretim Firebase Auth jetonlarını da kabul eder ve kuralları buna göre değerlendirir. Bu sayede, uygulamanızı entegrasyon ve manuel testlerde doğrudan emülatörlere bağlayabilirsiniz.

Yerel birim testleri çalıştırma

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

Firebase, hem 9. sürüm JavaScript SDK'sı hem de 8. sürüm SDK'sı ile birlikte bir Güvenlik Kuralları birim testi kitaplığı dağıtır. Kitaplık API'leri önemli ölçüde farklıdır. Daha akıcı olan ve emülatörlere bağlanmak için daha az kurulum gerektiren v9 test kitaplığını kullanmanızı öneririz. Bu sayede, üretim kaynaklarının yanlışlıkla kullanılmasını güvenli bir şekilde önleyebilirsiniz. Geriye dönük uyumluluk için v8 test kitaplığını kullanıma sunmaya devam ediyoruz.

Yerel olarak çalışan emülatörle etkileşimde bulunmak için @firebase/rules-unit-testing modülünü kullanın. Zaman aşımları veya ECONNREFUSED hataları alırsanız emülatörün gerçekten çalıştığını iki kez 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ı asenkron işlevleri içerir ve test modülü, Promise tabanlı kodla çalışacak şekilde tasarlanmıştır.

v9 Kuralları Birim Testi kitaplığı, emülatörlerin her zaman farkındadır ve üretim kaynaklarınıza asla dokunmaz.

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

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 aktarıldıktan sonra birim testlerinin uygulanması şu adımları içerir:

  • RulesTestEnvironment numarası aranarak initializeTestEnvironment ile görüşme oluşturma ve yapılandırma.
  • Kuralları tetiklemeden test verileri ayarlama, kuralları geçici olarak atlamanıza olanak tanıyan bir kolaylık yöntemi kullanma RulesTestEnvironment.withSecurityRulesDisabled.
  • Test verilerini ve ortamını temizlemek için RulesTestEnvironment.cleanup() veya RulesTestEnvironment.clearFirestore() gibi çağrılarla test paketi ve test öncesi/sonrası kancaları ayarlama.
  • RulesTestEnvironment.authenticatedContext ve RulesTestEnvironment.unauthenticatedContext kullanarak kimlik doğrulama durumlarını taklit eden test durumları uygulama.

Sık kullanılan yöntemler ve yardımcı işlevler

Ayrıca v9 SDK'sındaki emülatöre özgü test yöntemlerine de göz atın.

initializeTestEnvironment() => RulesTestEnvironment

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

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

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 isteklerde sahte bir kimlik doğrulama jetonu bulunur. İsteğe bağlı olarak, kimlik doğrulama jetonu yükleri için özel talepleri veya geçersiz kılmaları tanımlayan bir nesne iletin.

initializeTestEnvironment ile yapılandırılanlar da dahil olmak üzere yapılandırılmış tüm 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, kimlik doğrulama yoluyla giriş yapılmamış bir istemci gibi davranan bir RulesTestContext oluşturur. Döndürülen bağlam aracılığıyla oluşturulan isteklerde Firebase Auth jetonları eklenmez.

initializeTestEnvironment ile yapılandırılanlar da dahil olmak üzere yapılandırılmış tüm 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ışı bırakılmış gibi davranan bir bağlamla test kurulumu işlevi çalıştırın.

Bu yöntem, Security-Rules-bypassing bağlamını alan ve bir promise döndüren bir geri çağırma işlevi alır. Bağlam, söz çözüldüğünde / reddedildiğinde yok edilir.

RulesTestEnvironment.cleanup()

Bu yöntem, test ortamında oluşturulan tüm RulesTestContexts öğelerini yok eder ve temel kaynakları temizleyerek temiz bir çıkışa olanak tanır.

Bu yöntem, emülatörlerin durumunu hiçbir şekilde değiştirmez. Testler arasındaki verileri sıfırlamak için uygulamaya özel emülatör veri temizleme yöntemini kullanın.

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

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

Bu işlev, bir emülatör işlemini sarmalayan sağlanan Promise'in, güvenlik kuralları 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.

Bu işlev, bir emülatör işlemini sarmalayan sağlanan Promise'in bir güvenlik kuralları ihlaliyle 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öntemleri ve yardımcı işlevler başlıklı makaleyi de inceleyin.

RulesTestEnvironment.clearFirestore() => Promise<void>

Bu yöntem, Firestore emülatörü için projectId yapılandırılmış Firestore veritabanındaki verileri temizler.

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

Bu yöntem, 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ştirmenize olanak tanır.

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 İstekleri İzleyicisi

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 emülatördeki herkese açık 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, kurallarınızı ifadeler ve alt ifadeler halinde ayırır. Değerlendirme sayısı ve döndürülen değerler gibi daha fazla bilgi için imleçle bu ifadelerin ü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. Cloud Firestore projesi oluşturmanız gerekmez. Emülatör, erişilen tüm örnekleri otomatik olarak oluşturur.
  2. Cloud Firestore emülatörü, normal Firebase Authentication akışıyla çalışmaz. Bunun yerine, Firebase Test SDK'sında initializeTestApp() kitaplığında auth alanı alan rules-unit-testing yöntemini sağladık. Bu yöntem kullanılarak oluşturulan Firebase işleyeni, sağladığınız herhangi bir varlık olarak başarıyla kimlik doğrulaması yapılmış gibi davranır. null değerini iletirseniz kimliği doğrulanmamış bir kullanıcı gibi davranılı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ışları gidermek için aşağıdaki talimatları uygulayın. Bu notlar, Güvenlik Kuralları birim testi kitaplığı göz önünde bulundurularak yazılmıştır ancak genel yaklaşımlar tüm Firebase SDK'ları için geçerlidir.

Test davranışı tutarsız

Testlerde herhangi bir değişiklik yapılmamasına rağmen testleriniz bazen başarılı, bazen başarısız oluyorsa testlerin doğru sırada çalıştırıldığını doğrulamanız gerekebilir. Emülatörle yapılan etkileşimlerin çoğu asenkron olduğundan tüm asenkron kodun doğru şekilde sıralandığını tekrar kontrol edin. Sıralamayı, sözleri zincirleyerek veya await notasyonunu serbestçe kullanarak düzeltebilirsiniz.

Özellikle aşağıdaki asenkron işlemleri inceleyin:

  • Örneğin, initializeTestEnvironment ile güvenlik kuralları ayarlama.
  • Örneğin, db.collection("users").doc("alice").get() ile veri okuma ve yazma.
  • 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 bilgisi içerir. Yazılan tüm verileri bellekte depolar. Bu nedenle, emülatör her kapatıldığında veriler kaybolur. Aynı proje kimliğine karşı birden fazla test çalıştırıyorsanız her test, sonraki testleri etkileyebilecek veriler üretebilir. Bu davranışı atlamak için aşağıdaki yöntemlerden birini kullanabilirsiniz:

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

Test kurulumu çok karmaşık

Testinizi ayarlarken verileri, Cloud Firestore Security Rules'nızın aslında izin vermediği şekilde değiştirmek isteyebilirsiniz. Kurallarınız test kurulumunu karmaşık hale getiriyorsa kurulum adımlarınızda RulesTestEnvironment.withSecurityRulesDisabled kullanmayı deneyin. Böylece okuma ve yazma işlemleri PERMISSION_DENIED hatalarını tetiklemez.

Ardından, testiniz sırasıyla RulesTestEnvironment.authenticatedContext ve unauthenticatedContext kullanarak kimliği doğrulanmış veya doğrulanmamış bir kullanıcı olarak işlemler gerçekleştirebilir. Bu sayede, Cloud Firestore Security Rules öğenizin farklı durumları doğru şekilde izin verip vermediğini doğrulayabilirsiniz.