Salesforce レコードへのアクセス制御方法（共有設定・共有ルール等）まとめ

# はじめに
この記事は [チームスピリット Advent Calendar](https://adventar.org/calendars/3426) の 23日目の記事です（遅れてすみません…）。

# この記事は何
* オブジェクトへのアクセス権限
* 共有設定
* 共有ルール
* 項目レベルセキュリティ

あたりが訳わからなくなってきたので、対象の [Trailhead](https://trailhead.salesforce.com/ja/content/learn/modules/data_security) を見ながらまとめた。
あと自社内でも、私と同様によく分からないという人が何人かいたので、これを読めばとりあえずOKになるようにした。
n番煎じだったらすみません。

# Salesforce のアクセス制御とは
オブジェクトごとに、「組織内のどのユーザにどんなデータを見せるか」を制限できる。

たとえば以下の例を想定する：

* 「エンジニア採用候補者」というオブジェクトを作成する。
  * 開発者が「一緒に働きたい人」をレコード作成しておくと、人事部の担当者がその人にアプローチをしにいく、という流れを想定。
* このオブジェクトは、この採用活動に関係がない部署には見せないようにしたい。
* 採用に関係する部署にはレコードを見せるが、以下のルールを採用したい。
  * 個人情報保護のため、そのレコードを作成した人と、その人よりも上の階層の人（部長や社長など）以外にはレコードが見られないようにしたい。
  * しかし、上記の条件とは別に、採用フローに関わっている人事部のメンバーには見えるようにしたい。
  * うまく採用が進んだときのために「提示給与」という値を保存しておきたいが、人事部と社長にしか見えないようにしたい。

上記のような複雑な制御も、オブジェクトへのアクセス制限と共有設定を組み合わせれば比較的簡単に実現できる。

# 詳細

1. オブジェクト・項目へのアクセス権限
2. レコードへのアクセス権限（共有設定）

## 1. オブジェクト・項目へのアクセス権限

### オブジェクト権限
オブジェクトのCRUD権限と、レコード全体へのアクセス権限を管理できる。
基本的に、共有設定よりも優先される。

設定方法：「設定＞ユーザ＞プロファイル」画面で、プロファイルごとに指定できる。

|設定できる内容|詳細|ONの場合|OFFの場合
|:-------|:--------|:--------|:--------|
| 参照|レコードの参照権限|共有設定に従って参照できる|**共有設定にかかわらず、全レコードを参照できない**|
| 作成|レコードの作成権限|レコードを作成できる|レコードを作成できない|
| 更新|レコードの更新権限|共有設定に従って更新できる|共有設定にかかわらず、全レコードを更新できない|
| 削除|レコードの削除権限|共有設定に従って削除できる|共有設定にかかわらず、全レコードを削除できない|
| すべて参照|全レコードの参照権限|**共有設定にかかわらず、全レコードを参照できる**|共有設定に従う|
| すべて更新|全レコードの更新権限|**共有設定にかかわらず、全レコードを参照・更新できる**|共有設定に従う|

プロファイルが「システム管理者」の場合は、全オブジェクトの「参照・作成・更新・削除・すべて参照・すべて更新」がONになる。
また、「権限セット」をあらかじめ作成しておき、各ユーザに割り当てることで、プロファイル毎の権限に加えて追加の権限を与えることができる。

先ほど挙げた「エンジニア採用候補者」の例で言えば、「エンジニア採用に関係ある部署とそうでない部署でプロファイルを分け、前者にのみ『エンジニア採用候補者』への参照・更新権限を付与する」とよい。（権限セットを使って個別のユーザに付与してもよい）

### 項目レベルセキュリティ
上記と同様、プロファイルから設定する。

オブジェクトの各項目について、「参照」「更新」ができるかどうかを個別に設定できる。
（システム管理者の場合は、全項目に対して参照・更新が可能）

「エンジニア採用候補者」の例だと、「人事部に適用するプロファイルに対してのみ、『エンジニア採用候補者』オブジェクトの『提示給与』項目に参照・更新権限を設定し、それ以外のプロファイルでは権限を付与しない」というようにする。
（権限セットを使ってもよい）

## 2. レコードへのアクセス権限（共有設定）
オブジェクト全体に対する権限とは別に、オブジェクトのそれぞれのレコード単位で「参照・更新できるかどうか」を制御できる。
設定範囲が広い順に、「組織の共有設定」「ロール設定」「共有ルール」「個別の共有設定」がある。基本的に、「設定範囲が広い方ほど制約を厳しくすべき」という原則がある（はじめに最も厳しい条件で制約をかけ、個別に例外条件を追加することで権限を広げていくようにする。逆だとうまく設定することができない）。

### 組織の共有設定
「レコードを誰が参照できるか」のデフォルトの設定にあたる。

設定方法：「設定＞セキュリティ＞共有設定」画面で、オブジェクトごとに設定する。

カスタムオブジェクトの場合、主に以下の3つが選択できる（デフォルトのオブジェクトの場合は異なる選択肢があるものもある）。

|設定|内容|
|:-------|:--------|
|非公開|レコードの所有者のみがレコードを参照・更新できる|
|公開/参照のみ|レコードの所有のみがレコードを更新できる。それ以外の全ユーザは参照のみできる|
|公開/参照・更新可能|レコードの所有者にかかわらず、全ユーザが参照・更新できる|

これらとは別に「**階層を使用したアクセス許可**」というチェックボックスがあり、これにチェックを入れると、上記の設定に加えて「レコードの所有者よりもロール階層が上位であればレコードを参照・更新できる」ようになる（後述）。

先ほどの「エンジニア採用候補者」の例で言うと、「本人と上位階層のみアクセスできるようにしたい」ので、組織の共有設定としては「非公開」にし、「階層を使用したアクセス許可」にはチェックを入れておく。


### ロール
「ロール」というツリー構造のデータを作成し、各ユーザに割り当てることで、「上位の階層であれば、下位の階層が所有するレコードにアクセスできる」ようにすることができる。

設定方法：「設定＞ユーザ＞ロール」で設定する。

たとえばこのようなロールがあるとする：
役員
　└開発部リーダー
　　└開発部メンバー
　└人事部リーダー
　　└人事部メンバー

ここで、「開発部メンバー」のロールを持つ社員が「エンジニア採用候補者」のレコードを作成した場合、「作成した本人」「『開発部リーダー』ロールの人」「『役員』ロールの人」がレコードを見られる。作成者本人以外の開発部メンバーや、人事部リーダー、人事部メンバーはそのレコードは見られない。

### 共有ルール
上記の「組織の共有設定」「ロール」とは別に、例外のルールを個別に設定できる。
共有ルールは、「この条件のレコードに対して」「この条件の人が見られる」という形で設定する。

設定方法：「設定＞セキュリティ＞共有設定」画面で、オブジェクトごとに設定する。

「エンジニア採用候補者」の例だと、共有の条件を「ロール＆下位ロール：役員」、共有先を「ロール＆下位ロール:人事部リーダー」とすることで、人事部リーダーと人事部メンバーが、役員およびそれ以下の階層が所有するレコードを見られるようになる。

共有ルールはかなり柔軟に設定することができ、共有の条件としてロール単位でなくレコードの特定項目の値を指定することができたり、共有先もユーザ単位やグループ単位などを設定できる。

### 個別の共有設定
1レコードごとに、指定したユーザやグループへのアクセス権を付与することができる。

Apexを使用して実行するか、標準ページレイアウトの「共有」ボタンから実行できる（※Winter'19時点では、「共有」ボタンはClassic表示でのみ対応）。

Apexでの実行方法は [こちら](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm) を参照。 `****__Share` オブジェクトを insert すればよい。

# まとめ
「レコードが参照できるかどうか？」を図にするとこう:

![共有設定.png](https://qiita-image-store.s3.amazonaws.com/0/95358/33532622-b760-77e6-e274-477397118c69.png)

項目レベルセキュリティは、上記の図とは無関係に「項目への参照権限があれば見られる、なければ見られない」。

# 参考
Trailhead データセキュリティ https://trailhead.salesforce.com/ja/content/learn/modules/data_security

# 最後に
間違いなどあればご指摘願います！ :pray: