• トップ
  • ブログ一覧
  • テスト駆動で学ぶ Firestore セキュリティルール【CI 編】
  • テスト駆動で学ぶ Firestore セキュリティルール【CI 編】

    広告メディア事業部広告メディア事業部
    2020.06.29

    IT技術

    CI 環境におけるセキュリティルールの自動テスト

    これまで、「テスト駆動で学ぶ Firestore セキュリティルール」をテーマに、実例を交えてセキュリティルールの仕様や利用可能な関数について解説してきました。

    せっかく作成したテストであれば、「GitHub Actions」や「CircleCI」などの CI 環境で自動テストに活用したいところです。

    今回は、ここまでの記事とは少し雰囲気をかえて、CI 環境でのセキュリティルールの自動テストについて解説していきます。

    これまでの記事については、以下の記事を参照してください。

    データ検証編はこちら

    「データ検証編」では、リクエストデータ、データベース上のデータの参照などについて解説

    featureImg2020.04.22テスト駆動で学ぶ Firestore セキュリティルール 【データ検証編 / 前編】テスト駆動で商品データのルールを実装するこの記事では、セキュリティルールによるデータ検証について、商品データのルールを...

    データ比較編はこちら

    「データ比較編」では、データの比較や型チェックなどについて解説

    featureImg2020.05.07テスト駆動で学ぶ Firestore セキュリティルール 【データ比較編 / 前編】テスト駆動で書籍コレクションのルールを実装するこの記事では、前編・後編の二回に分けて、Firestore セキュリティ...

    カスタム関数編はこちら

    「カスタム関数編」では、「比較編」で作成したルールをもとに、カスタム関数の使い方を解説

    featureImg2020.06.04テスト駆動で学ぶ Firestore セキュリティルール【カスタム関数編:第1回】テスト駆動で成績データコレクションのルールを実装する【第1回】この記事では、全4回に分けて、Firestore セキュ...

    対象読者

    本記事では、以下のいずれかの CI ツールを利用している、または利用予定の読者を想定しています。

    1. GitHub Actions
    2. CircleCI
    3. GitLab CI/CD

    ※ GitHub Actions については、GitHub アカウントをお持ちであれば、本記事で紹介する設定ファイルの追加だけで動作確認が可能です。

    注意書き

    本記事では、各 CI ツール( GitHub Actions、CircleCI、GitLab CI/CD )でのセキュリティルールのテストについて、解説していきます。

    各 CI ツールの基本的な使用方法や構築方法などの解説はいたしませんので、予めご了承ください。

    また、CI ツールごとの解説は独立した内容となっています。

    利用しない、または利用予定のない CI ツールの解説は飛ばして読み進めても問題ありません。

    簡単な流れ

    本記事では、以下のような流れで、「CI 環境でのセキュリティルールのテスト」について解説していきます。

    1. CI 環境で使用するテスト環境とテストコード、セキュリティルールを用意
    2. ローカル環境でのテストの流れのおさらいと、テスト成功チェック
    3. CI 環境でのテストの設定について解説
    4. 人気のある3つの CI ツールにおける、セキュリティルールのテストの設定例を紹介
    5. まとめ

    前準備

    まずは、CI 環境で使用する「テスト環境」と「テストコード」、「テスト対象のセキュリティルール」を用意します。

    以下のリポジトリに、本記事のコードをまとめてあります。

    【rightcode/firestore-security-rules-test_ci-setting】
    https://github.com/rightcode/firestore-security-rules-test_ci-setting

    セットアップ

    以下のコマンドを実行して、テスト環境をセットアップしてください。

    1git clone "https://github.com/rightcode/firestore-security-rules-test_ci-setting" sandbox
    2cd sandbox
    3git checkout refs/tags/test-environment

    「masterブランチ」に完成ソースコードを設置してあります。

    本記事中で解説するソースコードを確認したい場合は、以下のコマンドで 「masterブランチ」をチェックアウトしてください。

    1git checkout master

    ※ コードの調整などにより、本記事の内容とは記述が若干異なる場合があります。

    使用するテストとセキュリティルールの準備

    テストコードとテスト対象となるルールは、先述のリポジトリに含まれているサンプルテストサンプルルールを使用します。

    サンプルテスト

    サンプルテストの中身は、以下の通りです。

    1process.env.FIRESTORE_EMULATOR_HOST = "localhost:58080";
    2
    3import {FirestoreTestSupporter} from "firestore-test-supporter";
    4
    5import * as path from "path";
    6import * as firebase from "@firebase/testing";
    7
    8describe("サンプルテスト", () => {
    9    const supporter = new FirestoreTestSupporter("my-test-project", path.join(__dirname, "firestore.rules"));
    10
    11    beforeEach(async () => {
    12        await supporter.loadRules();
    13    });
    14
    15    afterEach(async () => {
    16        await supporter.cleanup()
    17    });
    18
    19    describe('デフォルトで全てのアクセスを拒否', () => {
    20        test('読み込み拒否', async () => {
    21            const db = supporter.getFirestore();
    22            const doc = db.collection('default').doc('dummy');
    23            await firebase.assertFails(doc.get())
    24        });
    25
    26        test('書き込み拒否', async () => {
    27            const db = supporter.getFirestore();
    28            const doc = db.collection('default').doc('dummy');
    29            await firebase.assertFails(doc.set({data: 'dummy'}))
    30        });
    31
    32        test('認証付き読み込み拒否', async () => {
    33            const db = supporter.getFirestoreWithAuth();
    34            const doc = db.collection('default').doc('dummy');
    35            await firebase.assertFails(doc.get())
    36        });
    37
    38        test('認証付き書き込み拒否', async () => {
    39            const db = supporter.getFirestoreWithAuth();
    40            const doc = db.collection('default').doc('dummy');
    41            await firebase.assertFails(doc.set({data: 'dummy'}))
    42        });
    43    });
    44});

    サンプルテストは、全てのアクセスの拒否を確認する内容のテストになっています。

    サンプルルール

    サンプルルールの中身は、以下の通りです。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    allow read, write: if false;
    5  }
    6}

    サンプルルールは、サンプルテストの要件を満たす、全てのアクセスを拒否するセキュリティルールとなっています。

    ローカル環境でテストチェック

    おおよそ、ローカル環境でのテスト実行の流れを CI 環境でのテストの設定にも適用します。

    ローカル環境でテストが通ることをチェックしつつ、簡単にテスト実行の流れを確認しておきます。

    npm パッケージをインストール

    以下のコマンドを実行して、必要となる npm パッケージをインストールしてください。

    1npm install

    Firebase CLI ツールをインストール

    Firebase CLI ツールをインストールしていない場合は、以下のコマンドを実行してインストールしてください。

    1npm install -g firebase-tools

    Firestore エミュレータを起動

    以下のコマンドを実行して、Firestore エミュレータを起動してください。

    1firebase setup:emulators:firestore
    2firebase emulators:start --only firestore

    テスト実行

    以下のコマンドで、テストを実行してください。

    1npm run test

    以下のように結果が表示されれば、テストは成功です!

    1 PASS  tests/sample/firestore.rules.test.ts (6.033s)
    2  サンプルテスト
    3    デフォルトで全てのアクセスを拒否
    4読み込み拒否 (4092ms)
    5書き込み拒否 (55ms)
    6認証付き読み込み拒否 (45ms)
    7認証付き書き込み拒否 (54ms)
    8
    9Test Suites: 1 passed, 1 total
    10Tests:       4 passed, 4 total
    11Snapshots:   0 total
    12Time:        6.095s, estimated 8s
    13Ran all test suites.

    ローカル環境でのテストの成功が確認できたので、続いて、CI 環境でのテストの設定について解説していきます。

    CI 環境でのテスト設定方針

    簡単な流れ

    各CIツールでのテストは、おおよそ、以下の流れでコマンドを実行していきます。

    1. npm パッケージのインストール
    2. firebase-tools のインストール
    3. Firestore エミュレータをインストール
    4. エミュレータをバックグラウンド起動
    5. エミュレータの起動待機
    6. テスト実行

    ローカル環境でのテスト環境のセットアップ、テスト実行の流れとおおよそ同じ内容ですが、以下のような違いもあります。

    1. CI 環境でのテストに合わせ、firebase-tools をローカルインストールする
    2. CI 用に調整したテストスクリプトを使用する
    3. Firestore エミュレータの起動をバックグラウンドで行う必要がある

    注意事項

    特に留意しておきたいのが、エミュレータの起動です。

    CI 環境でのテストの場合、Firestore エミュレータをバックグラウンドで起動しないと、処理がそこで停滞してしまうため、肝心のテストが実行されません。

    また、エミュレータが起動するまでに少し時間がかかるため、テストの実行前にエミュレータの起動待機時間の設定が必要になります。

    次の項目では、以上の点に気を付けて、本題である「CI ツール別のテスト設定例」を紹介していきたいと思います。

    CI ツール別のテスト設定例

    CI ツールごとの設定の解説は、独立した内容となっています。

    利用しない CI ツールの解説は、飛ばして読み進めても問題ありません。

    また、テストに失敗する場合は、後述の「テストに失敗する場合は」の項目をチェックしてください。

    GitHub Actions の場合

    「GitHub Actions」でセキュリティルールをテストする場合は、.github/workflows ディレクトリを作成して、 test.yml ファイルを追加してください。

    .github/workflows/test.yml を作成したら、以下のように記述してください。

    1name: test
    2
    3on: [push]
    4
    5jobs:
    6  test:
    7    runs-on: ubuntu-latest
    8
    9    strategy:
    10      matrix:
    11        node-version: [12.x]
    12
    13    steps:
    14      - name: リポジトリのチェックアウト
    15        uses: actions/checkout@v2
    16
    17      - name: Node.js ${{ matrix.node-version }} セットアップ
    18        uses: actions/setup-node@v1
    19        with:
    20          node-version: ${{ matrix.node-version }}
    21
    22      - name: パッケージインストール
    23        run: npm install
    24
    25      - name: firebase-toolsをインストール
    26        run: npm install firebase-tools
    27
    28      - name: Firestoreエミュレータをインストール
    29        run: npm run setup:emu:firestore
    30
    31      - name: エミュレータの起動
    32        run: npm run emu:start:firestore &
    33
    34      - name: エミュレータの起動待機...
    35        run: sleep 10
    36
    37      - name: テスト実行
    38        run: npm run ci-test

    上記の設定のあと、GitHub にソースコードをプッシュすると、GitHub Actions で test ワークフローがスタートし、テストが実行されます。

    結果

    ワークフローの実行結果は、以下のようになります。

    テスト結果は、以下の通りです。

    1PASS tests/sample/firestore.rules.test.ts
    2  サンプルテスト
    3    デフォルトで全てのアクセスを拒否
    4読み込み拒否 (1463ms)
    5書き込み拒否 (149ms)
    6認証付き読み込み拒否 (99ms)
    7認証付き書き込み拒否 (87ms)
    8
    9Test Suites: 1 passed, 1 total
    10Tests:       4 passed, 4 total
    11Snapshots:   0 total
    12Time:        4.655s
    13Ran all test suites.

    以上で、GitHub Actions でのセキュリティルールのテストの設定は完了です。

    CircleCI の場合

    「CircleCI」でセキュリティルールをテストする場合は、.circleci ディレクトリを作成して、 config.yml ファイルを追加してください。

    .circleci/config.yml を追加したら、以下のように記述してください。

    1version: 2.1
    2jobs:
    3  test:
    4    docker:
    5      - image: circleci/node:lts-browsers
    6    steps:
    7      - checkout
    8      - run:
    9          name: パッケージインストール
    10          command: npm install
    11      - run:
    12          name: firebase-toolsをインストール
    13          command: npm install firebase-tools
    14      - run:
    15          name: Firestoreエミュレータをインストール
    16          command: npm run setup:emu:firestore
    17      - run:
    18          name: エミュレータの起動 & テスト実行
    19          command: npm run emu:start:firestore & sleep 10; npm run ci-test
    20workflows:
    21  test:
    22    jobs:
    23      - test

    config.yml ファイルを設定したら、CircleCI サイトでテスト対象の GitHub リポジトリをプロジェクトに追加してください。

    上記の設定のあと、GitHub にソースコードをプッシュすると、CircleCI の test ワークフローがスタートし、テストが実行されます。

    結果

    ワークフローの実行結果は、以下のようになります。

    テスト結果は、以下の通りです!

    1 PASS  tests/sample/firestore.rules.test.ts
    2  サンプルテスト
    3    デフォルトで全てのアクセスを拒否
    4読み込み拒否 (776ms)
    5書き込み拒否 (111ms)
    6認証付き読み込み拒否 (70ms)
    7認証付き書き込み拒否 (63ms)
    8
    9Test Suites: 1 passed, 1 total
    10Tests:       4 passed, 4 total
    11Snapshots:   0 total
    12Time:        3.127s
    13Ran all test suites.

    以上で、CircleCI でのセキュリティルールのテスト設定は完了です!

    GitLab CI/CD の場合

    「GitLab CI/CD」でセキュリティルールをテストする場合は、クローンしたリポジトリのルートに .gitlab-ci.yml ファイルを追加してください。

    .gitlab-ci.yml を追加したら、以下のように記述してください。

    1stages:
    2  - test
    3
    4test:
    5  image: circleci/node:lts-browsers
    6  stage: test
    7  script:
    8    - npm install
    9    - npm install firebase-tools
    10    - npm run setup:emu:firestore
    11    - npm run emu:start:firestore &
    12    - sleep 10
    13    - npm run ci-test

    上記の設定のあと、GitLab にソースコードをプッシュすると、GitLab CI/CD でパイプラインがスタートして、テストが実行されます。

    結果

    パイプラインの実行結果は、以下のようになります。

    テスト結果は、以下の通りです。

    1PASS tests/sample/firestore.rules.test.ts (5.357s)
    2  サンプルテスト
    3    デフォルトで全てのアクセスを拒否
    4読み込み拒否 (1456ms)
    5書き込み拒否 (210ms)
    6認証付き読み込み拒否 (127ms)
    7認証付き書き込み拒否 (107ms)
    8
    9Test Suites: 1 passed, 1 total
    10Tests:       4 passed, 4 total
    11Snapshots:   0 total
    12Time:        5.394s
    13Ran all test suites.

    以上で、GitLab CI/CD でのセキュリティルールのテスト設定は完了です。

    テストに失敗する場合は

    一部、または全てのテストに失敗する場合は、エミュレータが待機時間内で起動していない可能性があります。

    待機時間は長めに設定していますが、場合によっては、テスト開始までにエミュレータが起動しない事があります。

    テストが失敗する場合は、エミュレータの起動待機時間を調整してみてください。

    逆に、起動待機時間が原因のテスト失敗がないのであれば、3~5秒程度に調整しても問題ありません。

    まとめ

    今回は、CI 環境でのセキュリティルールのテストについて解説してみました。

    今回紹介した CI ツールの中でも、GitHub Actions は、GitHub アカウントさえあれば、記事中で紹介したような設定ファイルを追加するだけで簡単にはじめることができます。

    まだ CI 環境を導入していない場合は、まずは GitHub Actions からはじめてみるのがオススメです!

    では、最後に、今回の内容を簡単にまとめてみたいと思います。

    1. どの CI 環境でも、やることはローカル環境とほぼ同じ
    2. CI 環境での Firestore エミュレータの起動はバックグラウンドで
    3. Firestore エミュレータの起動後に待機時間が必要
    4. 一度設定してしまえば、プッシュのたびに自動リグレッションテスト!
    5. まだ CI 環境を導入していないなら、まずは GitHub Actions がおすすめ!

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    featureImg2020.08.04エンジニアの働き方 特集社員としての働き方社員としてのエンジニアの働き方とは?ライトコードのエンジニアはどんな働き方をしてるのか、まとめたいと...

    featureImg2020.07.27IT・コンピューターの歴史特集IT・コンピューターの歴史をまとめていきたいと思います!弊社ブログにある記事のみで構成しているため、まだ「未完成状態」...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    広告メディア事業部

    広告メディア事業部

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background