メインコンテンツへスキップ
見出し画像

ServiceNowのquery_range ACLとは? 自動ロードで何が変わるかをAustralia実機で確認


    ServiceNowでは、テーブルのフィールド(フォームや一覧に出る個々の列)を、ACLで特定のロールにだけ見せる設定ができます。たとえばユーザーテーブル(sys_user)に自社で「年収」フィールドを追加し、人事ロール以外は読み取り不可にしたとします。フォームを開いても、一覧に列を足しても、値は表示されません。

    ところが、一覧の絞り込みと並び替えは表示とは別の経路です。「年収が500万より上」という条件で絞って該当者が出るかを見る。次は「750万より上」で絞る。この繰り返しなら、値を一度も表示させないまま10回ほどで金額を特定できてしまいます。この抜け道を塞ぐ仕組みがquery_range ACLです。対象はあくまでテーブルのフィールドで、カタログアイテムの変数のような画面部品の設定とは別の話です。

    Zurichリリースで、このACLをシステムが自動生成する仕組みが導入されました。ZurichからAustraliaへメジャーアップグレード済みの実機を開き、何件作られ、何に注意すべきかを確認します。

    検証環境:Australia PDI(Zurichからメジャーアップグレード済み)/ 2026-08-26 確認

    • query_range ACLは何を守る仕組みなのか

    • 「自動ロード」で実機に何件できて、どれが非アクティブなのか

    • 非アクティブとして読み込まれたACLをどう確認し、どう扱うか

    • 生成を担う仕組みの中身

    結論を先に3行で置きます。

    • 自動生成されたquery_range ACLは、最終的に有効化されます(新しい制御が「締まる」方向)

    • 自作していたQuery ACLは非アクティブで読み込まれます(制御が「緩む」方向。棚卸しが必要)

    • アップグレード後にやることは「非アクティブの棚卸し3手順」です(本文後半に手順があります)

    いままでのACLと、今回何が変わったのか

    先に全体の関係を1枚にします。


    画像

    図の色は経路の状態を表します。緑が以前から制御されている経路、赤が制御のなかった抜け道、青がZurichで新設された制御、灰色がinactiveのまま保持される自作分です。

    いままでのACLは、表示(read)や更新(write・create・delete)という操作の結果を守る仕組みでした。どのレコードを見せるか、どの項目を書き換えさせるかはテーブル・フィールド単位で細かく制御できます。一方で、どう問い合わせるか(絞り込みの条件や並び替え)は制御の対象外で、ここが冒頭の「年収を当てる」抜け道になっていました。

    今回の変化は、この問い合わせ経路にquery_range ACLという制御が加わり、しかもそれがシステムによって自動生成されるようになったことです。表示・更新の守り方は変わりません。変わるのは問い合わせ側だけです。

    そもそもquery_range ACLは何を守るのか

    フィールドの読み取りをACLで制限しても、一覧の絞り込みと並び替えは別の経路です。値が漏れる筋道は2つあります。

    • 絞り込みで漏れる。冒頭の年収の例のとおり、範囲条件を繰り返せば値そのものを表示せずに特定できます

    • 並び替えでも漏れる。読めない項目の昇順で一覧を並べれば、先頭に来たレコードが最小値の持ち主だと分かります

    query_range ACLは、この問い合わせ方そのものを制御するアクセス制御です。表示を守るread ACLとは役割が分かれていて、両方そろって初めて「見えない項目は推測もできない」状態になります。ACLそのものの基本はServiceNowで権限はどこで決まる? ユーザーからACL・ドメインまで7つの層を実機でたどる完全ガイドで扱った階層の一部にあたります。

    query_rangeはACLの「タイプ」ではなく「操作(operation)」

    位置づけを最初に押さえます。ACL(sys_security_acl)にはread・write・createなどの操作(operation)があり、query_rangeはその1つです。実機のsys_security_operationテーブルには、クエリ系の操作が3つ登録されています。query_range・query_match・conditional_table_query_rangeです。レコード構造はACLの基本(sys_security_acl)で扱った通りです。


    画像

    ここで注意が1つあります。ACL一覧を「Type=query_range」で検索すると0件です。query_rangeはTypeではなくOperationのため、絞り込みはoperation.name=query_rangeで行います。Typeに入るのはrecord・ui_page・REST_Endpointなどの区分です。

    query_matchとconditional_table_query_rangeは守備範囲が違う

    3つのクエリ系操作は役割が分かれています。query_matchは一致条件の問い合わせを制御する操作で、実機ではわずか16件です。中身は*.*(全テーブル・全フィールドのワイルドカード)が1件です。ほかはNLU系テーブル(sys_nlu_intentなど)のsys_scopeフィールドや、ロール履歴系(sys_user_role_history系)に限られます。導入済みアプリのm2mテーブルを対象にした行も1件あり、プラグイン側がquery_matchを同梱してくる場合もある構成です。conditional_table_query_rangeは条件付きのテーブル単位版で、*のワイルドカードに加えてalm_assetやannouncementのような業務テーブルが並びます。ワイルドカードの行が全テーブル共通の既定を持ち、個別テーブルの行が例外を定義する構成です。数の主役はquery_rangeで、残る2つは特定用途の補完という構図です。

    プラグインを入れるたびに、このACLも増えるのか

    増えます。リリースノートの「プラグインのインストール時に自動ロードされる」という記述は、この環境の直近の導入で裏付けが取れます。この検証環境には2026年8月にアプリケーションを追加導入していて、そのとき初めて作られたテーブル群にもquery_range ACLが付いていました。内訳は表に分けます。


    画像

    テーブル自体が導入日まで存在しなかった以上、これらのACLは導入時に一緒に生成されたものです。プラグイン導入前後の増分を数える手法は導入前後の差分調査で扱った通りで、ACLの増分の中にはこのquery_range分も含まれています。

    自動ロードで実際に何件できるのか

    アップグレード済みの実機で数えた結果です。


    画像

    query_range ACLは合計8,161件です。内訳はactiveが8,155件、inactiveが6件でした。クエリ系操作の全体像は次の表のとおりです。


    画像

    1件を開くと、生成のされ方が説明文にそのまま書かれています。incidentテーブルのquery_range ACLの説明文(原文)はこうです。

    Auto-generated by System; Derived from read ACL: incident; Security Attribute: UserIsAuthenticatedAndHasRightsToRead; Roles: public

    (訳: システムによる自動生成。read ACL「incident」から導出。セキュリティ属性はUserIsAuthenticatedAndHasRightsToRead。ロールはpublic)

    引用元: /sys_security_acl_list.do?sysparm_query=name=incident^operation.name=query_range


    画像

    つまり自動ロードは、各テーブルの既存read ACLを元に、同じ守備範囲のquery_range ACLを機械的に導出する方式です。認可の判定にはロールだけでなくセキュリティ属性(Security Attribute。ロールと並ぶもう1つの認可条件)が使われます。UserIsAuthenticatedAndHasRightsToReadという属性が、実機にactiveで登録済みです。


    画像

    もう1点、incidentのACLで見逃せないのはAdmin overrides=falseです。管理者ロールでも素通りできない設定で生成されています。範囲クエリの制御は、「adminなら関係ない」とはならない前提です。管理者が組んだ定例レポートやスケジュールジョブのクエリも判定の対象に入るため、権限の強いユーザーで動かしている処理ほど、この前提を知らないと原因調査で遠回りします。

    公式リリースノートは「自動ロード」と「既存分はinactiveで保持」を明記している

    ZurichからAustraliaへの差分をまとめたアクセス管理リリースノートにも、この扱いが要旨として明記されています。

    Query ACLs now load automatically during plugin installation for most platform plugins. Existing custom query ACLs are preserved and loaded as inactive.

    (訳: Query ACLは、ほとんどのプラットフォームプラグインのインストール時に自動でロードされるようになりました。既存のカスタムQuery ACLは保持され、非アクティブとして読み込まれます)

    ポイントは2つに分かれます。1つ目は、プラグイン導入時に対象テーブルのquery_range ACLがシステム側で自動生成されること。2つ目は、利用者が自作していたカスタムのQuery ACLは消されず、inactiveの状態で残されることです。上書きで消える心配はない一方、アップグレード後にそのまま放置すると、自作の制御が効いていないまま運用が続きます。詳細はリリースノートが参照するKB2046494(要ログイン)にまとまっています。

    生成の実体はQueryRangeACLAuditorという3段階のスクリプト

    自動ロードを担う実装も実機で確認できます。本体はQueryRangeACLAuditorという名前のScript Include(サーバ側で動く共通スクリプトの部品。Global・active)で、全体で約144万文字という桁違いの規模を持ちます。冒頭のコメントに処理の流れが明記されています(Version 1.0.185・理由コードPRB1868877)。


    画像

    図の色は状態を表します。橙が「いったんinactiveで作られる中間状態」、青が「最後に有効化される結果」、灰が前提の投入、緑が最初から有効で作られるSecurity Attributeです。手順は3段です。まず全テーブル・フィールドのread ACLとquery_range ACLの情報を集めます。次にquery_range ACLをinactiveの状態で作成します。最後のステップで、新規に作成した分だけをactivateする流れです。リリースノートの「既存分はinactiveとして読み込まれる」という一文は、この第2段と第3段の差にあたります。新規生成分は最後に有効化される一方、既存のカスタム分は有効化の対象に入りません。

    前処理で投入されるnobodyロールも実機に確認できます。誰にも割り当てない前提の制御用ロールで、query_rangeのoperation定義・Security Attributeと並ぶ、自動ロードの前提部品の1つです。自分の環境にこれらの部品が揃っているかどうかは、自動ロードが走ったかどうかの傍証になります。

    非アクティブの6件は、システム自身が有効化を見送ったクローン関連ACL

    この実機の非アクティブ6件を開くと、対応の考え方が具体的に見えてきます。


    画像

    6件はすべてインスタンスクローン関連のテーブル(clone_data_preserver・clone_cleanup_scriptなど)です。作成者はglide.maintで、説明文は他と同じ「Auto-generated by System; Derived from read ACL: …」でした。自動生成の仕組み自体が、すべてを一律に有効化せず、一部をinactiveのまま残す運用をしています。システム側でさえ全件有効化を選ばないという事実は、自分のカスタムQuery ACLを有効化するかどうかの判断でも参考になります。

    アップグレードで制御は緩むのか、締まるのか

    リリースノートの一文から受ける印象と、実際に起きることを分けて整理します。影響は2方向です。

    1つ目は守りが緩む方向です。アップグレード前に自作していたQuery ACLがinactiveで読み込まれるため、その制御に頼っていた範囲クエリの制限は、有効化し直すまで効いていません。自作分が多い環境ほど、棚卸しを後回しにできない理由がここにあります。

    2つ目は制御が締まる方向です。自動生成されたquery_range ACLは最終段でactivateされるため、いままで制限のなかった範囲クエリに、新しい制御がかかる側です。Admin overrides=falseで生成される以上、管理者の定例レポートや連携のクエリが対象になる可能性も含めて、アップグレード後の動作確認の観点に足しておく必要があります。緩む側だけを見て「自作分を戻せば終わり」と判断すると、締まる側の影響を見落とします。

    アップグレード後にやることは「非アクティブの棚卸し」の3手順

    対応はシンプルです。次の3手順で棚卸しします。

    1. 非アクティブのQuery ACLを一覧にする。/sys_security_acl_list.do?sysparm_query=operation.name=query_range^active=false を開くと、この記事の6件のような一覧が自分の環境でも出ます

    2. 自作分とシステム生成分を説明文で仕分ける。システム生成分には「Auto-generated by System; Derived from read ACL: …」という説明文が入ります。説明文が空、または自社の命名規則のものが、アップグレード前に自作していたカスタムQuery ACLです。仕分けはdescriptionNOTLIKEAuto-generatedという条件を1つ足すだけで機械的にできます

    3. 自作分は1件ずつ有効化を判断する。自動生成された同名テーブルのACLと守備範囲が重なっていれば、自作分は不要になっている可能性があります。重なっていなければ、検証環境で有効化して一覧・レポート・連携の挙動を確認してから本番に反映します。ロール単位の影響を面で確かめるならAccess Analyzerが向いています

    条件付きの派生operationであるconditional_table_query_range(454件)も同じ一覧に入ってきます。テーブル単位で全体を見るときは、operation列を表示しておくと仕分けが速くなります。


    画像

    有効化の順序にも1つ判断があります。自作分を複数持っている場合、一度に全部有効化すると、問題が出たときにどのACLが原因か切り分けられません。1回の変更で有効化するのは関連するひとかたまりまでに絞り、変更のたびに対象テーブルの一覧・レポート・API呼び出しを確認する進め方が安全です。この点は通常のACL変更の作法と同じで、query_range固有の追加作業はありません。

    実機で気づいたこと

    症状: ACL一覧をType=query_rangeで検索すると0件になる。 原因はquery_rangeがTypeではなくOperationであるためです。Typeに入るのはrecordやui_pageなどの区分で、実機のType別分布にquery系の値はありません。回避策として、絞り込みはoperation.name=query_rangeで行います。REST APIで数える場合も同じです。

    症状: ACLの作成日を見ても、自分の環境にいつ入ったのか判断できない。 この実機では2025-11-05に7,050件の作成日が集中していますが、プラグインやアップグレードで入るレコードは、作成日が配布物の作成時点のまま入ることがあります。原因はコンテンツ配布の仕組みです。回避策として、ロールアウトの時期を特定したい場合は作成日ではなく、アップグレード履歴と突き合わせます。

    症状: 自動生成分と自作分の区別がつかない。 原因は同じsys_security_aclテーブルに同じoperationで並ぶためです。回避策として、説明文の「Auto-generated by System」を仕分けのキーに使います。


    画像

    この文字列は導出元のread ACL名とセキュリティ属性名まで含むため、棚卸しの一覧をそのまま機械的に分類できます。逆に言えば、自作するACLの説明文にも導出元や目的を書いておくと、次のアップグレードの棚卸しで同じ仕分けがそのまま使えます。

    実務では何に使えるか

    • アップグレード計画のレビュー項目に加える。「Query ACLの自動ロードで挙動が変わるテーブルはあるか」「自作のQuery ACLは何件あるか」を事前に数えておくと、アップグレード後の切り分けが速くなります。数え方の型は影響調査でチェックする27か所と同じです

    • セキュリティ監査の説明材料にする。「範囲クエリによる推測はquery_range ACL(8,155件)で制御している」という説明は、読み取りACLだけの説明より一段深い回答です

    • アップグレード直後のヘルスチェックを3クエリに定型化する。①operation.name=query_range^active=falseの件数 ②そのうち説明文に「Auto-generated by System」を含まない件数(=自作分) ③conditional_table_query_rangeを含めたクエリ系の総数。この3つを前後で控えるだけで、変化の有無を数字で報告できます

    • 一覧やレポートが突然動かないときの容疑者に入れる。Admin overrides=falseで生成されるため、管理者でも例外になりません。絞り込みだけが失敗する症状のときは、この一覧を確認します。切り分けの並びはServiceNowで「このレコードが見えない」は本当にACL拒否?の手順に足してください

    用語

    • query_range … 範囲条件・並び替えを使う問い合わせを制御するACLの操作(operation)

    • Security Attribute … ロールと並ぶ認可条件。sys_security_attributeに定義され、UserIsAuthenticatedAndHasRightsToReadなどが自動ロードで使われる

    • QueryRangeACLAuditor … query_range ACLを生成するWrite-Auditの実体(Script Include・Global)

    • nobody ロール … 誰にも割り当てない前提の制御用ロール。自動ロードの前処理で投入される

    付録:自分の環境で確認するときのURL

    • query_range ACLの全体(activeでグループ化):/sys_security_acl_list.do?sysparm_query=operation.name=query_range^GROUPBYactive

    • 非アクティブのquery_range ACL:/sys_security_acl_list.do?sysparm_query=operation.name=query_range^active=false

    • クエリ系のoperation定義:/sys_security_operation_list.do?sysparm_query=nameLIKEquery

    • セキュリティ属性:/sys_security_attribute_list.do?sysparm_query=nameLIKEUserIsAuthenticated

    • 生成スクリプトの実体:/sys_script_include_list.do?sysparm_query=name=QueryRangeACLAuditor

    引用した公式説明を自分で開く

    検証範囲とおことわり

    Australia PDI(Zurichからメジャーアップグレード済み・OOTB+別シリーズ検証でTPRM/SAM導入済み)で2026-08-26に確認しました。件数はすべてこの環境のGlideAggregate実測です。確認していない範囲は次のとおりです。

    • 読み取り権のないユーザーで範囲クエリが実際に拒否される挙動の再現(本記事は定義と件数の実測まで)

    • リリースノートが参照するKB2046494の中身(要ログインのため未確認)

    • 自動ロードの対象外になるプラグインの条件と、Early Availabilityの適用範囲

    関連記事

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ