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

ロールを付けたのに見えない理由:ACL(sys_security_acl)


    ServiceNow を触っていると、「ロールを付けたのにレコードが見えない」「編集できると思った項目が読み取り専用のまま」という場面に出会います。その振る舞いを決めているのは、多くの場合 ACL(Access Control=アクセス制御)です。


    画像

    ServiceNow の権限は、ロール(sys_user_role)を付けるだけでは完結しません。実際に「誰が・どのテーブルの・どの項目を・どの操作(読む/書く/作る/消す)できるか」を定義するのは、ACL という1行ずつのルールです。ACL は sys_security_acl というテーブルに保存されます。

    この記事では、ACL をセキュリティ論だけで説明しません。実際の sys_security_acl テーブルを起点に、上位の sys_metadata と、対象を表す name(table 単位か field 単位か)を確認します。続けて operation と type の参照値、要件となる roles / condition / script の組み合わせを見ます。最後に admin_overrides と、ACL とロールをつなぐ中間表 sys_security_acl_role です。

    この記事は、ServiceNow の Incident は触ったことがあるが、権限がどこで決まっているか(ACL のテーブル構造)をこれから理解したい人を想定しています。管理者・開発者が実機で「ロールを付けたのに見えない/編集できない」を調べるときに見るべきポイントとして、ACL の対象・operation・要件を取り上げます。

    この記事で分かること

    • ServiceNow の権限が sys_security_acl(ACL)の1行ずつのルールで定義されること

    • ACL には table 単位(name=incident)と field 単位(name=incident.field)があること

    • operation(read / write / create / delete ほか)と type が「選択肢」ではなく参照値であること

    • 1つの ACL が roles / condition / script の組み合わせで要件を持つこと

    • admin_overrides と decision_type(Allow If / Deny Unless)の役割

    • 「ロールを付けたのに見えない/編集できない」を ACL のどこから調べるか

    この記事の内容は ServiceNow の PDI(Personal Developer Instance)Zurich(ズーリッヒ)リリースの OOTB(初期設定)で確認した個人メモです。本番環境やカスタマイズ済み環境では、ACL の件数・条件・スクリプトの内容が異なる場合があります。また ACL の「評価順(field と table のどちらが先か、deny が優先か、最も具体的なルールが勝つか 等)」は1つのテーブル構造だけでは確認できないため、本記事では扱いません(後述の「検証範囲とおことわり」を参照)。


    ACL(アクセス制御)とは

    ServiceNow の「見える/編集できる」は、ACL という1行ずつのルールで決まります。ロールはその要件のひとつにすぎません。

    ACL(Access Control List)とは、ServiceNow で「どのロールを持つ人が、どのデータの、どの操作をできるか」を定義するルールです。ロールはあくまで「鍵束」で、実際に開く鍵穴(どのテーブル・どの項目・どの操作)を決めているのが ACL です。公式ドキュメントでも、ACL ルールは Access Control List Rules(Zurich)で「保護するオブジェクトと操作」を指定するものと説明されています。

    ServiceNow では、この ACL を格納する中心テーブルが sys_security_acl です。1レコード=1つの権限ルールです。「incident テーブルを read できるのは itil ロール」「incident.work_notes フィールドを read できるのは…」といったルールが、それぞれ別レコードとして並びます。

    ロールを付けたユーザーが何かを見られない/編集できないとき、原因はロールの不足とは限りません。対応する read / write の ACL を満たしていない、field 単位の ACL でその項目だけ制限されている、condition や script の条件を満たしていない。こうした ACL 側の理由であることが多くあります。


    sys_security_acl は「設定(メタデータ)」側のテーブル

    ACL のまわりの継承関係を見ると、ACL は incident や cmdb_ci のような業務データではなく、「設定(メタデータ)」側のテーブルであることが分かります。


    画像

    今回確認した PDI(Zurich / OOTB)では、sys_security_acl のラベルは Access Control でした。継承元は sys_metadata(ラベル:Application File)です。task 系(incident など)や cmdb 系(cmdb_ci など)が「業務データ」を表すのに対し、ACL は Business Rule や UI Policy と同じく「アプリの設定」を表します。だからメタデータ系の基底 sys_metadata の下に位置します。

    ACL とロールを結びつけるのは sys_security_acl_role(ラベル:Access Roles)という中間表で、これも sys_metadata を継承していました。1つの ACL に複数のロールを必要条件として結びつけるための m2m(多対多)テーブルです。

    クラスの位置づけは、次のURLで確認できます(先頭の <YourInstance> は自分のインスタンスに置き換えてください)。

    https://<YourInstance>/sys_db_object_list.do?sysparm_query=name=sys_security_acl


    画像

    ACL の対象:table 単位と field 単位

    ACL がどこに効くかは、レコードの name フィールド(型は composite_name)の書き方で決まります。名前の形そのものが「table 全体に効くのか、特定フィールドに効くのか」を表します。


    画像

    今回確認した PDI(Zurich / OOTB)では、name は次のように使い分けられていました。

    • table 単位 … name = テーブル名そのもの(例 incident)。その表のレコード全体に対する read / write / create / delete を制御します。

    • field 単位 … name = table.field(例 incident.work_notes)。特定フィールドの read / write を制御します。

    • field 既定 … name = table.*(例 incident.*)。個別に指定されていない全フィールドの既定として効きます。

    実例として、name=incident(table 単位)の ACL は今回の PDI で24件、incident. で始まる field 単位の ACL は84件ありました。incident.work_notes(read)や incident.*(read)など、項目ごとに別レコードとして存在します。「ロールはあるのにこの項目だけグレーアウトする」というとき、まずこの field 単位の ACL を疑います。

    対象が table か field かは、次のURLで一覧して name の形を見れば確認できます。

    https://<YourInstance>/sys_security_acl_list.do?sysparm_query=nameSTARTSWITHincident


    画像

    operation と type は「選択肢」ではなく参照値

    operation と type は固定の選択肢ではなく、別テーブルを参照する値でした。だから一覧したいときは参照先のテーブルを見ます。

    operation(操作)と type(種類)は、よくある選択肢(choice)フィールドではなく、別テーブルを参照する reference フィールドでした。なお read / write / create / delete といった操作が何を制御するかは、公式の ACL rule types(Zurich)に table 単位・field 単位それぞれの一覧があります。

    参照先                               件数  代表的な値
    -----------------------------------------------------
    operation(sys_security_operation)  18    read / write / create / delete / execute / report_on / report_view / list_edit / query_match / edit_ci_relations ほか
    type(sys_security_type)            15    record(テーブル・フィールド行アクセス) / processor / ui_page / REST_Endpoint / GraphQL / flow / ux_page ほか
    decision_type(choice)              2     allow(Allow If) / deny(Deny Unless)

    今回確認した PDI(Zurich / OOTB)では、次の構成でした。

    • operation … 参照先は sys_security_operation で、値は18種ありました。read / write / create / delete のほか、execute / report_on / list_edit / edit_ci_relations などが含まれます。ほかに add_to_list・query_range・personalize_choices・save_as_template・data_fabric・invoke_from_ai もあります。「見えるか」は read、「編集できるか」は write が決めます。

    • type … 参照先は sys_security_type で、値は15種ありました。大半の ACL が使うのは record(テーブル・フィールドの行アクセス)です。ほかに processor / ui_page / REST_Endpoint / GraphQL / flow / ux_page など、レコード以外のリソースに対する種類もあります。flow_action・ux_route・ux_data_broker のほか、gen_ai_skill・gen_ai_workflow・gen_ai_agent という種類もありました。

    • decision_type … こちらは選択肢(choice)で、allow(Allow If)と deny(Deny Unless)の2値でした。

    operation の全18種

    read, write, create, delete, execute, report_on, report_view, add_to_list
    query_match, query_range, conditional_table_query_range, list_edit
    personalize_choices, edit_task_relations, edit_ci_relations
    save_as_template, data_fabric, invoke_from_ai

    type の全15種

    record, processor, ui_page, REST_Endpoint, GraphQL, flow, flow_action
    client_callable_script_include, client_callable_flow_object
    ux_page, ux_route, ux_data_broker
    gen_ai_skill, gen_ai_workflow, gen_ai_agent

    なお、operation と type が参照フィールドであるため、選択肢を一覧しようとして sys_choice を引いても値は出ません(参照先テーブルから取得する必要があります)。この点は実機で確認するときの注意点です。

    operation の参照先は、次のURLで一覧できます。

    https://<YourInstance>/sys_security_operation_list.do


    画像

    1つの ACL が持つ「要件」:roles / condition / script

    1つの ACL レコードは、「対象(name・type・operation)」に加えて、満たすべき「要件」を持ちます。要件は roles・condition・script の3つを組み合わせて表現します。


    画像

    主なフィールドの代表は次のとおりです。ラベルは画面上の表示名で、実機どおり英語で記載します。

    Field               Label               Type / 参照先                       役割
    --------------------------------------------------------------------------------
    name                Name                composite_name                      対象。table 名(incident)または table.field(incident.work_notes)
    operation           Operation           Reference → sys_security_operation  操作(read / write / create / delete 等)
    type                Type                Reference → sys_security_type       対象の種類(record / processor / ux_page 等)
    decision_type       Decision Type       Choice                              Allow If / Deny Unless
    admin_overrides     Admin overrides     Boolean(既定 true)                admin ロールで上書き許可するか
    active              Active              Boolean(既定 true)                有効/無効
    advanced            Advanced            Boolean(既定 false)               詳細モード(script を評価)
    condition           Condition           Conditions                          レコード条件式
    script              Script              Script(plain)                     詳細条件のスクリプト
    security_attribute  Security Attribute  Reference → sys_security_attribute  属性ベースの制御(任意)

    固有フィールドは全部で15あります。表に挙げた項目のほか、description(説明)・applies_to(適用範囲)・controlled_by_refs(参照制御)も含まれます。

    要件の3つは次の役割でした。

    • roles … その操作に必要なロール。ACL 本体ではなく中間表 sys_security_acl_role に「ACL ↔ ロール」として保存されます(後述)。

    • condition … レコードの条件式。たとえば「自分が assigned_to のときだけ」のように、レコードの値で絞ります。今回の PDI では condition を設定した ACL は964件ありました。

    • script … より複雑な判定をスクリプトで書きます。advanced(詳細)を true にすると script が評価され、今回の PDI では advanced=true(=script あり)の ACL は3,137件で一致していました。

    加えて、decision_type が Allow If(既定)か Deny Unless かで「条件を満たしたら許可」か「条件を満たさない限り拒否」かが変わります。admin_overrides は、admin ロールでこの ACL を上書きできるかどうかのフラグです。今回の PDI では admin_overrides=true が20,791件、false が21,680件と、ほぼ半々でした。false が付いた ACL は admin でも上書きが効かない設計とされますが、実際の評価挙動は今回の確認範囲外です。

    要件を確認するときは、次のURLで個々の ACL を開きます。

    https://<YourInstance>/sys_security_acl_list.do?sysparm_query=scriptISNOTEMPTY


    画像

    ACL とロールをつなぐ中間表(sys_security_acl_role)

    「必要なロール」は ACL 本体のフィールドではなく、sys_security_acl_role という専用の中間表に、1行=1つの「ACL ↔ ロール」の組として保存されます。

    関連は sys_security_acl_role が持ちます。sys_security_acl(→ sys_security_acl)と sys_user_role(→ sys_user_role)の参照ペアです。1つの ACL に複数ロールを結びつけたい場合は、その分だけ行が増えます。今回確認した PDI(Zurich / OOTB)では、sys_security_acl_role は39,600件ありました。

    sys_security_acl_role の固有フィールド

    固有フィールドは4です。sys_security_acl(→ sys_security_acl)、sys_user_role(→ sys_user_role)、transaction_id、sys_id で構成されます。

    代表例を挙げます。ACL=ml_labeled_data には role=ml_labeler、ACL=sys_cs_vendor_context_configuration.* には role=admin が結びついていました。「ロールを付けたのに見えない」を調べるときは、対象の ACL がどのロールを要求しているかを、この中間表(または ACL フォームの Requires role リスト)で確認します。

    ロールの結びつきは、次のURLで確認できます。

    https://<YourInstance>/sys_security_acl_role_list.do


    画像

    「ロールを付けたのに見えない/編集できない」を ACL から調べる

    調べる順番は、read / write の ACL → field 単位の ACL → condition / script → admin_overrides です。

    ここまでの構造をふまえると、「ロールを付けたのに見えない/編集できない」を ACL のどこから調べればよいかが整理できます。ACL そのものの探し方は、公式の Explore Access Control Lists(Zurich)も参考になります。


    画像

    今回確認した PDI(Zurich / OOTB)では、ACL の総数は42,471件でした。その大半(type=record で40,314件)がテーブル・フィールドの行アクセスです。operation 別では read 7,743件、write 7,848件と、「見えるか(read)」「編集できるか(write)」を決める ACL がそれぞれ多数あります。

    観点                              件数            メモ
    ------------------------------------------------------
    総数(全 ACL)                    42,471          OOTB 全件
    active=true                       42,398          ほぼ全件が有効
    type=record                       40,314          大半はテーブル/フィールドの行アクセス
    operation=read                    7,743           「見えるか」を決める
    operation=write                   7,848           「編集できるか」を決める
    operation=create                  5,874           新規作成
    operation=delete                  5,768           削除
    operation=execute                 1,684           実行
    operation=report_on               0               レポート対象(今回は0件)
    admin_overrides=true              20,791          admin で上書き可
    admin_overrides=false             21,680          admin でも個別評価
    decision_type=allow / deny        33,756 / 8,715  Allow If が多数、Deny Unless も存在
    condition 設定あり                964             レコード条件で絞る ACL
    script 設定あり(advanced=true)  3,137           スクリプトで判定する ACL

    切り分けはこの順です。まず対象テーブルの read / write の ACL があるか。次に field 単位の ACL でその項目だけ制限されていないか。さらに condition / script の条件を満たしているか。最後に admin_overrides の有無を見ます。なお、複数の ACL が同じ対象に該当するときに「どれが優先されるか(評価順)」は、件数や1テーブルの構造だけでは判断できません。この評価ロジックは本記事の確認範囲外とし、別記事で扱います。

    自分のインスタンスでは、次のURLで対象テーブルの ACL を一覧できます。

    https://<YourInstance>/sys_security_acl_list.do?sysparm_query=nameSTARTSWITHincident^operation=read

    ServiceNow における ACL(sys_security_acl)のポイント

    • ServiceNow の権限は、ロールを付けるだけでなく sys_security_acl の1行ずつのルール で決まります。ACL は業務データではなく sys_metadata を継承する「設定(メタデータ)」側のテーブルです。

    • ACL の対象は name の形で決まります。table 単位(name=incident)と field 単位(name=incident.field / incident.*)があります。今回の PDI では incident の table 単位 ACL は24件、incident. 始まりの field 単位 ACL は84件でした。

    • operation と type は選択肢ではなく参照値でした。operation は sys_security_operation を参照し18種(read / write / create / delete ほか)です。type は sys_security_type を参照し15種(record が大半)。decision_type だけが choice(allow / deny)です。

    • 1つの ACL は roles / condition / script の組み合わせで要件を持ちます。今回の PDI では condition あり964件、script あり(advanced=true)3,137件でした。必要なロールは中間表 sys_security_acl_role(39,600件)に保存されます。

    • admin_overrides は admin による上書きの可否で、今回の PDI では true 20,791件 / false 21,680件とほぼ半々でした。false が付いた ACL は admin でも上書きが効かないとされますが、評価挙動は確認範囲外です。

    • 「見えない/編集できない」は、read / write の ACL → field 単位の ACL → condition / script → admin_overrides の順で切り分けます。ただし複数 ACL の評価順は本記事の確認範囲外です。

    ACL を調べるときは、まず「いま見ている ACL の対象は table か field か(name の形)」を意識します。そのうえで operation・要件(roles / condition / script)・decision_type・admin_overrides をセットで読みます。


    実機で気づいたこと

    • operation の18種類の中に invoke_from_ai、type の15種類の中に gen_ai_skill・gen_ai_workflow・gen_ai_agent という値があるのは意外でした。ACL はテーブルやフィールドの読み書きを制御する仕組みだと思っていましたが、AIエージェントやスキルの呼び出しも同じ ACL の枠組みで権限管理されている点に、プラットフォームの権限モデルが拡張され続けている様子がうかがえます。

    • admin_overrides は true が20,791件・false が21,680件とほぼ半々でした。「admin ロールなら何でも見える」と思い込みがちですが、実際には半数近くの ACL が admin でも上書きできない設計です。強い権限を持つユーザーでも一部のデータは意図的に見せない、という設計思想が数の上にも表れています。

    • ACL とロールの中間表 sys_security_acl_role は39,600件ある一方、ACL 自体は42,471件でした。単純に割ると1 ACL あたり1件に届きません。これは condition や script だけで判定し、role を必要としない ACL がそれなりの数あることを示していると読めます。


    次に読むなら

    次に確認したいのは、ACL の評価順です(field と table の評価順序、Allow / Deny の優先、最も具体的なルールが勝つかどうか)。加えて、ロールの含意(継承。あるロールが別のロールを含むときの解決)と、Contextual Security(条件・スクリプトによる行レベル制御)です。特に「同じ対象に複数の ACL が該当したとき、どのルールで最終判断されるか」は、権限のトラブルシュートで最も悩むところです。これらは1つのテーブル構造だけでは確認できないため、本記事では扱わず別記事で解説する予定です。


    用語

    • PDI:Personal Developer Instance(無料の検証用インスタンス)

    • OOTB:Out of the Box(初期設定のまま)

    • ACL:Access Control(List)(アクセス制御。1行=1つの権限ルール)

    • ロール(sys_user_role):権限の束。ACL の要件として参照される

    • table 単位 / field 単位:ACL が表全体に効くか、特定フィールドに効くか(name の形で決まる)

    • operation:read / write / create / delete など、制御する操作

    • decision_type:Allow If(許可)/ Deny Unless(拒否)の判定方向

    • admin_overrides:admin ロールでこの ACL を上書きできるか

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

    先頭に自分のインスタンスを付けると、同じ画面が開けます。

    テーブル定義        : sys_db_object_list.do?sysparm_query=name=sys_security_acl
    ACL 一覧            : sys_security_acl_list.do
    対象テーブルの ACL  : sys_security_acl_list.do?sysparm_query=nameSTARTSWITHincident
    operation 参照先   : sys_security_operation_list.do
    type 参照先        : sys_security_type_list.do
    ACL↔ロール 中間表  : sys_security_acl_role_list.do

    検証範囲とおことわり

    • 確認した範囲:sys_security_acl / sys_security_acl_role の継承(sys_metadata)、固有フィールド(operation/type は参照、decision_type は choice)、operation 18種・type 15種・decision_type 2種、各種件数(総数・operation 別・type=record・admin_overrides・active・decision_type・condition/script/advanced)、table 単位と field 単位の name の形(incident 例)、ACL とロールの中間表の構造と件数。すべて PDI(Zurich / 2026-06-20 確認)の OOTB で取得しています。

    • 確認していない範囲:ACL の評価順(field と table のどちらが先か、deny が優先か、最も具体的なルールが勝つか 等の評価ロジック)。これは1つのテーブル構造だけでは確認できないため本記事では扱いません。各 ACL の script の中身・実行挙動、Contextual Security の細部、ロールの含意(継承)の解決、High Security Settings との関係も本記事の範囲外です。これらは別記事で扱います。

    今回は PDI の OOTB(初期設定)を前提に、ACL のテーブル構造を確認しました。実環境では、既存のカスタマイズによって ACL の件数・条件・スクリプトの内容が変わります。権限のトラブルは、構造(本記事)と評価順(別記事)の両面から確認してください。

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

    あなたへのおすすめ