Aturan Keamanan Firebase untuk Referensi Cloud Storage

Aturan Keamanan Firebase untuk Cloud Storage digunakan untuk menentukan siapa yang memiliki akses baca dan tulis ke file yang disimpan di Cloud Storage, serta bagaimana struktur file dan metadata apa yang terkandung di dalamnya. Aturan Keamanan Cloud Storage terdiri dari aturan yang mempertimbangkan request dan resource untuk mengizinkan atau menolak tindakan yang diinginkan, seperti mengunggah file atau mengambil metadata file. Dokumen referensi ini mencakup jenis aturan, properti request dan resource , jenis data yang digunakan oleh Aturan Keamanan Cloud Storage, dan cara terjadinya kesalahan.

Aturan

rule adalah ekspresi yang dievaluasi untuk menentukan apakah suatu request diperbolehkan untuk melakukan tindakan yang diinginkan.

Jenis

Mengizinkan

aturan allow terdiri dari metode, seperti read atau write , serta kondisi opsional. Saat aturan dijalankan, kondisi dievaluasi, dan jika kondisi bernilai true , metode yang diinginkan diperbolehkan; jika tidak, metode ini ditolak. Aturan allow tanpa syarat selalu mengizinkan metode yang diinginkan.

// Always allow method
allow <method>;

// Allow method if condition is true
allow <method>: if <condition>;

Saat ini, allow adalah satu-satunya jenis aturan yang didukung.

Metode Permintaan

Membaca

Metode read mencakup semua permintaan di mana data file atau metadata dibaca, termasuk pengunduhan file dan pembacaan metadata file.

// Always allow reads
allow read;

// Allow reads if condition evaluates to true
allow read: if <condition>;

Menulis

Metode write mencakup semua permintaan di mana data file atau metadata ditulis, termasuk unggahan file, penghapusan file, dan pembaruan metadata file.

// Always allow writes
allow write;

// Allow writes if condition evaluates to true
allow write: if <condition>;

Cocok

Aturan dijalankan ketika request pengguna (seperti unggahan atau pengunduhan file) cocok dengan jalur file yang dicakup oleh aturan. match terdiri dari jalur dan isi, yang harus berisi setidaknya satu aturan allow . Jika tidak ada jalur yang cocok, permintaan ditolak.

Anda dapat match jalur dengan nama lengkap, atau Anda dapat menyisipkan karakter pengganti untuk mencocokkan semua jalur yang sesuai dengan pola tertentu.

Segmen Jalur

single_segment

Anda dapat menggunakan segmen jalur tunggal untuk membuat aturan yang cocok dengan file yang disimpan di Cloud Storage.

// Allow read at "path" if condition evaluates to true
match /path {
  allow read: if <condition>;
}

Beberapa segmen jalur dan jalur bertingkat juga diperbolehkan:

// Allow read at "path/to/object" if condition evaluates to true
match /path {
  match /to {
    match /object {
      allow read: if <condition>;
    }
  }
}

{single_segment_wildcard}

Jika Anda ingin menerapkan aturan ke beberapa file di jalur yang sama, Anda dapat menggunakan segmen jalur karakter pengganti untuk mencocokkan semua file di jalur tertentu. Variabel wildcard dideklarasikan di jalur dengan membungkus variabel dalam kurung kurawal: {variable} . Variabel ini dapat diakses dalam pernyataan match sebagai string .

// Allow read at any path "/*", if condition evaluates to true
match /{single_path} {
  // Matches "path", "to", or "object" but not "path/to/object"
  allow read: if <condition>;
}

Beberapa segmen jalur dan jalur bertumpuk mungkin juga memiliki karakter pengganti:

// Allow read at any path "/path/*/newPath/*", if condition evaluates to true
match /path/{first_wildcard} {
  match /newPath/{second_wildcard} {
    // Matches "path/to/newPath/newObject" or "path/from/newPath/oldObject"
    allow read: if <condition>;
  }
}

{multi_segment_wildcard=**}

Jika Anda ingin mencocokkan sejumlah segmen jalur pada atau di bawah suatu jalur, Anda dapat menggunakan wildcard multi segmen, yang akan mencocokkan semua permintaan ke dan di bawah lokasi. Hal ini dapat berguna untuk menyediakan ruang penyimpanan formulir bebas kepada pengguna, atau membuat aturan yang cocok dengan banyak segmen jalur berbeda (seperti membuat kumpulan file yang dapat dibaca publik, atau mewajibkan autentikasi untuk semua penulisan).

Jalur wildcard multi segmen dideklarasikan serupa dengan wildcard segmen tunggal, dengan penambahan =** di akhir variabel: {variable=**} . Variabel wildcard multi-segmen tersedia dalam pernyataan match sebagai objek path .

// Allow read at any path "/**", if condition evaluates to true
match /{multi_path=**} {
  // Matches anything at or below this, from "path", "path/to", "path/to/object", ...
  allow read: if <condition>;
}

Meminta

Variabel request disediakan dalam kondisi untuk mewakili permintaan yang dibuat di jalur tersebut. Variabel request memiliki sejumlah properti yang dapat digunakan untuk memutuskan apakah akan mengizinkan permintaan masuk.

Properti

auth

Saat pengguna yang diautentikasi melakukan permintaan terhadap Cloud Storage, variabel auth diisi dengan uid pengguna ( request.auth.uid ) serta klaim JWT Firebase Authentication ( request.auth.token ).

request.auth.token berisi beberapa atau semua kunci berikut:

Bidang Keterangan
email Alamat email yang terkait dengan akun tersebut, jika ada.
email_verified true jika pengguna telah memverifikasi bahwa mereka memiliki akses ke alamat email . Beberapa penyedia secara otomatis memverifikasi alamat email yang mereka miliki.
phone_number Nomor telepon yang terkait dengan akun tersebut, jika ada.
name Nama tampilan pengguna, jika disetel.
sub UID Firebase pengguna. Ini unik dalam sebuah proyek.
firebase.identities Kamus semua identitas yang terkait dengan akun pengguna ini. Kunci kamus dapat berupa salah satu dari yang berikut: email , phone , google.com , facebook.com , github.com , twitter.com . Nilai kamus adalah rangkaian pengidentifikasi unik untuk setiap penyedia identitas yang terkait dengan akun. Misalnya, auth.token.firebase.identities["google.com"][0] berisi ID pengguna Google pertama yang terkait dengan akun tersebut.
firebase.sign_in_provider Penyedia masuk digunakan untuk mendapatkan token ini. Dapat berupa salah satu string berikut: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com .
firebase.tenant TenantId yang terkait dengan akun, jika ada. misalnya tenant2-m6tyz

Jika menggunakan autentikasi khusus, request.auth.token juga berisi klaim khusus apa pun yang ditentukan oleh pengembang.

Ketika pengguna yang tidak diautentikasi melakukan permintaan, request.auth adalah null .

// Allow requests from authenticated users
allow read, write: if request.auth != null;

path

Variabel path berisi jalur yang digunakan untuk menjalankan request .

// Allow a request if the first path segment equals "images"
allow read, write: if request.path[0] == 'images';

resource

Variabel resource berisi metadata file yang sedang diunggah atau metadata yang diperbarui untuk file yang sudah ada. Hal ini terkait dengan variabel resource , yang berisi metadata file saat ini di jalur yang diminta, bukan metadata baru.

// Allow a request if the new value is smaller than 5MB
allow read, write: if request.resource.size < 5 * 1024 * 1024;

request.resource berisi properti berikut dari resource :

Properti
name
bucket
metadata
size
contentType

time

Variabel time berisi stempel waktu yang mewakili waktu server saat ini saat permintaan sedang dievaluasi. Anda dapat menggunakan ini untuk memberikan akses berbasis waktu ke file, seperti: hanya mengizinkan file diunggah hingga tanggal tertentu, atau hanya mengizinkan file dibaca hingga satu jam setelah diunggah.

// Allow a read if the file was created less than one hour ago
allow read: if request.time < resource.timeCreated + duration.value(1, 'h');

Banyak fungsi yang disediakan untuk menulis aturan menggunakan stempel waktu dan durasi .

Sumber

Variabel resource berisi metadata file untuk file di Cloud Storage, seperti nama file, ukuran, waktu pembuatan, dan metadata khusus.

Properti

name

String yang berisi nama lengkap file, termasuk path ke file tersebut.

// Allow reads if the resource name is "path/to/object"
allow read: if resource.name == 'path/to/object'

bucket

String yang berisi keranjang Google Cloud Storage tempat file ini disimpan.

// Allow reads of all resources in your bucket
allow read: if resource.bucket == '<your-cloud-storage-bucket>'

generation

Int berisi pembuatan objek Google Cloud Storage dari file tersebut. Digunakan untuk pembuatan versi objek.

// Allow reads if the resource matches a known object version
allow read: if resource.generation == <known-generation>

metageneration

Int berisi metagenerasi objek Google Cloud Storage dari file tersebut. Digunakan untuk pembuatan versi objek.

// Allow reads if the resource matches a known object metadata version
allow read: if resource.metageneration == <known-generation>

size

Int berisi ukuran file dalam byte.

// Allow reads if the resource is less than 10 MB
allow read: if resource.size < 10 * 1024 * 1024;

timeCreated

Stempel waktu yang menunjukkan kapan file dibuat.

// Allow reads if the resource was created less than an hour ago
allow read: if resource.timeCreated < request.time + duration.value(60, "m")

updated

Stempel waktu yang menunjukkan kapan file terakhir diperbarui.

// Allow reads if the resource was updated less than an hour ago
allow read: if resource.updated < request.time + duration.value(60, "m")

md5Hash

Sebuah string yang berisi hash MD5 dari file tersebut.

// Allow writes if the hash of the uploaded file is the same as the existing file
allow write: if request.resource.md5Hash == resource.md5Hash;

crc32c

Sebuah string yang berisi hash crc32c dari file tersebut.

// Allow writes if the hash of the uploaded file is the same as the existing file
allow write: if request.resource.crc32c == resource.crc32c;

etag

Sebuah string yang berisi etag file.

// Allow writes if the etag matches a known object etag
allow write: if resource.etag == <known-generation>

contentDisposition

Sebuah string yang berisi disposisi konten file.

// Allow reads if the content disposition matches a certain value
allow read: if resource.contentDisposition == 'inlined';

contentEncoding

Sebuah string yang berisi pengkodean konten file.

// Allow reads if the content is encoded with gzip
allow read: if resource.contentEncoding == 'gzip';

contentLanguage

Sebuah string yang berisi bahasa konten file.

// Allow reads if the content language is Japanese
allow read: if resource.contentLanguage == 'ja';

contentType

Sebuah string yang berisi tipe konten file.

// Allow reads if the content type is PNG.
allow read: if resource.contentType == 'image/png';

metadata

Map<String, String> berisi bidang metadata tambahan yang disediakan pengembang.

// Allow reads if a certain metadata field matches a desired value
allow read: if resource.metadata.customProperty == 'customValue';

firestore.get dan firestore.ada

Fungsi firestore.get() dan firestore.exists() memungkinkan Anda mengakses dokumen di Cloud Firestore untuk mengevaluasi kriteria otorisasi yang kompleks.

Fungsi firestore.get() dan firestore.exists() mengharapkan jalur dokumen yang ditentukan sepenuhnya. Saat menggunakan variabel untuk membuat jalur untuk firestore.get() dan firestore.exists() , Anda perlu meng-escape variabel secara eksplisit menggunakan sintaks $(variable) .

firestore.dapatkan

Dapatkan konten dokumen Cloud Firestore.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.uid)).data.memberships
    }
  }
}

firestore.ada

Periksa apakah dokumen Cloud Firestore ada.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.uid))
    }
  }
}

Melayani

service ini merupakan deklarasi pertama dalam file Aturan Keamanan Cloud Storage, dan menentukan layanan mana yang akan menerapkan aturan ini.

Nama

name

Nama aturan layanan akan berlaku. Satu-satunya nilai saat ini adalah firebase.storage .

// Specify the service name
service firebase.storage {
  match /b/{bucket}/o {
    ...
  }
}

Tipe Data

Bahasa Aturan memungkinkan Anda memeriksa jenis menggunakan operator is .

// For example
a is null
a is string

null

Tipe data null mewakili nilai yang tidak ada.

allow read: if request.auth != null;

bool

Tipe bool mewakili nilai boolean true atau false .

allow read: if true;   // always succeeds
allow write: if false; // always fails

Perbandingan

Nilai Boolean dapat dibandingkan menggunakan operator == != .

Operasi Boolean

Operasi Ekspresi
AND x && y
OR x || y
NOT !x

Operasi korsleting, dan dapat mengembalikan true , false , atau Error .

allow read: if true || false;   // always succeeds, short circuits at true
allow write: if false && true; // always fails, short circuits at false

int dan float

Tipe int dan float mewakili angka. Int adalah: 0 , 1 , -2 , dst. , sedangkan float adalah: 1.0 , -2.0 , 3.33 , dst.

Int adalah nilai 64-bit yang ditandatangani, dan float adalah nilai yang sesuai dengan IEEE 754 64-bit. Nilai bertipe int akan dipaksa menjadi float ketika digunakan dalam perbandingan dan operasi aritmatika dengan nilai float .

Perbandingan

Int dan float dapat dibandingkan dan diurutkan menggunakan operator == , != , > , < , >= , dan <= .

Hitung

Int dan float dapat ditambahkan, dikurangi, dikalikan, dibagi, dimodulasi, dan dinegasikan:

Operasi Ekspresi
Tambahan x + y
Pengurangan x - y
Perkalian x * y
Divisi x / y
Modulo x % y
Penyangkalan -x

Fungsi matematika

Aturan Keamanan Firebase untuk Cloud Storage juga menyediakan sejumlah fungsi pembantu matematika untuk menyederhanakan ekspresi:

Fungsi Keterangan
math.ceil(x) Batas atas nilai numerik
math.floor(x) Lantai nilai numerik
math.round(x) Bulatkan nilai input ke int terdekat
math.abs(x) Nilai mutlak dari masukan
math.isInfinite(x) Uji apakah nilainya ±∞ , mengembalikan bool
math.isNaN(x) Uji apakah nilainya bukan angka NaN , kembalikan bool

string

Perbandingan

String dapat dibandingkan dan diurutkan secara leksografis menggunakan operator == , != , > , < , >= , dan <= .

Rangkaian

String dapat digabungkan menggunakan operator + .

// Concatenate a file name and extension
'file' + '.txt'

Indeks dan Rentang

Operator index , string[] , mengembalikan string yang berisi karakter pada indeks yang disediakan dalam string.

// Allow reads of files that begin with 'a'
match /{fileName} {
  allow read: if fileName[0] == 'a';
}

Operator range , string[i:j] , mengembalikan string yang berisi karakter antara indeks yang ditentukan, dari i (inklusif) hingga j (eksklusif). Jika i atau j tidak ditentukan, maka defaultnya adalah 0 dan ukuran string, namun setidaknya i atau j harus ditentukan agar rentangnya valid.

// Allow reads of files that begin with 'abcdef'
match /{fileName} {
  allow read: if fileName[0:6] == 'abcdef';
}

Operator index dan range akan menghasilkan kesalahan jika indeks yang diberikan melebihi batas string.

size

Mengembalikan jumlah karakter dalam string.

// Allow files with names less than 10 characters
match /{fileName} {
  allow write: if fileName.size() < 10;
}

matches

Melakukan pencocokan ekspresi reguler, mengembalikan nilai true jika string cocok dengan ekspresi reguler yang diberikan. Menggunakan sintaks Google RE2 .

// Allow writes to files which end in ".txt"
match /{fileName} {
  allow write: if fileName.matches('.*\\.txt')
}

split

Memisahkan string berdasarkan ekspresi reguler yang disediakan dan mengembalikan list string. Menggunakan sintaks Google RE2 .

// Allow files named "file.*" to be uploaded
match /{fileName} {
  allow write: if fileName.split('.*\\..*')[0] == 'file'
}

path

Jalur adalah nama seperti direktori dengan pencocokan pola opsional. Adanya garis miring / menandakan awal suatu segmen jalur.

path

Mengonversi argumen string menjadi path .

// Allow reads on a specific file path
match /{allFiles=**} {
  allow read: if allFiles == path('/path/to/file');
}

timestamp

Stempel waktu dalam UTC, dengan kemungkinan nilai dimulai pada 0001-01-01T00.00.00Z dan berakhir pada 9999-12-31T23.59.59Z.

Perbandingan

Stempel waktu dapat dibandingkan dan diurutkan menggunakan operator == , != , > , < , >= , dan <= .

Hitung

Stempel waktu mendukung penambahan dan pengurangan antara stempel waktu dan durasi sebagai berikut:

Ekspresi Hasil
timestamp + duration timestamp
duration + timestamp timestamp
timestamp - duration timestamp
timestamp - timestamp duration
duration + duration duration
duration - duration duration

date

Nilai timestamp yang hanya berisi year , month , dan day .

// Allow reads on the same day that the resource was created.
allow read: if request.time.date() == resource.timeCreated.date()

year

Nilai tahun dalam satuan int, dari 1 hingga 9999.

// Allow reads on all requests made before 2017
allow read: if request.time.year() < 2017

month

Nilai bulan sebagai int, dari 1 hingga 12.

// Allow reads on all requests made during the month of January
allow read: if request.time.month() == 1;

day

Hari saat ini dalam sebulan sebagai int, dari 1 hingga 31.

// Allow reads on all requests made during the first day of each month
allow read: if request.time.day() == 1;

time

Nilai duration yang berisi waktu saat ini.

// Allow reads on all requests made before 12PM
allow read: if request.time.time() < duration.time(12, 0, 0, 0);

hours

Nilai jam sebagai int, dari 0 hingga 23.

// Allow reads on all requests made before 12PM
allow read: if request.time.hours() < 12;

minutes

Nilai menit sebagai int, dari 0 hingga 59.

// Allow reads during even minutes of every hour
allow read: if request.time.minutes() % 2 == 0;

seconds

Nilai detik sebagai int, dari 0 hingga 59.

// Allow reads during the second half of each minute
allow read: if request.time.seconds() > 29;

nanos

Detik pecahan dalam nano sebagai int.

// Allow reads during the first 0.1 seconds of each second
allow read: if request.time.nanos() < 100000000;

dayOfWeek

Hari dalam seminggu, dari 1 (Senin) hingga 7 (Minggu).

// Allow reads on weekdays (Monday to Friday)
allow read: if request.time.dayOfWeek() < 6;

dayOfYear

Hari pada tahun ini, dari 1 hingga 366.

// Allow reads every fourth day
allow read: if request.time.dayOfYear() % 4 == 0;

toMillis

Mengembalikan jumlah milidetik saat ini sejak zaman Unix.

// Allow reads if the request is made before a specified time
allow read: if request.time.toMillis() < <milliseconds>;

duration

Nilai durasi direpresentasikan sebagai detik ditambah pecahan detik dalam nanodetik.

Perbandingan

Durasi dapat dibandingkan dan diurutkan menggunakan operator == , != , > , < , >= , dan <= .

Hitung

Durasi mendukung penambahan dan pengurangan antara stempel waktu dan durasi sebagai berikut:

Ekspresi Hasil
timestamp + duration timestamp
duration + timestamp timestamp
timestamp - duration timestamp
timestamp - timestamp duration
duration + duration duration
duration - duration duration

seconds

Jumlah detik dalam durasi saat ini. Harus antara -315,576,000,000 dan +315,576,000,000 inklusif.

nanos

Jumlah pecahan detik (dalam nanodetik) dari durasi saat ini. Harus antara -999.999.999 dan +999.999.999 inklusif. Untuk detik bukan nol dan nanodetik bukan nol, tanda keduanya harus sesuai.

duration.value

Durasi dapat dibuat menggunakan fungsi duration.value(int magnitude, string units) yang menghasilkan durasi waktu dari besaran dan satuan tertentu.

// All of these durations represent one hour:
duration.value(1, "h")
duration.value(60, "m")
duration.value(3600, "s")

unit yang mungkin adalah:

Durasi unit
Minggu w
hari d
Jam h
Menit m
Detik s
Milidetik ms
nanodetik ns

duration.time

Durasi dapat dibuat menggunakan fungsi duration.time(int hours, int minutes, int seconds, int nanoseconds) , yang membuat durasi waktu dari jam, menit, detik, dan nanodetik tertentu.

// Create a four hour, three minute, two second, one nanosecond duration
duration.time(4, 3, 2, 1)

list

Daftar berisi larik nilai yang diurutkan, yang dapat bertipe: null , bool , int , float , string , path , list , map , timestamp , atau duration .

Diberikan x dan y bertipe list dan i dan j bertipe int

Penciptaan

Untuk membuat daftar, tambahkan nilai di antara tanda kurung:

// Create a list of strings
['apples', 'grapes', 'bananas', 'cheese', 'goats']

Perbandingan

Daftar dapat dibandingkan menggunakan operator == != . Kesetaraan dua daftar mengharuskan semua nilai sama.

Indeks dan Rentang

Operator index , list[] , mengembalikan item pada indeks yang disediakan dalam daftar.

// Allow reads of all files that begin with 'a'
match /{fileName} {
  allow read: if fileName[0] == 'a';
}

Operator range , list[i:j] , mengembalikan semua item dalam daftar antara indeks yang ditentukan, dari i (inklusif) hingga j (eksklusif). Jika i atau j tidak ditentukan, maka defaultnya adalah 0 dan ukuran daftar, namun setidaknya i atau j harus ditentukan agar rentang tersebut valid.

// Allow reads of all files that begin with 'abcdef'
match /{fileName} {
  allow read: if fileName[0:6] == 'abcdef';
}

in

Mengembalikan true jika nilai yang diinginkan ada dalam daftar atau false jika tidak ada.

// Allow read if a filename has the string 'txt' in it
match /{fileName} {
  allow read: if 'txt' in fileName.split('\\.');
}

join

Menggabungkan daftar string menjadi satu string, dipisahkan oleh string tertentu.

// Allow reads if the joined array is 'file.txt'
allow read: if ['file', 'txt'].join('.') == 'file.txt';

size

Jumlah item dalam daftar.

// Allow read if there are three items in our list
allow read: if ['foo', 'bar', 'baz'].size() == 3;

hasAll

Mengembalikan true jika semua nilai ada dalam daftar.

// Allow read if one list has all items in the other list
allow read: if ['file', 'txt'].hasAll(['file', 'txt']);

map

Peta berisi pasangan kunci/nilai, dengan kunci berupa string dan nilai dapat berupa: null , bool , int , float , string , path , list , map , timestamp , atau duration .

Penciptaan

Untuk membuat peta, tambahkan pasangan kunci/nilai di antara kurung kurawal:

// Create a map of strings to strings
{
  'mercury': 'mars',
  'rain': 'cloud',
  'cats': 'dogs',
}

Perbandingan

Peta dapat dibandingkan menggunakan operator == != . Kesetaraan dua peta mengharuskan semua kunci ada di kedua peta dan semua nilainya sama.

Indeks

Nilai dalam peta diakses dengan menggunakan notasi tanda kurung atau titik:

// Access custom metadata properties
allow read: if resource.metadata.property == 'property'
allow write: if resource.metadata['otherProperty'] == 'otherProperty'

Jika kunci tidak ada, error akan dikembalikan.

in

Mengembalikan true jika kunci yang diinginkan ada di peta atau false jika tidak ada.

// Allow reads if a property is present in the custom metadata
allow read: if property in resource.metadata;

size

Jumlah kunci di peta.

// Allow reads if there's exactly one custom metadata key
allow read: if resource.metadata.size() == 1;

keys

Daftar semua kunci di peta.

// Allow reads if the first metadata key is 'myKey'
allow read: if resource.metadata.keys()[0] == 'myKey';

values

Daftar semua nilai di peta, dalam urutan kunci.

// Allow reads if the first metadata value is 'myValue'
allow read: if resource.metadata.values()[0] == 'myValue';

Kesalahan

Evaluasi Kesalahan

Aturan Keamanan Firebase untuk Cloud Storage melanjutkan evaluasi ketika terjadi kesalahan. Ini berguna karena kondisional && dan || ekspresi dapat menyerap kesalahan jika kondisinya akan mengalami hubungan pendek menjadi false atau true . Contohnya:

Ekspresi Hasil
error && true error
error && false false
error || true true
error || false error

Tempat umum munculnya kesalahan adalah: pembagian dengan nol, mengakses nilai dalam daftar atau peta yang tidak ada, dan meneruskan nilai dengan tipe yang salah ke suatu fungsi.

// Error if resource.size is zero
allow read: if 1000000 / resource.size;

// Error, key doesn't exist
allow read: if resource.metadata.nonExistentKey == 'value';

// Error, no unit 'y' exists
allow read: if request.time < resource.timeCreated + duration.value(1, 'y');