2020.03.02

Spring'20に学ぶSalesforceの項目へのアクセス制御事情

はじめまして!テラスカイで開発を担当している鬼丸です。
今回はSpring'20で正式リリースされる項目ごとのセキュリティについてご紹介します。

Salesforceでは通常オブジェクトの権限や項目レベルセキュリティ、共有ルールを使用してユーザごとにデータへのアクセスを制御します。
しかしApexはシステムコンテキストモードで実行されるため、実行ユーザの権限や項目レベルセキュリティ、共有ルールに従いません。
 (※クラスにwith sharingをつけることで、共有ルールは適用されます)

では今まではどうやってフィールドレベルセキュリティを確認していたでしょうか?

今までのアクセスチェック、スキーマメソッドの使用

Spring'20以前も項目レベルでアクセスチェックする方法はあります。
プログラムを実行しているユーザを使用し、プログラム上で項目を読み取り、作成、更新アクセス権を持っているかの確認をすることができます。

たとえば、実行しているユーザが取引先責任者オブジェクトの電話項目にアクセスできるかを確認する場合は以下のようにします。
if (Schema.sObjectType.Contact.fields.Phone.isAccessible()) {
   Contact c = [SELECT Phone FROM Contact WHERE Id= :Id];
}
項目のアクセス権をチェックする方法
しかし都度チェックを行うため、複数の項目がある場合は複雑になりがちでした。

新しい項目へのアクセス制御 その1(WITH SECURITY_ENFORCED句)

まず一つ目はSpring'20よりベータ版から正式版として利用可能になる「WITH SECURITY_ENFORCED句」です。
この「WITH SECURITY_ENFORCED句」は通常にSOQLクエリはもちろんですが、サブクエリや集計関数使用時にもアクセス権のチェックを行います。

この句はSELECT句で取得するすべての項目が適用されます。
もし実行しているユーザに項目の読み取り権限がない場合は「System.QueryException」の例外をスローします。

そのため必ず、try / catchブロックで囲む必要があります。
以下が例になります。
List<Account> account = new List<Account>();

try{
    account = [SELECT Id, Name, (SELECT Phone FROM Contacts) FROM Account WHERE Rating = 'Hot' WITH SECURITY_ENFORCED];
} catch(System.QueryException){
    //エラーを記入
}
WITH SECURITY_ENFORCED句の使用例
1つだけ使用時の注意点があります。
WHERE句で使用されるフィールド、(例だとRating項目)は項目レベルのセキュリティ検証は行われません。

新しい項目へのアクセス制御 その2(stripInaccessibleメソッド)

次に2つ目もSpring'20よりベータ版から正式版として利用可能になる「stripInaccessibleメソッド」です。

stripInaccessibleメソッドはフィールドおよびオブジェクトのセキュリティチェックを行うことができるようになりました。

以下が例になります。
List<Account> accounts = new List<Account>{
    new Account(Name='取引先1', Type='Prospect', Website='https://base.terrasky.co.jp/'),
    new Account(Name='取引先2', Type='Installation Partner', Website='https://base.terrasky.co.jp/')
};

SObjectAccessDecision accessAccounts = Security.stripInaccessible(AccessType.CREATABLE, accounts);

try {
    insert accessAccounts.getRecords();
} catch(NoAccessException e) {
    // 例外処理
}
stripInaccessibleメソッドの使用例
このstripInaccessibleメソッドはgetRecordsメソッドを使用して実行ユーザの項目レベルのセキュリティチェックに失敗した項目を取り除かれたsObjectへアクセスします。

例えば上記例でいうと、種別項目(Type)へのアクセス権がない場合は種別に追加された項目が削除されinsert(登録)されます。
Accountオブジェクト自体に作成権限がない場合は例外をスローします。

実際に上記例のプログラムを実行結果は以下になります。

1つ目の画像は権限があるユーザで実行した場合で、2つ目の画像は実行結果がないユーザでの実行結果です。

実行権限のあるユーザで実行した例

実行権限のないユーザで実行した例

例ではアクセス権のチェック種別は作成時の「AccessType.CREATABLE」ですが、他のアクセス権もチェックすることができます。
CREATABLE 項目の作成アクセス権についてチェックします
READABLE 項目の読み込みアクセス権についてチェックします
UPDATABLE 項目の更新アクセス権についてチェックします
UPSERTABLE 項目の追加および更新のアクセス権についてチェックします

所感

個人的にはWITH SECURITY_ENFORCED句よりもstripInaccessibleメソッドの方が使用する機会が多いのでは?と感じました。

stripInaccessibleメソッドを使用することでプログラムコードのステップ数削減、今まで実装に時間のかかっていたアクセス権のチェックがだいぶ容易になったと言えそうです。


Salesforceでお困りごとやご相談したいことがありましたら、テラスカイへご連絡ください。
21 件
     
  • banner
  • banner

関連する記事