継承されたアクセスをクリーンする方法

この記事では、Microsoft Dataverse でテーブルのカスケード構成が変更されたときに、レコードの継承されたアクセスを削除する方法について説明します。

現象

[再親] または [共有] アクションのテーブルリレーションシップの連鎖動作[カスケードなし] に変更された後も、削除する必要がある関連レコードに引き続きアクセスできます。

ユーザーは、レコードに予期しないアクセス権があることを報告する場合があります。 関連レコードへのアクセスを確認するには、アクセスの 確認 機能または RetrieveAccessOrigin メッセージの 2 つの方法があります。

アクセスの確認機能を使用する

レコードにアクセスできるユーザーをチェックするには、モデル駆動型アプリの [アクセスの確認] 機能を使用します。 管理者は、この機能を使用して、個々のユーザーまたはレコードにアクセスできるすべてのユーザーをチェックできます。

アクセス チェッカーを使用すると、ユーザーがアクセス権を持つ理由の一覧が表示されます。 これらの理由の一部は、関連レコードへのアクセスが原因で共有が許可されたことを示しています。 以下に例を示します。

  • 関連レコードにアクセスできるため、レコードが共有されました。
  • レコードは、チームが関連レコードにアクセスできるため、自分がメンバーであるチームと共有されました。

RetrieveAccessOrigin メッセージを使用する

開発者は、メッセージを RetrieveAccessOrigin 使用して、レコードにアクセスできるユーザーを検出できます。 このメッセージは、ユーザーがアクセス権を持つ理由を説明する文を返します。 次のいずれかの結果は、関連レコードの共有が原因でアクセス権が付与されたことを示しています。

PrincipalId is owner of a parent entity of object (<record ID>)
PrincipalId is member of team (<team ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId is member of organization (<organization ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId has access to (<parent record ID>) through hierarchy security. (<parent record ID>) is owner of a parent entity of object (<record ID>)

詳細については、「 ユーザーがコードを使用してアクセス権を持つ理由を特定する」を参照してください。

原因

テーブルリレーションシップのカスケード動作が変更されると、Dataverse は非同期ジョブを開始して、以前に付与されたアクセス権を削除します。 ただし、このジョブが失敗し、ユーザーがアクセスを保持する可能性があります。

解決方法

この問題を解決するための最初の手順は、システム ジョブを再作成してアクセスを削除することです。 ジョブが失敗した場合、開発者はメッセージを ResetInheritedAccess 使用して、指定したレコードのセットに変更を適用できます。

システム ジョブを再作成してアクセスを削除する

開発者は、メッセージを CreateAsyncJobToRevokeInheritedAccess 使用して、非同期ジョブをもう一度作成できます。

Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest クラスを使用します。

/// <summary>
/// Creates and executes an asynchronous cleanup job to revoke inherited access granted through cascading inheritance.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="relationshipSchemaName">The schema name of the entity relationship.</param>
public static void CreateAsyncJobToRevokeInheritedAccessExample(IOrganizationService service, string relationshipSchemaName)
{
    var request = new Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest()
    {
        RelationshipSchema = relationshipSchemaName
    };

    service.Execute(request);
}

SDK for .NET でのメッセージの使用の詳細については、こちらをご覧ください

アクションは CreateAsyncJobToRevokeInheritedAccess 、 という名前 RevokeInheritedAccessの新しい非同期ジョブを作成します。 このジョブの成功を監視できます。 詳細については、「 システム ジョブの監視 」または 「コードを使用したシステム ジョブの管理」を参照してください。

継承されたアクセスをリセットする

システム ジョブを再作成してアクセスを削除できない場合、システム管理者またはシステム カスタマイザー権限を持つ開発者は、メッセージをResetInheritedAccess使用して、一致するレコードのサブセットをターゲットにすることができます。 このメッセージを複数回使用して、すべてのレコードへのアクセスを削除する必要がある場合があります。

/// <summary>
/// Resets the inherited access for the matching records.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="fetchXml">The fetchxml query.</param>
public static void OutputResetInheritedAccess(IOrganizationService service, string fetchXml)
{
    var parameters = new ParameterCollection()
    {
        { "FetchXml", fetchXml}
    };

    var request = new OrganizationRequest()
    {
        RequestName = "ResetInheritedAccess",
        Parameters = parameters
    };

    var response = service.Execute(request);

    Console.WriteLine(response.Results["ResetInheritedAccessResponse"]);
}

SDK for .NET でのメッセージの使用の詳細については、こちらをご覧ください

一致するレコードが多くない場合、メッセージは ResetInheritedAccess 同期的に実行しようとします。 その後、値は ResetInheritedAccessResponseExecutionMode : Sync終わります。 一致するレコードが多数ある場合、操作に時間がかかり、値は で ExecutionMode : Async終わります。 という名前 Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID> のシステム ジョブが作成され、そのジョブの成功を監視できます。 詳細については、「 システム ジョブの監視 」または 「コードを使用したシステム ジョブの管理」を参照してください。

メッセージには ResetInheritedAccess 、レコードを識別するために FetchXml クエリが必要です。 このクエリは、次の要件を満たす必要があります。

  • (POA) テーブルを principalobjectaccess使用します。
  • 列のみを principalobjectaccessid 返します。
  • 要素を link-entity 含めてはいけません。 別のテーブルに結合を追加することはできません。
  • テーブルの列に対してのみフィルター処理します principalobjectaccess

このテーブルは、 principalobjectaccess エンティティ型として Web API で使用できます。 POA テーブルではあらゆる種類の直接データ変更操作がサポートされていないため、 Dataverse テーブル/エンティティ参照 には含まれません。 FetchXml クエリを作成するには、このテーブルの列を把握する必要があります。

POA テーブル列

これらの列のみを使用して FetchXml クエリを作成する必要があります。

論理名 説明
accessrightsmask 整数 プリンシパルが直接持つアクセス権の AccessRights 列挙 メンバー値を結合して格納します。
changedon DateTime プリンシパルのレコードへのアクセスが変更された最後の日付。
inheritedaccessrightsmask 整数 継承のために適用されるアクセス権の AccessRights 列挙 メンバー値を組み合わせて格納します。
objectid 一意識別子 プリンシパルがアクセスできるレコードの ID。
objecttypecode 整数 テーブルに対応する EntityMetadata.ObjectTypeCode 値。 この値は、異なる環境で必ずしも同じとは限りません。 カスタム テーブルの場合、テーブルが作成された順序に基づいて割り当てられます。 この値を取得するには、テーブルのメタデータを表示する必要がある場合があります。 これを見つけるためのコミュニティ ツールがいくつかあります。 Microsoft のソリューションを次に示します。 環境内のテーブル定義を参照します
principalid 一意識別子 アクセス権を持つユーザーまたはチームの ID。
principalobjectaccessid 一意識別子 POA テーブルの主キー。
principaltypecode 整数 プリンシパルの型コード。 SystemUser = 8、 Team = 9。

次の AccessRights 列挙型 メンバー値は、 accessrightsmask 列と inheritedaccessrightsmask 列に適用されます。

[アクセスの種類] 説明
None 0 アクセスなし。
Read 1 レコードを読み取る権限。
Write 2 レコードを更新する権限。
Append 4 指定したレコードを別のレコードに追加する権限。
AppendTo 16 指定したレコードに別のレコードを追加する権限。
Create 32 レコードを作成する権限。
Delete 65,536 レコードを削除する権限。
Share 262,144 レコードを共有する権限。
Assign 524,288 指定したレコードを別のユーザーまたはチームに割り当てる権限。

値は一般的に 135,069,719 であることがわかります inheritedaccessrightsmask 。 この値には、 を除く Createすべてのアクセスの種類が含まれます。これは、これらの権限が既に作成されているレコードにのみ適用されるため、必要ありません。

FetchXml の例

このセクションでは、メッセージで ResetInheritedAccess 使用できる FetchXml クエリの例をいくつか示します。 詳細については、「 FetchXML を使用してクエリを作成する」を参照してください。

特定のアカウントの特定のユーザーに付与された継承されたアクセスをリセットする
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
            <condition attribute="objectid" operator="eq" value="B52B7A48-EAFB-ED11-884B-00224809B6C7" />
        </filter>
    </entity>
</fetch>
指定したオブジェクト型のすべての子行に対して継承されたアクセス権をリセットする
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="objecttypecode" operator="eq" value="10042" />
        </filter>
    </entity>
</fetch>
すべてのオブジェクトの種類について、指定したユーザーに付与された継承されたアクセスをリセットする
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
        </filter>
    </entity>
</fetch>