【SeviceNow】ACLのパフォーマンスを検証してみた

ServiceNow
なうもん
なうもん

ServiceNowでデータのセキュリティを守る必要はあるものの、ACLが複雑になってパフォーマンスが心配ってことありますよね?

そこで今日はACLの設定によってパフォーマンスにどんな影響がでるかを実際に検証してみます。

ACLの設定の違いによるパフォーマンスを実際に検証

検証の目的

  1. ACLの設定の違いにより、パフォーマンスにどのような影響が出るのかを検証
  2. Allow If、Deny-Unless、ロール、レコードの条件、スクリプトでそれぞれどのような違いがあるかを検証

検証の前提

  1. 検証する環境はDeveloperインスタンスを使うので、本番インスタンスとは測定値が異なる可能性があります。
  2. ACLの条件はロール、レコードの条件、スクリプトの3パターンで検証するが、パターンが多くなるため複数条件を組み合わせた全パターンの検証は行いません。

検証方法

  • ServiceNowの「応答時間インジケーター」と「スクリプトデバッガー」を利用する
  • 応答時間インジケーターではサーバーの処理時間、スクリプトデバッガーではトランザクション数を計測値とする。

応答時間インジケーター
https://www.servicenow.com/docs/ja-JP/bundle/xanadu-platform-user-interface/page/use/common-ui-elements/concept/c_ResponseTimeIndicator.html

スクリプトデバッガー
https://www.servicenow.com/docs/ja-JP/bundle/xanadu-api-reference/page/script/debugging/concept/script-debugger.html

検証パターン

【パターン毎の検証】
各パターンでACLの設定の違いにより、どのようなパフォーマンスの影響が出るか検証します。
→ロール、レコードの条件、スクリプトによる条件でどのようなパフォーマンス影響が出るかを検証。

ロール、レコードの条件、スクリプトによる条件とはACLの設定箇所を指しています。

・ロール

・レコードの条件

・スクリプトによる条件

【パターン間の検証】

  • ①と②の比較により、参照の拒否はDeny UnlessとAllow Ifのどちらがパフォーマンス上優位か検証
  • ③と④の比較により、Deny-Unlessでレコードを絞り込んだ上で、Allow Ifを評価した方がパフォーマンスの向上を見込めるのか検証

前回記事にした、Deny-Unless ACLのユースケースとして不要なACL評価を減らすことにより、パフォーマンスの向上を見込めないか?という疑問からこの検証を始めました。

#パターンDeny-UnlessAllow-If
Deny-Unlessでテーブル全体へのアクセスを拒否×
Deny-Unlessで全て許可した後、Allow Ifで拒否×
Deny-Unlessで一部のレコードを拒否した後、残りのレコードをAllow Ifで許可
Allow Ifで許可

×:拒否
〇:許可

検証の準備

検証の準備
  • 検証用のユーザーを作成

    A・B Userを作成し、それぞれA UserにのみRequesterロールを付与します。

  • ACLを設定するためのテーブルを作成

    Taskテーブルを継承した申請テーブルを作成しました。

    自分の会社のレコードだけ参照可能、という条件を追加するために「会社」カラムを持たせています。

  • 申請テーブルにデータを作成
    • パフォーマンス測定のために、申請レコードを30,000レコード作成しました。
      (バックグラウンドスクリプトで作成したのですが時間がかかりすぎて一旦検証を止めて寝ました。)
    • 30,000レコードのうち100レコードには会社項目に”A Company”を設定し、残りの29,900レコードには”ACME Japan”を設定しています。
  • ロールでアクセス拒否・許可を行うためのACLを作成
    • Requesterロールを持っているユーザー以外の参照を拒否するDeny-Unless ACLを作成
    • Requesterロールを持っているユーザーの参照を許可するAllow If ACLを作成
  • レコードの条件に応じてアクセス拒否・許可を行うためのACLを作成
    • 会社項目の値に応じて拒否・許可を行うACLをDeny-Unless、Allow Ifでそれぞれ作成。
  • スクリプトでアクセス拒否・許可を行うためのACLを作成
    • ログインユーザーのロールで判別
    • レコードの会社レコードで判別

①Deny-Unlessでテーブル全体へのアクセスを拒否

ユーザーがテーブルに対し、アクセスリクエストを行った際にDeny-Unless ACLでアクセスを拒否します。
そのため、Allow IfのACLは評価されないままアクセスが拒否されます。

#Deny-Unlessの拒否パターンロールレコードの条件スクリプト
①-1ロールで拒否×
①-2レコードの条件で拒否×
①-3スクリプトで拒否(スクリプト内の条件はロール)×
①-4スクリプトで拒否(スクリプト内の条件はレコード)×
①-51~4のACL全てをアクティブ化した上で拒否×××

×:拒否

ロール、レコードの条件、スクリプトによる条件で拒否を行い、パフォーマンスを測定します。

スクリプト内の条件は、ロールとレコードで違いを測定するためにロールを判別するスクリプト、レコードの条件で判別するスクリプトを記述します。

また、1~4の全てをアクティブ化したときのパフォーマンスも測定してみます。

②Allow Ifで拒否

このパターンではAllow If ACLで許可を与えず、アクセスを拒否します。

#Allow-Ifロールレコードスクリプト
②-1ロールで拒否×
②-2レコードの条件で拒否×
②-3スクリプトで拒否(スクリプト内の条件はロール)×
②-4スクリプトで拒否(スクリプト内の条件はレコード)×
②-5②-1~4のACL全てをアクティブ化した上で拒否×××

×:拒否

「①Deny-Unlessでテーブル全体へのアクセスを拒否」のパターンと比べて、どのようなパフォーマンスの違いがあるかが②での主な検証ポイントとなります。

③Allow Ifで許可

次に③では、Allow If ACLでアクセス許可を与えます。

#Allow Ifの許可パターンロールレコードスクリプト
③-1ロールで許可
③-2レコードの条件で許可
③-3スクリプトで許可(スクリプト内の条件はロール)
③-4スクリプトで許可(スクリプト内の条件はレコード)
③-51~4のACLを全てアクティブ化した上で許可

ここではロールによる許可、レコードによる許可、スクリプトによる許可でどのようなパフォーマンスの違いがあるかを見ていきます。

また、スクリプトではロール、レコードの条件それぞれのパターンも検証します。

③-5では1~4のACL全てをアクティブ化した上でアクセスを許可し、パフォーマンスの測定を行います。

許可対象のレコードは30,000レコードのうち、100レコードとします。

④Deny-Unlessで一部のレコードを拒否した後、残りのレコードをAllow Ifで許可

④ではDeny-UnlessとAllow Ifを組み合わせてパフォーマンスの検証を行います。

Deny-Unless ACLはレコードの条件でアクセスを拒否します。

Deny Unlessの拒否パターンロールレコードの条件スクリプト
レコードの条件で拒否×

作成したAllow If ACLは③と同様のパターンです。

#Allow Ifの許可パターンロールレコードの条件スクリプト
④-1ロールで許可
④-2レコードの条件で許可
④-3スクリプトで許可(スクリプト内の条件はロール)
④-4スクリプトで許可(スクリプト内の条件はレコード)
④-51~4のACLを全てアクティブ化した上で許可

Deny-Unless ACLで29,900レコードのアクセスを拒否し、Allow Ifの評価対象を100レコードのみに絞ることで、「③Allow Ifで許可」と比較して、パフォーマンスの向上を期待しています。

検証結果

なうもん
なうもん

それでは各パターンの検証結果を紹介します。

検証結果:①Deny-Unlessでテーブル全体へのアクセスを拒否

#Deny-Unlessの拒否パターンサーバー処理時間トランザクション数
①-1ロールで拒否305ms5
①-2レコードの条件で拒否901ms268
①-3スクリプトで拒否(スクリプト内の条件はロール)725ms268
①-4スクリプトで拒否(スクリプト内の条件はレコード)852ms268
①-51~4のACL全てをアクティブ化した上で拒否254ms5

結果としては「①-5:1~4のACL全てをアクティブ化した上で拒否」のパフォーマンスが最もよかったですが、これはロールが優先的に評価され、レコードの条件、スクリプトが評価されなかったためだと思われます。

そのため、①-1とは誤差があるものの、まずはロールでDeny-Unlessを設定した方がパフォーマンス上良さそうです。

スクリプトよりレコードの条件で拒否した方がサーバー処理時間が多くかかっていたのは意外な結果でした。

検証結果:②Allow Ifで拒否

#Allow-Ifサーバー処理時間トランザクション数
②-1ロールで拒否253ms5
②-2レコードの条件で拒否274ms10
②-3スクリプトで拒否(スクリプト内の条件はロール)508ms268
②-4スクリプトで拒否(スクリプト内の条件はレコード)530ms268
②-5②-1~4のACL全てをアクティブ化した上で拒否690ms268

こちらの検証結果としては、「②-1:ロールで拒否」したパターンが最もサーバー処理時間が短く、トランザクション数も少なかったです。

一方で「②-5:1~4のACL全てをアクティブ化した上で拒否」のパターンが最もパフォーマンスが悪かったですが、こちらはDeny-UnlessのACLとは異なり、1~4の全てのACLが評価された上でアクセスが拒否されたためだと考えられます。

そのため、Allow IfのACLが増えれば増えるほど、評価対象のACLが増えていくためパフォーマンスは悪化していくと予想されます。

なうもん
なうもん

適切にDeny-Unless ACLを設定することで、無駄なAllow If ACLの評価を減らし、パフォーマンスを向上できる可能性はありそうですね。

ただ、①ではレコードの条件が最も時間がかかっており、トランザクション数も268だったのに対し、②ではレコードの条件はサーバー処理時間も短く、トランザクション数も10と少なかった理由は良く分からず、引き続き調査が必要です。

検証結果:③Allow Ifで許可

#Allow Ifの許可パターンサーバー処理時間トランザクション数
③-1ロールで許可1199ms452
③-2レコードの条件で許可1157ms434
③-3スクリプトで許可(スクリプト内の条件はロール)1172ms452
③-4スクリプトで許可(スクリプト内の条件はレコード)959ms434
③-51~4のACLを全てアクティブ化した上で許可1812ms452

こちらは意外な結果が出ました。

なんとロールで許可するパターンよりも、レコードを条件としたスクリプトを記述したパターンが最もパフォーマンスが良かったです。

ただ、こちらは全てのケースに当てはまる訳ではなく、スクリプトの処理内容に依存することは言うまでもありません。

また、「③-5:1~4のACLを全てアクティブ化した上で許可」が一番パフォーマンスが悪かったことは想定通りで、1~4のACL全てが評価された結果だと考えられます。

なうもん
なうもん

当たり前ですが、パフォーマンスのことを考えるとACLはなるべくシンプルにしないといけませんね。

検証結果:④Deny-Unlessで一部のレコードを拒否した後、残りのレコードをAllow Ifで許可

#Allow Ifの許可パターンサーバー処理時間トランザクション数
④-1ロールで許可1536ms434
④-2レコードの条件で許可1028ms434
④-3スクリプトで許可(スクリプト内の条件はロール)1188ms434
④-4スクリプトで許可(スクリプト内の条件はレコード)965ms434
④-51~4のACLを全てアクティブ化した上で許可1664ms434

Deny-Unless ACLであらかじめ30,000レコードのうち、29,900レコードのアクセスを拒否することで、後続のAllow If ACLのパフォーマンスが向上できるのではと予想していましたが、③の結果と比べて大きな差は見られませんでした。

Deny-Unlessでアクセスが拒否されたものの、Allow IfのACL自体は評価されているためだと考えられます。

検証結果のまとめ

Deny-Unlessでのアクセス拒否、Allow Ifのアクセス許可はともにロールで判別する方がパフォーマンス上優位…..のはずでしたが場合によってはレコードの条件、スクリプトによる条件の方が良いケースもあるようです。

ただ、かの有名なChuck Tomasi氏は、ロールが一番最初に評価され、かつキャッシュされるため可能な限りロールをACLの条件に利用するのが常に効率的とコメントしています。

ServiceNow Communityより引用
https://www.servicenow.com/community/grc-forum/order-of-execution-of-an-acl/m-p/1311960

また、Allow If ACLは増えれば増えるほど評価されるACLも増えていくため、予めテーブルに対するアクセスが拒否されるユーザーが明確な場合は、Deny-Unlessで最初にアクセスを拒否することで、Allow If ACLの評価もされず、パフォーマンスの向上も見込めそうです。

なうもん
なうもん

色々検証してみたものの….ACLのパフォーマンスに関する公式情報をServiceNow社には出してほしいというのが正直な感想です。

おまけ

ちなみに遅いACLはシステムログに出力されます。

コメント

タイトルとURLをコピーしました