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

ServiceNowで付けたロールが想定外の権限を含んでいた理由 sys_user_role_containsで包含を実機でたどる


    「限定的なつもりでitilロールを1つ付けただけなのに、なぜかCMDBやRequestの画面まで触れる」。ServiceNowのロールは1つ付けるだけで、その裏に何十ものロールが自動的にぶら下がることがあります。この包含関係はsys_user_role_containsという1つのテーブルに定義されています。Zurich PDIで実際に辿ると、itilロールは24件を直接含み、adminロールはわずか13件しか直接は含んでいませんでした。数だけ見るとitilの方が多いという、意外な結果です。

    検証環境:Zurich PDI / OOTB / 2026-08-09 確認

    結論:直接の件数と最終的な広さは別物だった

    先に全体像です。

    • itilロールが直接containsするロールは24件、adminロールは13件でした。1階層目だけを見ると、itilの方が多くのロールを抱えています。

    • そこからさらに何段も辿ると順位が入れ替わります。itilは4階層で止まり合計42件、adminは5階層まで続き合計60件に達しました。

    • adminの権限の広さは「ロールを多く含んでいるから」ではなく、ACL(sys_security_acl)側のAdmin overridesという設定で支えられている可能性が高いと分かりました。ロール要件そのものを個別にスキップできる仕組みです。


    画像

    図の色は役割の違いを示します。濃紺はitil・adminという起点のロール、水色は1段たどるごとに新しく現れる包含先のロール、橙は最終的にたどり着いた合計件数です。紫は両方の木から重複して辿り着く共通ロールを表します。以下の節で、この数字がどう出てきたのかを1つずつ確認します。

    sys_user_role_containsとは何のテーブルか

    ServiceNowのロールには「別のロールを内包する」という設定があります。この関係を1件ずつ記録しているのがsys_user_role_contains(Contains Roles)です。フィールドはrole(親ロール)とcontains(子ロール)という2つの参照だけで、他の中間表と同じ「1関係=1レコード」の作りでした。

    今回のPDIではsys_user_role_containsの全体件数は713件、ロール自体(sys_user_role)は623件登録されています。1つのロールが平均1件強の子ロールを持つ計算です。実際の分布には偏りが大きく、ほとんど何も含まないロールと、何十件も含むロールとに分かれます。公式のExploring user administration(Zurich)には、ロールがどのように権限をまとめる単位になっているかの説明があります。

    itilが直接含む24件の中身

    itilとadminで実際に絞り込むと、次のようになりました。


    画像

    itilが直接含む24件は、sn_incident_write・sn_problem_write・sn_change_write・sn_request_write・cmdb_read・agent_workspace_user・app_service_userのように、各モジュールの業務操作を有効にする「〜_write」「〜_user」系のロールがほとんどでした。SOW(Shared Ownership Workspace)関連のsn_sow.sow_home・sn_sow.sow_list・sn_sow.sow_userも含まれており、ヘルプデスク担当者が日常触れる画面を一通りカバーする構成だと分かります。

    itilロールのフォーム自体を開くと、Contains Rolesという関連リストのタブに件数バッジが表示されていました。


    画像

    Descriptionには「ITILヘルプデスク技術者としての標準操作ができる。out-of-boxの'technician'ロールで、Incident・Problem・Change・構成アイテムのオープン・更新・クローズができる」という説明があります。Elevated privilege(昇格が必要な強いロールかどうか)のチェックボックスはオフでした。役割を広げているのはこのフラグではありません。下の関連リストに並ぶ24件のcontainsが実体だと分かります。

    adminが直接含む13件の中身

    一方でadminが直接含む13件は、様子が違いました。


    画像

    mi_admin・nlu_admin・sn_employee.admin・sn_hr_sp.esc_admin・sn_deploy_pipeline.deployment_pipeline_adminのように、個別のスコープアプリごとに管理者権限を切り出した「〜_admin」ロールばかりです。それぞれAI SearchのMedia Intelligence・NLU・HR Service Portal・Employee Centerといった、独立したアプリの管理機能を担っています。adminという名前から「あらゆる権限をひとまとめに持つロール」を想像しがちですが、containsの中身を見る限りは特定アプリの管理権限を寄せ集めた構成でした。adminはsys_user_roleの中でも代表的な役割です。公式のBase system roles(Zurich)にほかの基本ロールと合わせて掲載されています。

    ACLのAdmin overridesを確認する:なぜadminは含む数が少ないのに全権を持つのか

    itil24件・admin13件という数字だけを見ると、「itilの方が権限が広いのでは」と誤解しそうになります。実際には逆です。adminの方がほぼすべての操作を通せる立場にあります。この矛盾を解く手がかりは、ロール側ではなくACL(sys_security_acl)側にありました。

    ロール自身のフラグを比べる

    まずロール自身のフラグを比べてみます。


    画像

    admin・itilともにelevated_privilege(昇格が必要な強い権限かどうか)はfalseでした。「adminは特別なフラグが立っているから強い」という予想は外れます。can_delegate(他人へ委任できるか)はitilがtrue、adminがfalseという違いはありましたが、これだけでは権限の広さを説明できません。ロールレコード単体を見比べても、admin固有の「強さ」を示す設定は見当たりませんでした。

    sys_security_aclのAdmin overridesを集計する

    そこでACL側を確認すると、sys_security_aclにはadmin_overrides(Admin overrides)という真偽値のフィールドが用意されていました。PDI全体で43,744件のACLのうち、admin_overrides=trueが21,637件(約49%)、admin_overrides=falseが22,107件(約51%)と、ほぼ半々に分かれています。


    画像


    画像

    ACLの全体像は公式のExploring Access Control List(Zurich)にまとまっています。admin_overridesがtrueのACLでは、ユーザーが実際にどのロールを持っているかに関わらず、adminロールさえあれば条件を評価せずに通過できると読み取れます。逆にfalseのACLでは、adminロールを持つユーザーであっても通常の条件判定を経る必要があるはずです。

    user_passwordフィールドで見る個別ACLの中身

    具体例を1つ見ておきます。sys_userテーブルのuser_password(パスワード)フィールドのACLを見ると、read・writeの2件はadmin_overrides=trueでした。ところがquery_range操作の1件だけはadmin_overrides=falseになっていました。


    画像

    このACLはRequires roleにadminロールそのものが指定されているうえ、Security Attribute Conditionという追加条件も付いていました。adminロールを持っているというだけでは自動的に通過しません。ACLの種類やRequires roleの考え方は公式のACL rule types(Zurich)で解説されています。

    ここまでで確認できたのは、sys_security_aclの約半数がadmin_overrides=trueで、そのACLでは持っているロールに関係なくadminが自動的に通過するという事実です。adminがsys_user_role_containsで多くのロールをcontainsしていなくても全操作を通せる背景には、この仕組みが大きく関わっていると考えられます。ただしACLエンジンの内部評価順序やスクリプトACLとの優先関係までは、PDIの読み取りだけでは確認できていません。ここは推測にとどめます。Admin overridesの扱いに関するハードニング設定はHonor Admin Override ACLs(Zurich)で説明されています。

    ロールの入れ子は何階層まで続くのか

    itilの24件・adminの13件は、あくまで1階層目の数字です。それぞれのcontains先が、さらに別のロールをcontainsしていないかを1段ずつ辿ると、最終的な広さが見えてきます。


    画像

    itilは4階層で止まる

    itilは1階層目24件・2階層目13件・3階層目3件・4階層目2件と減っていき、そこで新しいロールが出なくなりました。合計は42件で打ち止めです。2階層目に現れるのはsn_incident_read・sn_change_read・sn_request_readのように、1階層目のwrite系ロールに対応するread系ロールが中心です。3階層目にはinteraction_agent・sn_cmdb_user、4階層目にはcmdb_ms_user・data_manager_userが現れ、そこで探索は収束しました。

    adminは5階層まで続く

    adminは1階層目13件・2階層目19件・3階層目21件・4階層目6件・5階層目1件(search_relevancy_model_admin)と、itilより1段深いところまで新しいロールが現れ続けました。合計は60件に達しています。3階層目が21件と最も多く、catalog_builder_developer・import_admin・openapi_admin・graphql_schema_adminのように、プラットフォームの開発・連携系の管理ロールが次々と展開されていきました。

    2つの入れ子が交差する共通ロール

    2つの入れ子は完全に別々ではありません。view_changerとsn_itam_recomm.recommendations_readという2つのロールには、itil側では1階層目、admin側では3階層目という別の経路から、両方の入れ子が辿り着きます。sys_user_role_containsは木構造ではなく、1つのロールに複数の親から到達できる有向グラフでした。同じ理由で、sn_ace.ace_userにはadminから直接、さらにnlu_adminとsn_nowassist_admin.nsa_adminという2つの2階層目の経路からも到達しています。

    sys_user_has_roleのinh_countは「深さ」ではなかった

    ロールの定義側(sys_user_role_contains)には深さの情報がありません。ユーザーへの実際の付与側(sys_user_has_role)にはinh_countという整数フィールドがあります。名前だけを見ると「継承の段数」を想像します。デモユーザー「User ITIL」(itilとitil_adminの2ロールを直接付与)で確認すると、様子が違いました。

    ほとんどのロールはinh_count=1でしたが、sn_sow.sow_homeとsn_nb_action.next_best_action_userは5、dependency_viewsは8という値になっていました。dependency_viewsはitilの入れ子の中でapp_service_userとsn_request_writeという複数の経路から重複して到達するロールです。段数ではありません。到達した経路の本数に近い値だと分かりました。フィールド名だけで意味を決めつけず、実際の値を見て確かめる必要があると実感した場面です。ロール継承の仕組みをAPI経由で扱う場合の考え方は、公式のUser Role Inheritance API(Zurich)にまとまっています。

    実務では何に使えるか:ロールを付ける前に確認する手順

    「このロールを付けたら実際に何が付くのか」を事前に確認したいときは、次の手順が使えます。

    1. 付与予定のロール名で sys_user_role_contains_list.do?sysparm_query=role.name=<ロール名> を開き、1階層目のcontainsを確認する

    2. 一覧に出てきた各ロール名について、同じURLの<ロール名>を差し替えて再度開き、さらにcontainsしていないか(2階層目)を確認する

    3. 新しいロールが出てこなくなるまで手順2を繰り返す。今回のitil・adminではそれぞれ4階層・5階層で止まった

    4. 途中で見覚えのないロール、特に他のアプリスコープ名が付いたロールが出てきたら、そのロールのDescriptionを確認する。想定外の権限でないか確かめる

    5. 実際にユーザーへ付与したあとは、sys_user_has_roleでinherited=trueの行を確認すると、展開済みの実効ロール一覧が見られる。ただしinh_countは深さではない点に注意する

    1階層目の件数だけを見て「このロールは小さい」と判断するのは早計です。今回のadminのように、1階層目が少なくても2階層目・3階層目で大きく広がるロールがあります。付与前に最低でも2〜3階層は実際に辿っておくと、想定外の画面が見える事態を避けやすくなります。なお、グループにロールをまとめて配る場合も確認の手順は変わりません。グループ経由の割り当て方法は公式のAssign a role to a group(Zurich)を参照してください。

    実機で気づいたこと

    sys_user_role_containsというテーブル自体には、深さや階層を示すフィールドが一切ありませんでした。role・contains・sys_idの3列だけで、「このロールは何段目か」という情報はどこにも保存されていません。中間表としては素直な作りです。実際に何階層まで積み重なっているかを知りたければ、自分でこのテーブルを繰り返し辿るしかない設計になっています。他の多くのServiceNowテーブルには集計用のフィールドが用意されていることが多いので、この単純さは少し意外でした。

    もう1つ意外だったのは、admin自身のロールレコードにelevated_privilegeやscoped_adminといった「強さ」を示すフラグが一切立っていなかったことです。てっきりadminには何らかの特別フラグがあるものだと思っていました。実機で見る限り、ロールレコード単体はitilとほとんど変わりません。権限が強い理由はロールの設定そのものにはなく、ACL側のAdmin overridesという仕組みに支えられていました。権限の強さを調べるときは、ロールのフラグだけでなくACL側の設定もあわせて見る必要があると学びました。

    inh_countというフィールド名から「継承段数」を思い込んでいたのも、実機を見て初めて誤りに気づいた点です。dependency_viewsのinh_count=8という数字を最初に見たとき、「itilから8階層も離れているのか」と身構えましたが、実際は複数経路からの重複到達を表す値でした。フィールド名の見た目だけで意味を判断しない方がよいと、あらためて感じました。

    用語

    • sys_user_role_contains(Contains Roles):ロールが別のロールを内包する関係を1件ずつ記録する中間表。role(親)とcontains(子)の2参照のみ

    • ロール包含:1つのロールを付与すると、containsで定義された子ロールが自動的に展開される仕組み

    • Admin overrides(sys_security_aclのadmin_overrides):trueの場合、adminロールを持つユーザーはそのACLの条件を見ずに通過する

    • inh_count(sys_user_has_role):継承の段数ではなく、そのロールに到達した経路の本数に近い値

    実機で調べるときに開いたURL

    • /sys_user_role_contains_list.do?sysparm_query=role.name=itil … itilが直接containsする一覧

    • /sys_user_role_contains_list.do?sysparm_query=role.name=admin … adminが直接containsする一覧

    • /sys_user_role.do?sys_id=<itilのsys_id> … itilロールのフォーム(Contains Rolesタブ)

    • /sys_security_acl_list.do?sysparm_query=GROUPBYadmin_overrides … ACLをAdmin overridesで集計した一覧

    • /sys_security_acl.do?sys_id=<ACLのsys_id> … 個別ACLのフォーム(Admin overrides・Requires role)

    よくある質問

    Q1. 1階層目のcontains件数が少ないロールは、権限も狭いと判断してよいですか

    今回のadminのように、1階層目が少なくても2階層目以降で大きく広がるロールがあります。1階層目の件数だけでは判断せず、最低でも2〜3階層は実際に辿ることをおすすめします。特に「〜_admin」のような管理者系ロールは、階層が進むほど広がる傾向が見られました。

    Q2. Admin overridesがtrueのACLと、falseのACLはどう見分けますか

    ACLのフォームにAdmin overridesというチェックボックスがあります。個別に開いて確認する以外に、一覧画面でsysparm_query=GROUPBYadmin_overridesを使うと、true・falseそれぞれの件数を集計表示できます。今回のPDIではほぼ半々でした(true 21,637件・false 22,107件)。

    Q3. Requires roleにadminが指定されているACLは、なぜAdmin overridesがfalseになるのですか

    今回確認したuser_password(query_range)のACLでは、Requires roleにadminが指定されていながらAdmin overridesはオフでした。Admin overridesはロール要件をスキップするかどうかの設定で、Requires roleは通常の条件として要求するロールの設定です。両者は独立した項目なので、adminを要求しつつAdmin overridesをオフにする組み合わせも作れると分かります。内部の優先順位まではPDIの読み取りだけでは確認できておらず、この点は検証範囲外です。

    Q4. カスタムロールを作るとき、containsは自分で設定できますか

    sys_user_roleのフォームにはIncludes rolesという欄があり、そこに子ロールを追加すればsys_user_role_containsにレコードが作られます。ただし今回はPDIの読み取り調査の範囲にとどめており、実際にカスタムロールを作成しての検証は行っていません。

    さらに詳しく知りたい人へ

    参考リンク

    検証環境と未検証範囲

    数値はZurich PDI(OOTB)で2026-08-09に確認したものです。本番環境やカスタマイズ済み環境では、ロール構成・ACL設定・件数が異なります。

    確認した範囲は次のとおりです。

    • sys_user_role_containsの全体件数、フィールド構成、itil・adminそれぞれの直接contains件数

    • 両ロールの包含関係を6階層までBFSで再帰的に走査した階層別件数と合計ユニーク数、2つの木が交差する共通ロール

    • admin・itilロール自身のフラグ(elevated_privilege・scoped_admin・can_delegate・grantable)

    • sys_security_aclのadmin_overridesの全体件数・真偽の内訳、sys_user.user_passwordのACL4件の個別設定

    • デモユーザーのsys_user_has_role内訳とinh_countの値

    確認していない範囲は次のとおりです。

    • ACLエンジンの内部評価順序、スクリプトACLとの優先関係

    • admin_overridesの正確な実装仕様(本文中のリンク先が一次情報。JS描画のページのため本文からの機械的な全文取得はできていない)

    • inh_count・inh_mapの正確な算出ロジック

    • カスタムロールを実際に作成してのIncludes roles設定、本番環境での再現性

    • itil・admin以外の業務ロールでの同様の入れ子調査

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

    あなたへのおすすめ