sf-permissions について
sf-permissionsは、Salesforceの権限管理とアクセス監査を行うスキルです。権限セットの設定、ユーザーアクセスの確認、権限エラーの調査を行う担当者向けに、グループ、項目レベルセキュリティ、共有、クエリ、デプロイ手順を扱います。
主な機能
- 01権限セットとグループのメタデータ生成
- 02ユーザーとオブジェクトのアクセス監査
- 03項目レベルセキュリティの確認
- 04権限やレコードアクセスのエラー診断
- 05カスタム権限とミューティング権限の管理
- 06デプロイと割り当てのコマンド提示
活用シーン
- 01新機能に最小権限のアクセスを設定
- 02レコードを編集できない問題の調査
- 03オブジェクトやApexクラスへのアクセス監査
- 04Profileから権限セットへの設定移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ clientell-ai/ salesforce-skills --skill sf-permissionsインストール後、Claude Code で/sf-permissionsを入力して読み込まれたか確認します。
同梱ファイルreferences/permissions-reference.md
詳細
Salesforce 権限管理とアクセス監査
あなたは Salesforce の権限スペシャリストです。権限セットの管理、アクセスの監査、権限エラーの診断、最小権限のセキュリティの徹底を行います。
1. 権限モデルの概要
| レイヤー | 制御対象 | 適用範囲 |
|---|---|---|
| プロファイル | ログイン時間、IP 範囲、ページレイアウト、レコードタイプ、デフォルトアプリ | ユーザーごとに 1 つ(必須) |
| 権限セット | オブジェクトの CRUD、FLS、Apex クラス、VF ページ、タブ、カスタム権限 | ユーザーごとに複数(追加型) |
| 権限セットグループ | 権限セットのバンドル + オプションのミュート | ユーザーごとに複数(追加型) |
ベストプラクティス:最小限のプロファイル + 権限セット。 簡素化したプロファイル(例:「Minimum Access - Salesforce」)を割り当て、それ以外の権限は権限セットと権限セットグループを通じて付与します。
プロファイルより権限セットを優先する理由:
- ユーザーが持てるプロファイルは 1 つだけですが、権限セットは複数持てます
- 権限セットは追加型で、組み合わせて使用できます
- プロファイルはソース管理でマージ競合を引き起こします
- 権限セットグループを使うと、例外をミュートしてロールベースのバンドルを作成できます
- Salesforce はプロファイルベースの権限から積極的に移行しています
2. 権限セット XML(SFDX ソース形式)
<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Order Manager</label>
<description>Full CRUD on Order__c, read on Account</description>
<hasActivationRequired>false</hasActivationRequired>
<license>Salesforce</license>
<objectPermissions>
<object>Order__c</object>
<allowCreate>true</allowCreate>
<allowDelete>false</allowDelete>
<allowEdit>true</allowEdit>
<allowRead>true</allowRead>
<modifyAllRecords>false</modifyAllRecords>
<viewAllRecords>true</viewAllRecords>
</objectPermissions>
<fieldPermissions>
<field>Order__c.Amount__c</field>
<editable>true</editable>
<readable>true</readable>
</fieldPermissions>
<tabSettings>
<tab>Order__c</tab>
<visibility>Visible</visibility>
</tabSettings>
<classAccesses>
<apexClass>OrderService</apexClass>
<enabled>true</enabled>
</classAccesses>
<pageAccesses>
<apexPage>OrderEntryPage</apexPage>
<enabled>true</enabled>
</pageAccesses>
<customPermissions>
<name>Bypass_Validation</name>
<enabled>true</enabled>
</customPermissions>
<userPermissions>
<name>RunReports</name>
<enabled>true</enabled>
</userPermissions>
</PermissionSet>
hasActivationRequired:trueの場合、適用するにはセッション内で有効化する必要がありますlicense:指定したライセンスタイプを持つユーザーに割り当てを制限します- オブジェクト権限の階層:編集には読み取りが必要です。削除には編集が必要です。
viewAllRecords/modifyAllRecordsは共有設定を上書きします
3. 権限セットグループ XML
<?xml version="1.0" encoding="UTF-8"?>
<PermissionSetGroup xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Sales Team</label>
<description>All permissions needed by sales reps</description>
<status>Updated</status>
<permissionSets>
<permissionSet>Account_Reader</permissionSet>
<permissionSet>Opportunity_Manager</permissionSet>
<permissionSet>Report_Viewer</permissionSet>
</permissionSets>
<mutingPermissionSet>Sales_Team_Muting</mutingPermissionSet>
</PermissionSetGroup>
ミュート権限セット
ミュート権限セットは、グループから特定の権限を削除します。権限セットグループ内でのみ機能します。
<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Sales Team Muting</label>
<description>Removes delete access granted by Opportunity_Manager</description>
<objectPermissions>
<object>Opportunity</object>
<allowDelete>true</allowDelete>
</objectPermissions>
</PermissionSet>
ミュートによって権限が取り消されるのは、このグループを通じてアクセス権を得たユーザーのみです。直接割り当てには影響しません。
4. プロファイルのメタデータ
プロファイルは、引き続き次の設定に必要です:ログイン時間/IP 制限、ページレイアウトの割り当て、レコードタイプのデフォルト、デフォルトアプリの割り当て。
最小限のプロファイル戦略
<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<custom>true</custom>
<description>Minimal profile - all access via Permission Sets</description>
<userLicense>Salesforce</userLicense>
<loginHours>
<mondayStart>480</mondayStart>
<mondayEnd>1080</mondayEnd>
</loginHours>
<layoutAssignments>
<layout>Account-Account Layout</layout>
</layoutAssignments>
</Profile>
プロファイルにオブジェクト/項目の権限を設定するのは避けてください。権限セットでは実現できない設定に限り、プロファイルを使用します。
5. オブジェクトおよび項目レベルのセキュリティ(CRUD/FLS)
CRUD 権限の階層
Read ─── required for ──→ Edit ─── required for ──→ Delete
│ │
└── viewAllRecords └── modifyAllRecords
(bypasses sharing) (bypasses sharing + ownership)
FLS(項目レベルセキュリティ)
各項目には、読み取り可能と編集可能の 2 つのフラグがあります(編集可能にするには読み取り可能である必要があります)。FLS は UI、レポート、リストビュー、API 全体に適用されます。FLS で非表示になっている項目は、WITH USER_MODE を使用した SOQL では null を返します。
FLS 監査クエリ
-- Field permissions for a permission set
SELECT SobjectType, Field, PermissionsRead, PermissionsEdit
FROM FieldPermissions WHERE Parent.Name = 'Order_Manager'
-- Fields a user can edit (across all permission sets)
SELECT SobjectType, Field, PermissionsRead, PermissionsEdit
FROM FieldPermissions WHERE ParentId IN (
SELECT PermissionSetId FROM PermissionSetAssignment
WHERE AssigneeId = '005xx000001234AAA'
)
-- Who can edit a sensitive field?
SELECT Parent.Label, Parent.IsOwnedByProfile
FROM FieldPermissions
WHERE Field = 'Contact.SSN__c' AND PermissionsEdit = true
6. カスタム権限
カスタム権限は、コードを変更せずに機能へのアクセスを制御するブール値フラグです。
<?xml version="1.0" encoding="UTF-8"?>
<CustomPermission xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Can Export Data</label>
<description>Allows user to export data from custom UI</description>
<isLicensed>false</isLicensed>
</CustomPermission>
Apex(推奨):
if (FeatureManagement.checkPermission('Can_Export_Data')) {
// user has the custom permission
}
LWC:
import hasExportPermission from '@salesforce/customPermission/Can_Export_Data';
Flow:Decision 要素で $Permission.Can_Export_Data を使用します(true/false を返します)。
7. アクセス監査
PermissionSetAssignment クエリ
-- All users assigned a permission set
SELECT Assignee.Name, Assignee.Username, Assignee.IsActive
FROM PermissionSetAssignment WHERE PermissionSet.Name = 'Order_Manager'
-- All permission sets for a user (excluding profile-based)
SELECT PermissionSet.Label, PermissionSet.Name, PermissionSetGroupId
FROM PermissionSetAssignment
WHERE AssigneeId = '005xx000001234AAA'
AND PermissionSet.IsOwnedByProfile = false
ObjectPermissions クエリ
-- Who has Delete on an object?
SELECT Parent.Label, Parent.IsOwnedByProfile,
PermissionsDelete, PermissionsViewAllRecords, PermissionsModifyAllRecords
FROM ObjectPermissions
WHERE SobjectType = 'Account' AND PermissionsDelete = true
-- Over-privileged check: ModifyAll on any object
SELECT Parent.Label, SobjectType FROM ObjectPermissions
WHERE PermissionsModifyAllRecords = true AND Parent.IsOwnedByProfile = false
SetupEntityAccess(Apex/VF/Connected App)
-- Who has access to an Apex class?
SELECT Parent.Label FROM SetupEntityAccess
WHERE SetupEntityType = 'ApexClass'
AND SetupEntityId IN (SELECT Id FROM ApexClass WHERE Name = 'OrderService')
-- Connected App access
SELECT Parent.Label FROM SetupEntityAccess
WHERE SetupEntityType = 'ConnectedApplication'
AND SetupEntityId IN (SELECT Id FROM ConnectedApplication WHERE Name = 'DataLoader')
権限セットグループのメンバーシップ
-- Permission sets in a group
SELECT PermissionSetGroup.MasterLabel, PermissionSet.Label
FROM PermissionSetGroupComponent
WHERE PermissionSetGroup.MasterLabel = 'Sales Team'
-- Groups containing a permission set
SELECT PermissionSetGroup.MasterLabel FROM PermissionSetGroupComponent
WHERE PermissionSet.Name = 'Opportunity_Manager'
8. 権限のトラブルシューティング
INSUFFICIENT_ACCESS_OR_READONLY
ユーザーにオブジェクトまたはレコードの編集権限がありません。オブジェクトレベルの編集権限、共有アクセス、レコードの所有権、ロール階層、レコードロック(承認プロセス)を確認してください。
SELECT Parent.Label FROM ObjectPermissions
WHERE SobjectType = 'TargetObject__c' AND PermissionsEdit = true
AND ParentId IN (
SELECT PermissionSetId FROM PermissionSetAssignment WHERE AssigneeId = :userId
)
INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY
ユーザーに関連レコードへのアクセス権がありません。よくある原因は、親レコードの読み取り権限がない状態で子レコードを挿入すること、ユーザーが参照できないレコードにルックアップを変更すること、トリガー/フローが関連レコードを更新することです。
「Insufficient Privileges」エラー
次のいずれかを意味する一般的なエラーです:Apex クラスへのアクセス権がない、VF ページへのアクセス権がない、Lightning コンポーネントへのアクセス権がない、タブが非表示、Connected App へのアクセス権がない、またはセッションベースの権限セットが有効化されていない。
# Quick CLI diagnosis
sf data query -q "SELECT PermissionSet.Label, PermissionSet.Name \
FROM PermissionSetAssignment \
WHERE Assignee.Username = '[email protected]' \
AND PermissionSet.IsOwnedByProfile = false" --target-org myOrg
9. 共有と権限
権限(CRUD/FLS)と共有は、互いに独立したレイヤーです。
| レイヤー | 確認する内容 | 範囲 |
|---|---|---|
| CRUD | ユーザーはこのオブジェクト種別を作成/参照/編集/削除できますか? | オブジェクト全体 |
| FLS | ユーザーはこの特定の項目を参照/編集できますか? | 項目単位 |
| 共有 | ユーザーがアクセスできる特定のレコードはどれですか? | レコード単位 |
ユーザーには、適切なCRUD/FLS権限と共有アクセスの両方が必要です。
OWD 設定
| 設定 | 効果 |
|---|---|
| 非公開 | 所有者と上位のロール階層のみ |
| 公開読み取り専用 | すべてのユーザーが参照でき、編集できるのは所有者のみ |
| 公開読み取り/書き込み | すべてのユーザーが参照および編集可能 |
| 親による制御 | 親レコードによって決定されます(主従関係) |
レコードアクセスの判定順序
1. Record owner? → Full access
2. Above owner in role hierarchy? → Access per OWD
3. Sharing rules? → Read or Read/Write
4. Apex managed sharing? → Read or Read/Write
5. View All / Modify All on object? → Bypasses sharing
6. View All Data / Modify All Data? → Full access
主な違い
viewAllRecords/modifyAllRecordsは、そのオブジェクトの共有設定をバイパスします- Apex の
with sharingは共有を適用しますが、CRUD/FLS は適用しません - SOQL の
WITH USER_MODEは、共有とCRUD/FLSの両方を適用します
10. 注意点
- 権限セットグループの再計算は非同期です — 変更の反映に数分かかることがあります。
PermissionSetGroup.StatusがUpdatedかOutdatedかを確認してください。 - プロファイルはマージ競合の原因になります — プロファイルの XML ファイルは非常に大きく、予測不能な順序変更が発生します。権限セットを優先してください。
- FLSはデフォルトではAPIアクセスを制限しません — Apex はシステムモードで実行されます。
WITH USER_MODEまたはSecurity.stripInaccessible()を使用してください。 - カスタム権限はキャッシュされます — 割り当ての変更が反映されるまで、ユーザーの再認証が必要な場合があります。
- 権限ミュートセットはグループ内でのみ機能します — ユーザーに直接割り当てても効果はありません。
- 権限セットライセンス — 特定のライセンスが必要なものがあります。ライセンスを持たないユーザーへの割り当ては、通知なしに失敗する場合があります。
- セッションベースの権限セット —
hasActivationRequired=trueの場合、Flow またはSessionPermSetActivationによる有効化が必要です。自動では有効化されません。 viewAllRecordsは項目へのアクセス権を付与しません — ユーザーはレコードを参照できますが、FLSで制限された項目は参照できません(FLSが適用される場合)。- IsOwnedByProfile — すべてのプロファイルには非表示の権限セットがあります。クエリでは
PermissionSet.IsOwnedByProfile = falseで絞り込んでください。 - 割り当て上限 — グループ経由のものも含め、ユーザーごとに最大1,000件の権限セットを割り当てられます。
11. ワークフロー
新機能の権限設定
- 必要なアクセスを特定する:オブジェクト、項目、Apex クラス、VF ページ、タブ、カスタム権限を一覧にします。
- 権限セットを作成する:最小権限のアクセス権を設定した
.permissionset-meta.xmlを生成します。 - カスタム権限を作成する(必要な場合):機能フラグ用の
.customPermission-meta.xmlを生成します。 - 権限セットグループに追加する(該当する場合):
.permissionsetgroup-meta.xmlを更新します。 - 権限ミュートセットを作成する(必要な場合):グループが一部のユーザーに過剰な権限を付与する場合に限ります。
- デプロイする:
sf project deploy start -d force-app/main/default/permissionsets \ -d force-app/main/default/permissionsetgroups \ -d force-app/main/default/customPermissions --target-org myOrg - 割り当てる:
sf org assign permset --name Order_Manager --target-org myOrg sf org assign permsetgroup --name Sales_Team --target-org myOrg - 監査する:
sf data query -q "SELECT Assignee.Name, PermissionSet.Label \ FROM PermissionSetAssignment \ WHERE PermissionSet.Name = 'Order_Manager'" --target-org myOrg
プロファイルから権限セットへの移行
- プロファイル上のデフォルト以外の権限をすべてクエリします
- 各機能領域に対応する権限セットを作成します
- プロファイルのロールに対応する権限セットグループを作成します
- 影響を受けるユーザーにグループを割り当てます
- プロファイルから権限を削除します(レイアウト、レコードタイプ、ログイン時間のみを残します)
- セクション7の監査クエリで検証します