Quản lý và triển khai Quy tắc bảo mật của Firebase

Firebase cung cấp cho bạn một số công cụ để quản lý Rules, mỗi công cụ đều hữu ích trong những trường hợp cụ thể và mỗi công cụ đều sử dụng cùng một API quản lý Quy tắc bảo mật Firebase ở phần phụ trợ.

Bất kể bạn dùng công cụ nào để gọi API này, API quản lý sẽ:

  • Tiếp nhận một nguồn quy tắc: một tập hợp các quy tắc, thường là một tệp mã chứa các câu lệnh Firebase Security Rules.
  • Lưu trữ nguồn đã nhận dưới dạng một ruleset bất biến.
  • Theo dõi việc triển khai từng nhóm quy tắc trong một bản phát hành. Các dịch vụ hỗ trợ Quy tắc bảo mật Firebase sẽ tra cứu bản phát hành cho một dự án để đánh giá từng yêu cầu đối với một tài nguyên được bảo mật.
  • Cung cấp khả năng chạy các bài kiểm thử cú pháp và ngữ nghĩa của một nhóm quy tắc.

Sử dụng CLI Firebase

Với Firebase CLI, bạn có thể tải nguồn cục bộ lên và triển khai bản phát hành. Firebase Local Emulator Suite của CLI cho phép bạn thực hiện kiểm thử cục bộ đầy đủ các nguồn.

Việc sử dụng CLI cho phép bạn kiểm soát phiên bản của các quy tắc bằng mã ứng dụng và triển khai quy tắc trong quy trình triển khai hiện có.

Tạo tệp cấu hình

Khi định cấu hình dự án Firebase bằng giao diện dòng lệnh (CLI) Firebase, bạn sẽ tạo một tệp cấu hình .rules trong thư mục dự án. Sử dụng lệnh sau để bắt đầu định cấu hình dự án Firebase:

Cloud Firestore

// Set up Firestore in your project directory, creates a .rules file
firebase init firestore

Realtime Database

// Set up Realtime Database in your project directory, creates a .rules file
firebase init database

Cloud Storage

// Set up Storage in your project directory, creates a .rules file
firebase init storage

Chỉnh sửa và cập nhật quy tắc

Chỉnh sửa nguồn quy tắc ngay trong tệp cấu hình .rules.

Đảm bảo rằng mọi nội dung chỉnh sửa bạn thực hiện trong CLI Firebase đều được phản ánh trong bảng điều khiển Firebase hoặc bạn cập nhật nhất quán bằng bảng điều khiển Firebase hoặc CLI của Firebase. Nếu không, bạn có thể ghi đè mọi nội dung cập nhật đã thực hiện trong bảng điều khiển Firebase.

Kiểm thử bản cập nhật

Local Emulator Suite cung cấp trình mô phỏng cho tất cả các sản phẩm có bật Quy tắc bảo mật. Công cụ Security Rules cho mỗi trình mô phỏng đều thực hiện cả việc đánh giá cú pháp và ngữ nghĩa của các quy tắc, do đó vượt quá khả năng kiểm thử cú pháp mà Security Rules Management API cung cấp.

Nếu bạn đang làm việc với CLI, thì Suite là một công cụ tuyệt vời để kiểm thử Firebase Security Rules. Dùng Local Emulator Suite để kiểm thử các bản cập nhật cục bộ và xác nhận rằng Rules của ứng dụng có hành vi mà bạn muốn.

Triển khai bản cập nhật

Sau khi bạn cập nhật và kiểm thử Rules, hãy triển khai các nguồn này cho bản phát hành công khai.

Đối với Cloud Firestore Security Rules, hãy liên kết các tệp .rules với cơ sở dữ liệu mặc định và cơ sở dữ liệu có tên bổ sung bằng cách xem xét và cập nhật tệp firebase.json.

Sử dụng các lệnh sau để chỉ triển khai Rules hoặc triển khai chúng trong quy trình triển khai thông thường.

Cloud Firestore

// Deploy rules for all databases configured in your firebase.json
firebase deploy --only firestore:rules
// Deploy rules for the specified database configured in your firebase.json firebase deploy --only firestore:<databaseId>

Realtime Database

// Deploy your .rules file
firebase deploy --only database

Cloud Storage

// Deploy your .rules file
firebase deploy --only storage

Sử dụng bảng điều khiển Firebase

Bạn cũng có thể chỉnh sửa Rules các nguồn và triển khai chúng dưới dạng bản phát hành từ bảng điều khiển Firebase. Hoạt động kiểm thử cú pháp được thực hiện khi bạn chỉnh sửa trong giao diện người dùng của bảng điều khiển Firebase, còn hoạt động kiểm thử ngữ nghĩa có thể thực hiện bằng Playground Rules.

Chỉnh sửa và cập nhật quy tắc

  1. Mở Firebase console rồi chọn dự án của bạn.
  2. Sau đó, hãy chọn Realtime Database, Cloud Firestore hoặc Lưu trữ trong trình đơn điều hướng sản phẩm, rồi nhấp vào Quy tắc để chuyển đến trình chỉnh sửa Rules.
  3. Chỉnh sửa quy tắc ngay trong trình chỉnh sửa.

Kiểm thử bản cập nhật

Ngoài việc kiểm thử cú pháp trong giao diện người dùng của trình chỉnh sửa, bạn có thể kiểm thử hành vi ngữ nghĩa Rules bằng cách sử dụng cơ sở dữ liệu và tài nguyên lưu trữ của dự án ngay trong bảng điều khiển Firebase bằng Rules Playground. Mở màn hình Rules Playground (Sân chơi quy tắc) trong trình chỉnh sửa Rules, sửa đổi chế độ cài đặt rồi nhấp vào Run (Chạy). Tìm thông báo xác nhận ở đầu trình chỉnh sửa.

Triển khai bản cập nhật

Khi bạn hài lòng với nội dung cập nhật, hãy nhấp vào Xuất bản.

Sử dụng Admin SDK

Bạn có thể sử dụng Admin SDK cho các bộ quy tắc Node.js. Với quyền truy cập có lập trình này, bạn có thể:

  • Triển khai các công cụ, tập lệnh, trang tổng quan và quy trình CI/CD tuỳ chỉnh để quản lý các quy tắc.
  • Quản lý các quy tắc dễ dàng hơn trên nhiều dự án Firebase.

Khi cập nhật các quy tắc theo phương thức lập trình, bạn cần tránh thực hiện những thay đổi ngoài ý muốn đối với quyền kiểm soát truy cập của ứng dụng. Hãy viết mã Admin SDK của bạn với mục tiêu bảo mật là ưu tiên hàng đầu, đặc biệt là khi cập nhật hoặc triển khai các quy tắc.

Một điều quan trọng khác cần lưu ý là các bản phát hành Firebase Security Rules sẽ mất vài phút để truyền tải đầy đủ. Khi sử dụng Admin SDK để triển khai các quy tắc, hãy đảm bảo tránh tình huống tương tranh (race condition) trong đó ứng dụng của bạn ngay lập tức dựa vào các quy tắc chưa hoàn tất việc triển khai. Nếu trường hợp sử dụng của bạn yêu cầu cập nhật thường xuyên các quy tắc kiểm soát quyền truy cập, hãy cân nhắc các giải pháp sử dụng Cloud Firestore. Giải pháp này được thiết kế để giảm tình trạng xung đột dữ liệu mặc dù bạn cập nhật thường xuyên.

Ngoài ra, hãy lưu ý những giới hạn sau:

  • Các quy tắc phải nhỏ hơn 256 KiB văn bản được mã hoá UTF-8 khi được chuyển đổi tuần tự.
  • Một dự án có thể có tối đa 2.500 quy tắc được triển khai. Khi đạt đến giới hạn này, bạn phải xoá một số nhóm quy tắc cũ trước khi tạo nhóm quy tắc mới.

Tạo và triển khai bộ quy tắc Cloud Storage hoặc Cloud Firestore

Quy trình làm việc thông thường để quản lý các quy tắc bảo mật bằng Admin SDK có thể bao gồm 3 bước riêng biệt:

  1. Tạo nguồn tệp quy tắc (không bắt buộc)
  2. Tạo một bộ quy tắc
  3. Phát hành hoặc triển khai bộ quy tắc mới

SDK cung cấp một phương thức để kết hợp các bước này thành một lệnh gọi API duy nhất cho các quy tắc bảo mật Cloud StorageCloud Firestore. Ví dụ:

    const source = `service cloud.firestore {
      match /databases/{database}/documents {
        match /carts/{cartID} {
          allow create: if request.auth != null && request.auth.uid == request.resource.data.ownerUID;
          allow read, update, delete: if request.auth != null && request.auth.uid == resource.data.ownerUID;
        }
      }
    }`;
    // Alternatively, load rules from a file
    // const fs = require('fs');
    // const source = fs.readFileSync('path/to/firestore.rules', 'utf8');

    await admin.securityRules().releaseFirestoreRulesetFromSource(source);

Mẫu này cũng áp dụng cho các quy tắc Cloud StoragereleaseFirestoreRulesetFromSource().

Ngoài ra, bạn có thể tạo tệp quy tắc dưới dạng một đối tượng trong bộ nhớ, tạo bộ quy tắc và triển khai bộ quy tắc riêng biệt để kiểm soát chặt chẽ hơn các sự kiện này. Ví dụ:

    const rf = admin.securityRules().createRulesFileFromSource('firestore.rules', source);
    const rs = await admin.securityRules().createRuleset(rf);
    await admin.securityRules().releaseFirestoreRuleset(rs);

Cập nhật Realtime Database bộ quy tắc

Để cập nhật các quy tắc Realtime Database bằng Admin SDK, hãy sử dụng các phương thức getRules()setRules() của admin.database. Bạn có thể truy xuất các nhóm quy tắc ở định dạng JSON hoặc dưới dạng một chuỗi có kèm theo nhận xét.

Cách cập nhật một nhóm quy tắc:

    const source = `{
      "rules": {
        "scores": {
          ".indexOn": "score",
          "$uid": {
            ".read": "$uid == auth.uid",
            ".write": "$uid == auth.uid"
          }
        }
      }
    }`;
    await admin.database().setRules(source);

Quản lý bộ quy tắc

Để giúp quản lý các bộ quy tắc lớn, biểu tượng Admin SDK cho phép bạn liệt kê tất cả các quy tắc hiện có bằng biểu tượng admin.securityRules().listRulesetMetadata. Ví dụ:

    const allRulesets = [];
    let pageToken = null;
    while (true) {
      const result = await admin.securityRules().listRulesetMetadata(pageToken: pageToken);
      allRulesets.push(...result.rulesets);
      pageToken = result.nextPageToken;
      if (!pageToken) {
        break;
      }
    }

Đối với những triển khai rất lớn đạt đến giới hạn 2.500 quy tắc theo thời gian, bạn có thể tạo logic để xoá các quy tắc cũ nhất theo chu kỳ thời gian cố định. Ví dụ: để xoá tất cả các nhóm quy tắc được triển khai trong hơn 30 ngày:

    const thirtyDays = new Date(Date.now() - THIRTY_DAYS_IN_MILLIS);
    const promises = [];
    allRulesets.forEach((rs) => {
      if (new Date(rs.createTime) < thirtyDays) {
        promises.push(admin.securityRules().deleteRuleset(rs.name));
      }
    });
    await Promise.all(promises);
    console.log(`Deleted ${promises.length} rulesets.`);

Sử dụng REST API

Các công cụ được mô tả ở trên rất phù hợp với nhiều quy trình công việc, bao gồm cả việc quản lý Firebase Security Rules cho nhiều cơ sở dữ liệu Cloud Firestore trong dự án của bạn, nhưng bạn có thể muốn quản lý và triển khai Firebase Security Rules bằng chính API quản lý. API quản lý mang lại cho bạn sự linh hoạt cao nhất.

Ngoài ra, hãy lưu ý những giới hạn sau:

  • Các quy tắc phải nhỏ hơn 256 KiB văn bản được mã hoá UTF-8 khi được chuyển đổi tuần tự.
  • Một dự án có thể có tối đa 2.500 quy tắc được triển khai. Khi đạt đến giới hạn này, bạn phải xoá một số nhóm quy tắc cũ trước khi tạo nhóm quy tắc mới.

Tạo và triển khai các nhóm quy tắc Cloud Firestore hoặc Cloud Storage bằng REST

Các ví dụ trong phần này sử dụng Rules Firestore, mặc dù chúng cũng áp dụng cho Cloud Storage Rules.

Các ví dụ này cũng sử dụng cURL để thực hiện lệnh gọi API. Các bước thiết lập và truyền mã thông báo xác thực sẽ bị bỏ qua. Bạn có thể thử nghiệm API này bằng cách sử dụng API Explorer được tích hợp với tài liệu tham khảo.

Các bước thông thường để tạo và triển khai một bộ quy tắc bằng API quản lý là:

  1. Tạo nguồn tệp quy tắc
  2. Tạo một bộ quy tắc
  3. Phát hành (triển khai) bộ quy tắc mới.

Tạo nguồn

Giả sử bạn đang làm việc trên dự án Firebase secure_commerce và muốn triển khai Cloud Firestore Rules bị khoá vào một cơ sở dữ liệu trong dự án có tên east_store.

Bạn có thể triển khai các quy tắc này trong tệp firestore.rules.

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

Tạo một bộ quy tắc

Bây giờ, hãy tạo một vân tay được mã hoá base64 cho tệp này. Sau đó, bạn có thể sử dụng nguồn trong tệp này để điền tải trọng cần thiết để tạo một bộ quy tắc bằng lệnh gọi REST projects.rulesets.create. Ở đây, hãy dùng lệnh cat để chèn nội dung của firestore.rules vào tải trọng REST.

Để theo dõi, hãy liên kết sự kiện này với cơ sở dữ liệu east_store của bạn bằng cách đặt attachment_point thành east_store.

curl -X POST -d '{
  "source": {
    "files": [
      {
        "content": "' $(cat storage.rules) '",
        "name": "firestore.rules",
        "fingerprint": <sha fingerprint>
      },
    "attachment_point": "firestore.googleapis.com/databases/east_store"
    ]
  }
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets'

API này trả về một phản hồi xác thực và tên của bộ quy tắc, ví dụ: projects/secure_commerce/rulesets/uuid123.

Phát hành (triển khai) một bộ quy tắc

Nếu bộ quy tắc hợp lệ, bước cuối cùng là triển khai bộ quy tắc mới trong một bản phát hành có tên.

curl -X POST -d '{
  "name": "projects/secure_commerce/releases/cloud.firestore/east_store"  ,
  "rulesetName": "projects/secure_commerce/rulesets/uuid123"
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/releases'

Xin lưu ý rằng các bản phát hành Firebase Security Rules sẽ mất vài phút để lan truyền hoàn toàn. Khi sử dụng API REST quản lý để triển khai, hãy nhớ tránh các điều kiện xung đột trong đó ứng dụng của bạn ngay lập tức dựa vào các quy tắc chưa hoàn tất quá trình triển khai.

Cập nhật bộ quy tắc Realtime Database bằng REST

Realtime Database cung cấp giao diện REST riêng để quản lý Rules. Xem phần Quản lý Firebase Realtime Database Rules thông qua REST.

Quản lý bộ quy tắc bằng REST

Để giúp quản lý việc triển khai các quy tắc lớn, ngoài phương thức REST để tạo các quy tắc và bản phát hành, API quản lý còn cung cấp các phương thức để:

  • liệt kê, nhận và xoá ruleset
  • liệt kê, nhận và xoá các bản phát hành quy tắc

Đối với những triển khai rất lớn đạt đến giới hạn 2.500 quy tắc theo thời gian, bạn có thể tạo logic để xoá các quy tắc cũ nhất theo chu kỳ thời gian cố định. Ví dụ: để xoá tất cả các nhóm quy tắc được triển khai trong hơn 30 ngày, bạn có thể gọi phương thức projects.rulesets.list, phân tích cú pháp danh sách JSON gồm các đối tượng Ruleset trên các khoá createTime của chúng, sau đó gọi project.rulesets.delete trên các nhóm quy tắc tương ứng theo ruleset_id.

Kiểm thử nội dung cập nhật bằng REST

Cuối cùng, API quản lý cho phép bạn chạy các kiểm thử cú pháp và ngữ nghĩa trên các tài nguyên Cloud FirestoreCloud Storage trong các dự án sản xuất của bạn.

Việc kiểm thử bằng thành phần này của API bao gồm:

  1. Xác định một đối tượng JSON TestSuite để biểu thị một tập hợp các đối tượng TestCase
  2. Đang gửi TestSuite
  3. Phân tích cú pháp các đối tượng TestResult được trả về

Hãy xác định một đối tượng TestSuite có một TestCase duy nhất trong tệp testcase.json. Trong ví dụ này, chúng ta truyền nguồn ngôn ngữ Rules cùng với tải trọng REST, cùng với bộ kiểm thử để chạy trên các quy tắc đó. Chúng tôi chỉ định một kỳ vọng đánh giá Quy tắc và yêu cầu của máy khách mà bộ quy tắc sẽ được kiểm thử. Bạn cũng có thể chỉ định mức độ hoàn chỉnh của báo cáo kiểm thử bằng cách sử dụng giá trị "FULL" để cho biết kết quả của tất cả các biểu thức ngôn ngữ Rules phải được đưa vào báo cáo, bao gồm cả những biểu thức không khớp với yêu cầu.

 {
  "source":
  {
    "files":
    [
      {
        "name": "firestore.rules",
        "content": "service cloud.firestore {
          match /databases/{database}/documents {
            match /users/{userId}{
              allow read: if (request.auth.uid == userId);
            }
            function doc(subpath) {
              return get(/databases/$(database)/documents/$(subpath)).data;
            }
            function isAccountOwner(accountId) {
              return request.auth.uid == accountId 
                  || doc(/users/$(request.auth.uid)).accountId == accountId;
            }
            match /licenses/{accountId} {
              allow read: if isAccountOwner(accountId);
            }
          }
        }"
      }
    ]
  },
  "testSuite":
  {
    "testCases":
    [
      {
        "expectation": "ALLOW",
        "request": {
           "auth": {"uid": "123"},
           "path": "/databases/(default)/documents/licenses/abcd",
           "method": "get"},
        "functionMocks": [
            {
            "function": "get",
            "args": [{"exact_value": "/databases/(default)/documents/users/123"}],
            "result": {"value": {"data": {"accountId": "abcd"}}}
            }
          ]
      }
    ]
  }
}

Sau đó, chúng ta có thể gửi TestSuite này để đánh giá bằng phương thức projects.test.

curl -X POST -d '{
    ' $(cat testcase.json) '
}' 'https://firebaserules.googleapis.com/v1/projects/secure_commerce/rulesets/uuid123:test'

TestReport được trả về (chứa trạng thái THÀNH CÔNG/THẤT BẠI của kiểm thử, danh sách thông báo gỡ lỗi, danh sách các biểu thức Quy tắc đã truy cập và báo cáo đánh giá của các biểu thức đó) sẽ xác nhận rằng quyền truy cập được cho phép đúng cách với trạng thái THÀNH CÔNG.

Quản lý quyền đối với Cloud Storage Security Rules trên nhiều dịch vụ

Nếu tạo Cloud Storage Security Rules sử dụng nội dung tài liệu Cloud Firestore để đánh giá các điều kiện bảo mật, bạn sẽ được nhắc trong bảng điều khiển Firebase hoặc giao diện dòng lệnh Firebase để bật quyền kết nối hai sản phẩm.

Nếu bạn quyết định tắt tính năng bảo mật trên nhiều dịch vụ như vậy:

  1. Trước tiên, trước khi tắt tính năng này, hãy chỉnh sửa các quy tắc của bạn, xoá tất cả các câu lệnh sử dụng hàm Rules để truy cập vào Cloud Firestore. Nếu không, sau khi tính năng này bị vô hiệu hoá, các lượt đánh giá Rules sẽ khiến các yêu cầu Storage của bạn không thành công.

  2. Sử dụng trang IAM trong Google Cloud Console để xoá vai trò "Firebase Rules Firestore Service Agent" bằng cách làm theo hướng dẫn trên Cloud để thu hồi vai trò.

Bạn sẽ được nhắc bật lại tính năng này vào lần tiếp theo lưu các Quy tắc trên nhiều dịch vụ từ CLI Firebase hoặc bảng điều khiển Firebase.