はじめに
Dreamforce '14 「Secure Coding: Field-level Security, CRUD, and Sharing」
2014/10/13 Mon 11:00 AM - 11:40 AM Moscone Center West, 2009
『Secure Coding: Field-level Security, CRUD, and Sharing』 なるセッションを受けて、自分なりにまとめてみたいと思います。スピーカーは、Salesforceの製品セキュリティエンジニアである、Kyle Tobener氏と Maxwell Feldman氏です。彼らの主張を、英語のわからない&道半ばのSalesforceデベロッパである、私の解釈を織り交ぜて執筆します。
誤りがありましたら、ご指摘下さい。 尚、当投稿では、Dreamforce '14 の熱さはまったく伝わりませんので、ご容赦下さい。
まず、セキュアコーディングの指針について
指針:最小権限の原則に基づくべきである。 アクセス権は、業務上の必要範囲に制限する。つまり、そのユーザーにとって必須な権限のみを与える事が大事である、と。 早速、本題に入りたいと思います。
CRUDとは何か?
Create、Read、Update、Delete 生成、読み取り、更新、削除という、アプリケーションが備えるべき4つの基本機能のこと。
Salesforceは、クラウド上に配置された壮大なデータベースシステムであり、その上に自由にアプリケーションを配置できるのが醍醐味と思います。(自論) よって、CRUDを的確にコントロールするのは重要です。 ここで彼らの言っているCRUDは、オブジェクトレベルでの制御です。 これは、原則として、プロファイルごとに設定します。
Salesforceデベロッパにとっての、CRUDの注意点
彼らの言葉です。
- Apexクラスは、(原則)システムモードで実行されるので、CRUDを遵守しない。
- Visualforceページは、ユーザモードで実行されるので、CRUDを遵守する、と。
よって、Apexクラスでは、確認を怠るなと主張したいのだと思います。 事実、私達の開発するSalesforceアプリケーションにおいても、実行ユーザの、そのオブジェクトに対する各種権限(CRUD)の有無の確認を、クエリやDML実行前にチェックするようにしています。
Apexクラスで、ある目的のオブジェクトに対して権限があるかを確認するには、次のような構文が用意されています。
Field Level Security(FLS)とは何か?
項目レベルでCRUDをコントロールします。 言っている傍から恐縮ですが、厳密にはCRUDではありません。 項目ごとに、必須、編集可能、参照のみ、非表示、などといった細かな設定が出来ます。 これもプロファイル上で設定します。
Salesforceデベロッパにとっての、FLSの注意点
彼らの言葉です。
- Apexは、(原則)システムモードで実行されるので、FLSを遵守しない。
- Visualforceは、ユーザモードで実行されるので、FLSを遵守する、と。
よって、オブジェクト同様に項目レベルにおいても、Apexクラスでは、確認を怠るなと主張したいのだと思います。 Apexクラスで、ある目的の項目に対して権限があるかを確認するには、次のような構文が用意されています。 削除はどうするのか?といった疑問があるかもしれませんが、 Salesforceでは、削除権限は、項目ごとではなく、オブジェクトに対して付与するので、 目的のオブジェクトに対して、削除権限があるかを確認して下さい。
Sharingとは何か?
レコードレベルでのアクセス権を制御するものです。 Salesforceでは、組織の共有設定、ロール、所有者、共有ルールに従って、あるオブジェクトの、あるレコードへのアクセス権が決定されます。 ここでは、これら全般を指して "sharing" と呼んでいると思われますので、これ以降の"共有設定"は、組織の共有設定だけでなく、上述全般を指していると思って下さい。
彼らの言葉です。
- Apexクラスは、(原則)システムモードで実行されるので、共有設定を遵守しない。
- Visualforceページが共有設定を遵守するかは、コントローラに依存する、と。
- 例外:標準コントローラは、共有設定を遵守する。
例によって、Apexクラスは、ルールを遵守しません。 Visualforceページで言っている、コントローラとは、その名の通り、ページのコントローラクラスなのですが、これには、いくつか種類があります。
- 標準コントローラは原則ユーザモードであり、
- カスタムコントローラはシステムモード、
- コントローラ拡張は拡張元に依存する
など、種類と各々の動きや制約があります。 標準コントローラにおいても、項目の記述方法によっては、CRUD、FLS&Sharingが適用されないケースがありますので、製品マニュアルの熟読と、十分な試験を実施して下さい。
Apexで、共有設定を効かすには
彼らの言葉です。
- ・共有設定を効かすには、"With Sharing" キーワードを使用する。
- ・呼び出されたクラスは、定義された共有を尊重する。共有が定義されない場合、それらは呼出元からの共有を継承する。
どういう事か?
- メソッドがコールされるクラスの共有設定ではなく、メソッドが定義されているクラスの共有設定が適用される。 たとえば、"with sharing" が宣言されたクラス内に定義されているメソッドが、"without sharing" が宣言されたクラスでコールされる場合、そのメソッドの実行では共有ルールが適用される。
- "with sharing" も "without sharing" もクラスで宣言されていない場合、現在の共有ルールが有効となる。 つまり、そのクラスが、共有が強制実行されているクラスからコールされると、コールされたクラスでも共有が強制実行される。
- クラスが別のクラスを拡張または実装している場合、親クラスからこの設定が継承される。
こういったことを、伝えたいのだと思います。
共有における振る舞い
さいごに
実務に直結する講義を受け、このブログにまとめたいと思い、こうして起してみましたが、私が取り上げるには、深遠なるテーマで執筆早々に後悔しました。が、当然引き下がることもできず。。
地味ではありますが、デリバリを生業とする私達にとって、絶対に外せないテーマですので、取り上げました。lightningと呼ばれる新しいフレームワーク上においても、こういった基本は変わらないと思います。
本来、ざっと語れるテーマではありませんので、例外は常に存在します。 あらゆるケースに基づいて十分に試験を実施して下さい。 何より、マニュアルをよく読んで下さい。 自戒の念も込めて。 Salesforce デリバリに携わる後輩達の一助になれば幸いです。