スクリプト:ACL が評価される状況の理解Issue <!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } 本記事では、Business Rules、UI Scripts、Script Includes、バックグラウンドスクリプト、UI Actions、および Client Scripts における Access Control Rules(ACL)が実行時に評価されるタイミングについて説明します。 Business Rules、UI Scripts、Script Includes、バックグラウンドスクリプト、UI Actions、および Client Scripts を使用する場合、実行時に ACL が評価されるタイミングを理解することが重要です。この動作に対する理解不足は、クライアントサイドおよびサーバーサイド JavaScript に関連する問題を調査する際の問題の原因となることがよくあります。 以下の3つの重要な事実が適用されます。 上記のすべてのスクリプトは、現在のユーザーのコンテキストで実行されます。ServiceNow のサーバーサイド JavaScript API クラスを使用してレコードの作成、読み取り、更新、削除を行うスクリプトは、ACL の合否の対象になりません。GlideRecordSecure クラスはその例外です。ServiceNow のクライアントサイド JavaScript API 関数を使用するスクリプトは、常に ACL を適用します。 Release<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } Resolution<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } State フィールドへの書き込みアクセス権なしでレコードを承認する。 1 つの UI Action が上記の3つの事実をすべて示しています。この UI Action は、テストインスタンスで以下の URL から確認できます。 https://instance-name.service-now.com/nav_to.do?uri=sys_ui_action.do?sys_id=8468ee55c611227d01a072a67bdbd3e7 この UI Action の Client チェックボックスはオフになっており、サーバーサイド JavaScript として実行されます。スクリプトは現在のレコードの state を「approved」に設定し、レコードを更新します。デフォルトではサーバーサイドで ACL が適用されないため、UI Action フォームボタンにアクセスできるユーザーは、sysapproval_approver テーブルの ACL に合格するかどうかに関係なく、現在の承認レコードを承認できます。 UI Action フォームボタンを表示するための条件は、現在のレコードの state が「requested」であり、現在のユーザーがレコードの承認者またはその代理人であることです。ACL によって書き込み権限のないユーザーの承認が防止されるという前提のもと、この条件を緩和してより多くのエンドユーザーにボタンを表示できるようにすると、問題が発生します。 テスト 1:サーバーサイド JavaScript はデフォルトで ACL を無視する。 UI Action の条件を以下から変更します。 current.state == 'requested' && isApprovalMine(current) 以下に変更します。 current.state == 'requested' Application Navigator で Debug を検索し、Debug Security を選択します。ITIL ユーザーに切り替えます。ITIL ユーザーは sysapproval_approver テーブルのすべてのレコードを読み取れますが、ベースシステムインスタンスの State フィールドへの書き込み ACL には合格しません。以下の URL に移動します。 https://instance-name.service-now.com/nav_to.do?uri=sysapproval_approver_list.do state が「requested」のレコードを開きます。ブラウザページで「state/write」というテキストを検索します。Mac では Chrome で ⌘+Enter、Windows では Ctrl+F で検索します。結果から、ITIL ユーザーが sysapproval_approver.state の書き込み ACL に合格しないことが確認できます。Approve UI Action ボタンを選択します。 ACL によって ITIL ユーザーが State フィールドへの書き込みを防止されることが期待されますが、UI Action のサーバーサイド JavaScript は ACL をチェックせずに State フィールドを更新します。そのユーザーが Approve UI Action フォームボタンへのアクセスを許可されていたため、State フィールドへの書き込み ACL に合格できないユーザーによってレコードが承認されます。 サーバーサイドスクリプトで ACL を適用するオプション サーバーサイドスクリプトで ACL を適用するには、以下のいずれかの方法を使用します。 サーバーサイド GlideRecord クラスの canCreate()、canRead()、canWrite()、canDelete() 関数、またはサーバーサイド GlideElement クラスの canRead() および canWrite() 関数を使用します。GlideRecord 関数を使用してテーブルレベルで ACL を確認し、GlideElement 関数を使用してフィールドレベルで ACL を確認します。これらの関数は明快で、ユーザーがアクションを実行できる場合は true、できない場合は false を返します。GlideRecordSecure クラスを使用します。このクラスは GlideRecord と同じように動作しますが、読み取りまたは書き込み対象のテーブルの ACL を適用する点が異なります。 テスト 2:canWrite() で ACL を適用する。 UI Action の条件が以下のままであることを確認します。 current.state == 'requested' スクリプトを以下から変更します。 javascript current.state='approved'; current.update(); 以下に変更します。 javascript if(current.state.canWrite()){ current.state='approved'; current.update(); } UI Action への変更を保存し、ITIL ユーザーに切り替えて、sysapproval_approver テーブルのリクエストを承認しようとします。 State フィールドは「Requested」から「Approved」に変更されなくなります。GlideElement クラスの canWrite() 関数は、更新を許可する前に ITIL ユーザーが sysapproval_approver.state の書き込み ACL に合格できるかどうかを確認します。ユーザーは ACL チェックに合格せず、State フィールドを変更できません。 テスト 3:GlideRecordSecure で ACL を適用する。 UI Action の条件が以下のままであることを確認します。 current.state == 'requested' スクリプトを以下から変更します。 javascript if(current.state.canWrite()){ current.state='approved'; current.update(); } 以下に変更します。 javascript var grs = GlideRecordSecure('sysapproval_approver'); grs.get(current.sys_id); grs.state='approved'; grs.update(); UI Action への変更を保存し、ITIL ユーザーに切り替えて、sysapproval_approver テーブルのリクエストを承認しようとします。 結果はテスト 2 と同じで、ITIL ユーザーは State フィールドを変更できません。手法は異なりますが、結果は同一です。 クライアントサイド JavaScript における ACL 適用の仕組み クライアントサイド JavaScript API 関数は、実行者を制御できないため、常に ACL を適用します。技術的な知識を持つエンドユーザーであれば、ブラウザの JavaScript コンソールを開いて任意のクライアントサイド JavaScript を実行できます。 これは、前の UI Action をクライアントサイド JavaScript で実行するように変更し、クライアントサイド GlideRecord クラスを使用して State フィールドを「Approved」に設定してレコードを更新することで確認できます。 テスト 4:クライアントサイド JavaScript は自動的に ACL を適用する。 UI Action の条件が以下のままであることを確認します。 current.state == 'requested' Client チェックボックスをオンにします。Onclick フィールドに以下を入力します。 approve() スクリプトを以下から変更します。 javascript var grs = GlideRecordSecure('sysapproval_approver'); grs.get(current.sys_id); grs.state='approved'; grs.update(); 以下に変更します。 javascript function approve(){ var gr = new GlideRecord('sysapproval_approver'); gr.get(g_form.getUniqueValue()); gr.state = 'approved'; gr.update(); } UI Action への変更を保存し、ITIL ユーザーに切り替えて、sysapproval_approver テーブルのリクエストを承認しようとします。 ACL が適用されるようにするための特別な対応は不要です。ServiceNow のクライアントサイド JavaScript API は常に ACL を適用します。これらの違いを理解することが、ServiceNow JavaScript API に関連する問題の解決において重要です。