メインコンテンツまでスキップ

認可をテストする

認可を確かめるには、種類の異なる証拠が必要です。人間によるレビュー、関所、生成される validation、verify、アプリケーションのテスト、移行時の比較は、それぞれ別の問いに答えます。どれか一つで、ほかを代用することはできません。

証拠分かること分からないこと
手形のレビュー認可仕様が、プロダクトの意図した要件を表しているかアプリケーションが正しいデータを渡し、判定を正しく適用しているか
関所Ninka が機械的に検出できるスキーマ上・意味上の検査に通っているか要件そのものが正しいか、人間が承認したか
生成される validation現在の手形から導いた具体例と、コンパイル済みポリシーの判定が一致するか手形が業務要件や以前の実装と一致するか
ninka-authz verify解決された成果物・Consumer Projection の状態が現在のソースに対応し、Ninka の再現性・検証条件を満たすかGit がそのファイルを追跡しているか、人間が承認したか、以前と同じ挙動か
アプリケーション境界のテストアプリケーションが意図した入力を作り、意図したポリシーを呼び、結果を正しく適用しているかポリシーそのものが正しい業務ルールか
移行時の比較比較したケースについて、新旧の認可システムが同じ判定を返すかどちらかがすべての入力について正しいか

1. 現在のポリシーは、生成される validation で確かめる

WASM を生成するコンパイルでは、Ninka は 現在の手形から validation vector を導出します。期待される判定は、生成された Rego とは独立した reference evaluator が決め、生成された WASM がその判定と一致することを確認します。

対象には、各 allow ルールが実際に許可を与える例、条件などを一つ変えた場合、allow と deny が重なる場合などが含まれます。ここで検査しているのは、現在の仕様が実行成果物へ正しく変換されたかです。過去のポリシーに対する回帰テストではありません。ルールを意図的に変更すれば、次の validation は新しい手形から導かれます。

具体例は Authorization Reference で確認できます。vector の形式や成果物のフィールドは 生成ファイル を参照してください。

2. verify は再現性を確かめるゲートとして使う

npx ninka-authz verify

verify は、現在のワークスペースと、解決された出力先にある生成ファイルを読みます。ソースから導かれる状態を再生成し、成果物どうしの結び付きとハッシュを検査します。さらに、必要な validation を実行 bundle に対して再評価し、Consumer Projection も生成し直してバイト単位で比較します。

verify は Git を参照しません。 生成ファイルを Git で追跡するかどうかは、リポジトリ側の方針です。一方、そのファイルがディスク上に存在し、現在のソースと toolchain から再現できる状態と一致するかどうかは verify が検査する事実です。たとえば raw WASM を意図的に Git 管理から外しているリポジトリでも、bundle がディスク上に存在すれば verify は通り得ます。

したがって green になることが意味するのは、検査対象の状態を現在の Ninka と toolchain の契約のもとで再現できることです。次の意味ではありません。

  • 人間が手形を承認した
  • 変更前と同じ認可結果を保っている
  • Git が特定の生成ファイル一式を追跡している

正確な検査項目、フラグ、スキップ条件、失敗条件は CLI リファレンス を参照してください。

3. アプリケーションとの境界をテストする

ハンドラが正しいドメインデータを読み、意図した認可入力を組み立て、意図したポリシーを呼び、deny を実際に適用しているかどうかは Ninka だけでは証明できません。ここはアプリケーション側でテストします。

少なくとも、境界の両側を確認してください。

  1. 意図した subject・action・具体的な resource を check() に渡していること
  2. check() が返した boolean を、deny の場合も含めて正しく扱っていること
const check = vi.fn();
vi.mocked(createNinka).mockResolvedValue({ check } as never);

check.mockReturnValue(false);
const response = await POST(request);
expect(check).toHaveBeenCalledWith(policies.documentAccess, expectedInput);
expect(response.status).toBe(403);

check() 自体は同期処理です。await が必要なのはインスタンスの生成です。

アプリケーション側で Ninka を独自の composition root に包んでいるなら、この例をそのまま写すのではなく、その境界をテストまたはモックしてください。

4. 移行時は、置き換える認可システムと比較する

生成される validation だけでは、OPA、手書きの認可、その他の旧実装との parity は確認できません。期待値が現在の手形の意味論から導かれているためです。

移行中は、代表的なケースを新旧両方の認可経路へ通して判定を比較します。allow、deny、境界値、入力欠損、複数 role の組み合わせ、旧実装固有の入力表現など、移行対象のポリシーで意味のあるケースを含めてください。

この比較結果は Ninka の生成 validation とは別の証拠です。不一致がゼロでも、期待したポリシーとケースが実際に比較されていなければ意味はありません。詳しくは OPA から移行する を参照してください。

5. 人間によるレビューは別の層に残る

機械的な検査もアプリケーションのテストもすべて通っているのに、手形が業務要件の誤った解釈を忠実に実装している、ということはあり得ます。

認可の変更を受け入れる前に、仕様そのものをレビューしてください。認可をレビューする を参照してください。

関連項目