Salesforce の項目レベルセキュリティをマスターする:管理者向け完全ガイド

概要とビジネスシーン

Field-Level Security(項目レベルセキュリティ、FLS)は、Salesforce が提供する堅牢なセキュリティモデルの重要な要素です。これは、特定のユーザーが Salesforce オブジェクト内の個々の項目(フィールド)を参照または編集できるかどうかを制御し、データプライバシーとコンプライアンスを確保します。

実際のビジネスシーン

シーンA - 金融業界:ある金融機関では、顧客の個人信用情報(例: 銀行口座番号、信用スコア)をSalesforceで管理しています。これらの情報は極めて機密性が高く、GDPRやCCPAなどの規制により厳格な保護が求められます。すべての営業担当者がこれらの情報にアクセスできる必要はありません。

  • ビジネス課題:個人信用情報の不正アクセスや漏洩リスクの管理。
  • ソリューション:FLS を利用して、一般の営業担当者にはこれらの信用情報を非表示にし、特定の上級マネージャーやコンプライアンス担当者のみが参照・編集できるように設定します。
  • 定量的効果:個人情報漏洩のリスクを大幅に低減し、コンプライアンス違反による罰金や顧客からの信頼喪失を防ぎます。データ漏洩インシデントのリスクを年間20%削減しました。

シーンB - 医療業界:病院では、患者の診断記録や治療履歴などの機密性の高い健康情報(Protected Health Information, PHI)をSalesforceに保存しています。HIPAAなどの規制により厳格なアクセス制御が義務付けられています。

  • ビジネス課題:患者データのプライバシー保護と医療情報規制(HIPAA)への準拠。
  • ソリューション:受付担当者には患者の名前や連絡先などの基本情報のみを表示し、診断情報や治療計画は非表示にします。医師や特定の医療スタッフのみがこれらの詳細な医療情報にアクセスできるように FLS を設定します。
  • 定量的効果:患者データのプライバシーを保護し、HIPAA規制への準拠を確保します。監査対応の工数を年間15%削減しました。

シーンC - 製造業界:製造業の営業部門では、営業パイプラインにおける特定の取引(Opportunity)に、戦略的な製品開発情報や将来の価格戦略など、競合他社に漏洩してはならない機密項目が含まれることがあります。

  • ビジネス課題:企業秘密の漏洩防止と市場競争力の維持。
  • ソリューション:特定の製品開発情報や戦略的価格設定の項目に対し、一般の営業担当者には参照・編集権限を与えず、営業マネージャー以上の役職者のみにアクセスを許可する FLS を適用します。
  • 定量的効果:企業秘密の保護を強化し、市場競争上の優位性を維持します。機密情報の意図しない共有を年間25%防止しました。

技術原理とアーキテクチャ

FLS は、Salesforce のセキュリティモデルの重要なレイヤーであり、オブジェクトレベルセキュリティ(ユーザーがオブジェクト自体にアクセスできるか)の下に位置します。ユーザーが特定のオブジェクトにアクセスできる場合でも、そのオブジェクト内の個々の項目に対するアクセス権は FLS によって制御されます。これはプロファイル (Profile) または権限セット (Permission Set) に紐付けられ、ユーザーがデータにアクセスしようとした際にリアルタイムで評価されます。

主要コンポーネントと依存関係

  • プロファイル (Profile):ユーザーインターフェース (UI) や API を通じたユーザーの項目アクセス権限を定義します。Salesforce 管理者が各標準オブジェクトおよびカスタムオブジェクトの項目ごとに「参照可能 (Visible)」と「参照・編集可能 (Read-Only)」を設定できます。
  • 権限セット (Permission Set):プロファイルを補完し、特定のユーザーまたはユーザーグループに追加の権限(項目アクセス権を含む)を付与するためのツールです。プロファイルで設定された権限を「広げる」ことはできますが、「狭める」ことはできません。
  • オブジェクト (Object):データが格納される基本的な構造です。
  • 項目 (Field):オブジェクト内の個々の属性です。

データフロー

ステップ 説明 適用セキュリティレイヤー
1. ユーザー認証 ユーザーが Salesforce にログインします。 認証
2. オブジェクトアクセス評価 ユーザーが特定のオブジェクトへのアクセス権を持つか評価されます。 オブジェクトレベルセキュリティ (プロファイル/権限セット)
3. 項目アクセス評価 ユーザーがオブジェクト内の特定の項目を参照・編集する権限を持つか評価されます。 項目レベルセキュリティ (プロファイル/権限セット)
4. レコードアクセス評価 ユーザーが特定のレコード自体へのアクセス権を持つか評価されます。 レコードレベルセキュリティ (組織の共有設定/共有ルール/ロール階層など)
5. データ表示/操作 すべてのセキュリティチェックを通過した場合に、項目が UI に表示され、操作が可能になります。 -

ソリューション比較と選定

ソリューション 適用シーン セキュリティレベル Governor Limits 複雑度
Field-Level Security (FLS) 特定のユーザーグループに対して、項目単位で参照・編集アクセスを制御。データそのもののセキュリティを確保。法規制遵守が必須な機密データの保護。 高 (データ層) 直接的な制限はなし (ApexからのチェックはSOQL/DML制限に影響する可能性あり) 中 (設定は比較的容易だが、設計は重要)
ページレイアウト (Page Layouts) 異なるユーザーグループに対して、特定の項目を UI 上で「非表示」または「読み取り専用」にする。純粋にUI表示の制御で、データ層のセキュリティ要件がない場合。 低 (UI層) なし 低 (ドラッグ&ドロップで容易に設定)
Apex による手動制御 高度なロジックに基づいて、プログラム的に項目へのアクセスを制御。動的な条件や外部システムとの連携を含む複雑な要件。FLSやページレイアウトでは対応できない特殊なケース。 高 (データ層、ただし実装依存) あり (SOQLクエリ、DML操作、CPU時間など) 高 (開発スキルが必要)
**field-level security を使用すべき場合**:
  • ✅ データプライバシーとコンプライアンスが最優先される場合。法規制(GDPR、HIPAAなど)に基づき、特定の機密情報を厳格に保護する必要がある。
  • ✅ 異なる職務役割を持つユーザーグループ(例:営業担当者、営業マネージャー、サポート担当者)間で、項目へのアクセス権をきめ細かく制御したい場合。
  • ✅ プロファイルや権限セットの標準機能で項目アクセスを管理したい場合。これにより、宣言的(コード不要)な方法でセキュリティを確保できる。
  • ❌ 不適用シーン:レコードレベルのアクセス制御が必要な場合(組織の共有設定、共有ルール、ロール階層、手動共有を使用すべき)。
  • ❌ 不適用シーン:純粋にUI上の項目表示順序や配置のみを変更したい場合(ページレイアウトで十分であり、セキュリティ要件がない場合はFLSは過剰)。

実装例

Salesforce 管理者として、Field-Level Security (FLS) は主にユーザーインターフェース (UI) を介して設定します。しかし、Salesforce プロフェッショナルとしては、Apex コードから FLS をプログラム的に確認する方法も理解しておくことが重要です。これにより、カスタムコードがFLSを尊重し、セキュリティホールを生み出さないようにできます。 以下のコード例は、特定の項目に現在のユーザーがアクセス可能かどうかを Apex で確認する方法を示します。これは、データの表示や更新を行う前に、セキュリティチェックを明示的に実施するためのベストプラクティスです。
public class FieldLevelSecurityChecker {

    /**
     * @description 現在のユーザーが指定されたオブジェクトの特定の項目を参照できるかチェックします。
     * @param objectName API参照名 (例: 'Account')
     * @param fieldName API参照名 (例: 'Phone')
     * @return ユーザーが項目を参照できる場合は true、それ以外は false
     */
    public static boolean canReadField(String objectName, String fieldName) {
        // オブジェクトのDescribeSObjectResult(SObject記述結果)を取得
        Schema.SObjectDescribeResult objectDescribe = Schema.getGlobalDescribe().get(objectName).getDescribe();
        
        // 項目のSObjectFieldトークンを取得
        Schema.SObjectField fieldToken = objectDescribe.fields.getMap().get(fieldName);
        
        if (fieldToken != null) {
            // 項目のDescribeFieldResult(項目記述結果)を取得
            Schema.DescribeFieldResult fieldDescribe = fieldToken.getDescribe();
            // isAccessible() メソッドで参照権限をチェック
            return fieldDescribe.isAccessible();
        }
        return false;
    }

    /**
     * @description 現在のユーザーが指定されたオブジェクトの特定の項目を編集できるかチェックします。
     * @param objectName API参照名 (例: 'Account')
     * @param fieldName API参照名 (例: 'Phone')
     * @return ユーザーが項目を編集できる場合は true、それ以外は false
     */
    public static boolean canEditField(String objectName, String fieldName) {
        // オブジェクトのDescribeSObjectResultを取得
        Schema.SObjectDescribeResult objectDescribe = Schema.getGlobalDescribe().get(objectName).getDescribe();
        // 項目のSObjectFieldトークンを取得
        Schema.SObjectField fieldToken = objectDescribe.fields.getMap().get(fieldName);
        
        if (fieldToken != null) {
            // 項目のDescribeFieldResultを取得
            Schema.DescribeFieldResult fieldDescribe = fieldToken.getDescribe();
            // isUpdateable() メソッドで編集権限をチェック
            return fieldDescribe.isUpdateable();
        }
        return false;
    }

    /**
     * @description FLS チェックのデモンストレーション (匿名実行またはテストクラスから呼び出し可能)
     */
    public static void demonstrateFLSCheck() {
        String objName = 'Account';
        String field1 = 'Name';
        String field2 = 'AnnualRevenue'; // 機密性の高い項目を想定
        String field3 = 'BillingCity';

        System.debug('User can read ' + objName + '.' + field1 + ': ' + canReadField(objName, field1));
        System.debug('User can edit ' + objName + '.' + field1 + ': ' + canEditField(objName, field1));

        System.debug('User can read ' + objName + '.' + field2 + ': ' + canReadField(objName, field2));
        System.debug('User can edit ' + objName + '.' + field2 + ': ' + canEditField(objName, field2));

        System.debug('User can read ' + objName + '.' + field3 + ': ' + canReadField(objName, field3));
        System.debug('User can edit ' + objName + '.' + field3 + ': ' + canEditField(objName, field3));
    }
}

実装ロジックの解析

  1. Schema.getGlobalDescribe().get(objectName).getDescribe() を使用して、指定されたオブジェクトのメタデータ(DescribeSObjectResult)を取得します。これにより、オブジェクトの項目情報にアクセスできます。
  2. objectDescribe.fields.getMap().get(fieldName) を使用して、特定の項目のトークン(SObjectField)を取得します。
  3. fieldToken.getDescribe() を呼び出して、項目の詳細なメタデータ(DescribeFieldResult)を取得します。
  4. fieldDescribe.isAccessible() は、現在のユーザーがその項目を参照する権限があるかどうかを返します。
  5. fieldDescribe.isUpdateable() は、現在のユーザーがその項目を編集する権限があるかどうかを返します。

これらのメソッドは、プロファイルや割り当てられた権限セットの FLS 設定を自動的に評価します。

注意事項とベストプラクティス

  • 権限要件
    • FLS 設定を変更するには、「プロファイルおよび権限セットの管理」権限が必要です。通常はシステム管理者 (System Administrator) プロファイルに含まれます。
    • カスタムプロファイルや権限セットを管理するユーザーにも、これらの権限が付与されている必要があります。
  • Governor Limits:FLS 自体に直接的な Governor Limits はありません。しかし、Apex で isAccessible()isUpdateable() を大量に呼び出すことは、CPU 時間の消費につながる可能性があります。また、FLS を尊重しない SOQL クエリや DML 操作は、WITH SECURITY_ENFORCED 句を使用しない限り、ガバナ制限とは別にセキュリティ上のリスクとなります。
  • エラー処理:Apex コード内で FLS を考慮せずにデータ操作を行うと、System.NoAccessException (「無効なクロス参照」または「項目にアクセスできません」などのメッセージ) が発生することがあります。これを防ぐためには、Apex でのデータアクセス時に WITH SECURITY_ENFORCED 句の使用、または isAccessible() / isUpdateable() による明示的な権限チェックが推奨されます。
  • パフォーマンス最適化
    1. 最小特権の原則 (Principle of Least Privilege):ユーザーには、その職務を遂行するために必要な最小限のアクセス権限のみを与えるようにします。過剰な権限はセキュリティリスクを高め、管理を複雑にします。
    2. 権限セットの活用:プロファイルを少なく保ち、特定の追加権限(FLSを含む)は権限セットで管理します。これにより、変更管理が容易になり、プロファイルの数を爆発的に増やすことを避けることができます。
    3. SOQL の WITH SECURITY_ENFORCED:Apex で SOQL クエリを記述する際には、可能な限り WITH SECURITY_ENFORCED 句を使用してください。これにより、クエリが実行される前に自動的にオブジェクトレベルおよび項目レベルのセキュリティが適用され、ガバナ制限の範囲内で安全にデータアクセスが保証されます。例えば、SELECT Id, Name, AnnualRevenue FROM Account WITH SECURITY_ENFORCED

よくある質問 FAQ

Q1:Field-Level Security (FLS) とページレイアウトの「参照のみ/非表示」設定はどのように違うのですか?

A1:FLS はデータ層のセキュリティであり、ユーザーが API、Apex、レポートなどあらゆる方法で項目にアクセスできるかを制御します。ページレイアウトは UI 層の制御であり、UI 上で項目が見えるか見えないかを制御するだけです。FLS でアクセス権がない場合、ページレイアウトで「表示」されていても項目は表示されません。

Q2:Apex で FLS を考慮せずに SOQL クエリを発行するとどうなりますか?

A2:デフォルトでは、Apex コードは「システムコンテキスト (System Context)」で実行されるため、FLS をバイパスしてすべての項目にアクセスできてしまいます。これはセキュリティホールとなる可能性があります。WITH SECURITY_ENFORCED 句を使用するか、isAccessible() などのメソッドで明示的にチェックする必要があります。

Q3:FLS の設定変更はどのようにデプロイまたは管理するのがベストですか?

A3:小規模な変更やテスト環境では UI からの手動設定が便利ですが、大規模な組織や本番環境へのデプロイでは、メタデータ API、Salesforce CLI、または変更セット(Change Sets)を使用して、プロファイルや権限セットの XML ファイルとして変更を管理・デプロイすることが推奨されます。これにより、変更の追跡とバージョン管理が可能になります。

まとめと参考資料

Field-Level Security(FLS)は、Salesforce における堅牢なデータセキュリティモデルの礎石です。個々の項目レベルでアクセスを制御することで、機密情報の保護、規制コンプライアンスの維持、およびユーザーの職務に応じた適切な情報アクセスを保証します。管理者は、プロファイルと権限セットを効果的に活用し、最小特権の原則に従うことで、安全で管理しやすい Salesforce 環境を構築できます。Apex 開発者は、isAccessible(), isUpdateable(), そして WITH SECURITY_ENFORCED 句を用いて、コードが FLS を尊重するように徹底する必要があります。

公式リソース

コメント