

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon Verified Permissions を使用した PDP の実装
<a name="avp"></a>

Amazon Verified Permissions は、ポリシー決定ポイント (PDP) を実装するために使用できる、スケーラブルできめ細かなアクセス許可の管理および認可サービスです。ポリシーエンジンとして、アプリケーションがユーザーアクションをリアルタイムで検証し、過度に特権的または無効なアクセス許可を強調表示するのに役立ちます。これは、認可を外部化し、ポリシーの管理と管理を一元化することで、開発者がより安全なアプリケーションを迅速に構築するのに役立ちます。認可ロジックをアプリケーションロジックから分離することで、Verified Permissions はポリシーのデカップリングをサポートします。

Verified Permissions を使用して PDP を実装し、アプリケーション内で最小特権と継続的な検証を実装することで、開発者はアプリケーションへのアクセスを[ゼロトラスト](https://aws.amazon.com/security/zero-trust/)の原則に合わせることができます。さらに、セキュリティチームと監査チームは、アプリケーション内のどのリソースにアクセスできるかをより適切に分析および監査できます。Verified Permissions は、専用でセキュリティファーストのオープンソースポリシー言語である [Cedar](https://www.cedarpolicy.com/en) を使用して、よりきめ細かなコンテキスト対応アクセスコントロールのために、ロールベースのアクセスコントロール (RBAC) と属性ベースのアクセスコントロール (ABAC) に基づいてポリシーベースのアクセスコントロールを定義します。

Verified Permissions は、Amazon Cognito、Google、Facebook などの複数の ID プロバイダーを使用してマルチテナント認可を有効にする機能など、SaaS アプリケーションにいくつかの便利な機能を提供します。SaaS アプリケーションに特に役立つもう 1 つの Verified Permissions 機能は、テナントごとのカスタムロールのサポートです。顧客関係管理 (CRM) システムを設計する場合、1 つのテナントは、1 つの特定の基準セットに基づいて、販売機会ごとにアクセスの粒度を定義できます。別のテナントに別の定義がある場合があります。Verified Permissions の基盤となるアクセス許可システムは、これらのバリエーションをサポートできるため、SaaS ユースケースの優れた候補となります。Verified Permissions は、すべてのテナントに適用されるポリシーを記述する機能もサポートしているため、ガードレールポリシーを適用して SaaS プロバイダーとしての不正アクセスを防ぐことは簡単です。

![\[Amazon Verified Permissions を使用した PDP の実装\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp.png)


**Verified Permissions を使用する理由**

[Amazon Cognito](https://aws.amazon.com/cognito/) などの ID プロバイダーで Verified Permissions を使用すると、アプリケーション用のより動的なポリシーベースのアクセス管理ソリューションを実現できます。データのセキュリティ、機密性、プライバシーを維持しながら、ユーザーによる情報の共有とコラボレーションを支援するアプリケーションを構築できます。Verified Permissions は、アイデンティティとリソースのロールと属性に基づいてアクセスを強制するきめ細かな認可システムを提供することで、運用コストを削減します。ポリシーモデルを定義し、ポリシーを作成して一元的に保存し、アクセスリクエストをミリ秒単位で評価できます。

Verified Permissions では、Cedar というシンプルで人間が読める宣言言語を使用してアクセス許可を表現できます。Cedar で記述されたポリシーは、各チームのアプリケーションで使用されるプログラミング言語に関係なく、チーム間で共有できます。

**Verified Permissions を使用する際の考慮事項**

Verified Permissions では、プロビジョニングの一環としてポリシーを作成し、自動化できます。アプリケーションロジックの一部として、実行時にポリシーを作成することもできます。ベストプラクティスとして、テナントのオンボーディングとプロビジョニングの一部としてポリシーを作成するときは、継続的インテグレーションと継続的デプロイ (CI/CD) パイプラインを使用してポリシーバージョンを管理、変更、追跡する必要があります。または、アプリケーションはポリシーバージョンを管理、変更、追跡できますが、アプリケーションロジックは本質的にこの機能を実行しません。アプリケーションでこれらの機能をサポートするには、この機能を実装するようにアプリケーションを明示的に設計する必要があります。

認可決定に到達するために他のソースから外部データを提供する必要がある場合は、このデータを取得し、認可リクエストの一部として Verified Permissions に提供する必要があります。このサービスでは、追加のコンテキスト、エンティティ、属性はデフォルトでは取得されません。

# Cedar の概要
<a name="cedar"></a>

Cedar は、柔軟で拡張可能でスケーラブルなポリシーベースのアクセスコントロール言語であり、開発者がアプリケーションのアクセス許可をポリシーとして表現するのに役立ちます。管理者と開発者は、ユーザーがアプリケーションリソースを操作することを許可または禁止するポリシーを定義できます。1 つのリソースに複数のポリシーをアタッチできます。アプリケーションのユーザーがリソースに対してアクションを実行しようとすると、アプリケーションは Cedar ポリシーエンジンに認可をリクエストします。Cedar は該当するポリシーを評価し、 `ALLOW`または `DENY`の決定を返します。Cedar は、任意のタイプのプリンシパルとリソースの認可ルールをサポートし、ロールベースのアクセスコントロール (RBAC) と属性ベースのアクセスコントロール (ABAC) を許可し、自動推論ツールによる分析をサポートします。

Cedar では、ビジネスロジックと認可ロジックを分離できます。アプリケーションのコードからリクエストを行うときは、Cedar の認可エンジンを呼び出して、リクエストが承認されているかどうかを判断します。承認されている場合 (決定は `ALLOW`)、アプリケーションはリクエストされたオペレーションを実行できます。承認されていない場合 (決定は `DENY`)、アプリケーションはエラーメッセージを返す可能性があります。Cedar の主な機能は次のとおりです。
+ **表現性** – Cedar は認可のユースケースをサポートするために特別に設計されており、人間の読みやすさを念頭に置いて開発されました。
+ **パフォーマンス** – Cedar は、迅速な取得のためのインデックス作成ポリシーをサポートし、制限されたレイテンシーで高速でスケーラブルなリアルタイム評価を提供します。
+ **分析** – Cedar は、ポリシーを最適化し、セキュリティモデルを検証できる分析ツールをサポートしています。

詳細については、[Cedar のウェブサイト](https://www.cedarpolicy.com/)を参照してください。

# 例 1: Verified Permissions と Cedar を使用した基本的な ABAC
<a name="avp-basic-abac-examples"></a>

このシナリオ例では、Amazon Verified Permissions を使用して、架空のペイロールマイクロサービス内の情報にアクセスできるユーザーを決定します。このセクションでは、Cedar を使用してアクセスコントロールの決定をレンダリングする方法を示す Cedar コードスニペットについて説明します。これらの例は、Cedar および Verified Permissions が提供する機能を完全に探索することを目的としたものではありません。Cedar の詳細な概要については、[Cedar のドキュメント](https://docs.cedarpolicy.com/)を参照してください。

次の図では、 `viewSalary``GET`メソッドに関連付けられた 2 つの一般的なビジネスルールを適用します。*従業員は自分の給与を表示でき*、*従業員は自分の直属の従業員の給与を表示できます。*Verified Permissions ポリシーを使用して、これらのビジネスルールを適用できます。

![\[PDP を実装するための Amazon Verified Permissions と Cedar を使用した基本的な ABAC 実装の例\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-1.png)


*従業員は自分の給与を表示できます。*

Cedar では、基本的なコンストラクトは、プリンシパル、アクション、またはリソースを表す*エンティティ*です。認可リクエストを行い、Verified Permissions ポリシーを使用して評価を開始するには、*プリンシパル、**アクション*、*リソース、*エンティティ*のリストを指定する必要があります。*
+ プリンシパル (`principal`) は、ログインしているユーザーまたはロールです。
+ アクション (`action`) は、リクエストによって評価されるオペレーションです。
+ リソース (`resource`) は、アクションがアクセスするコンポーネントです。
+ エンティティのリスト (`entityList`) には、リクエストの評価に必要なすべてのエンティティが含まれます。

*従業員が自分の給与を表示できる*ビジネスルールを満たすために、次のような Verified Permissions ポリシーを指定できます。

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner
};
```

このポリシーは、 `Action`が `ALLOW`であり`viewSalary`、リクエスト内のリソースにプリンシパルと等しい属性所有者があるかどうかを に評価します。たとえば、Bob が給与レポートをリクエストしたログインユーザーであり、給与レポートの所有者でもある場合、ポリシーは に評価されます`ALLOW`。

次の認可リクエストが Verified Permissions に送信され、サンプルポリシーによって評価されます。この例では、Bob は`viewSalary`リクエストを行うログインユーザーです。したがって、Bob はエンティティタイプ のプリンシパルです`Employee`。Bob が実行しようとしているアクションは `viewSalary,`で`viewSalary`、表示されるリソースはタイプ `Salary-Bob`です`Salary`。Bob が`Salary-Bob`リソースを表示できるかどうかを評価するには、 タイプを の値 `Bob` (プリンシパル) `Employee` と タイプを持つリソースの所有者属性にリンクするエンティティ構造を指定する必要があります`Salary`。この構造は で指定します。ここで`entityList`、 に関連付けられた属性`Salary`には、タイプ `Employee`と値 `entityIdentifier`を含む を指定する所有者が含まれます`Bob`。Verified Permissions は、認可リクエストで`principal`提供された を、決定を行うために`Salary`リソースに関連付けられている`owner`属性と比較します。

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        }
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {}
      }
    ]
  }
}
```

Verified Permissions への認可リクエストは出力として以下を返します。 属性`decision`は `ALLOW`または です`DENY`。

```
{
    "determiningPolicies": 
        [ 
            {
                "determiningPolicyId": "PAYROLLAPP_POLICYSTOREID" 
            }
        ],
    "decision": "ALLOW",
    "errors": [] 
}
```

この場合、Bob は自分の給与を表示しようとしていたため、Verified Permissions に送信された認可リクエストは に評価されます`ALLOW`。ただし、目的は Verified Permissions を使用して 2 つのビジネスルールを適用することでした。以下を示すビジネスルールも当てはまります。

*従業員は、自分の部下の給与を表示できます。*

このビジネスルールを満たすには、別のポリシーを指定できます。次のポリシーは、アクションが `ALLOW`であり`viewSalary`、リクエストのリソースにプリンシパルと`owner.manager`等しい属性があるかどうかを に評価します。たとえば、Alice が給与レポートをリクエストしたログインユーザーで、Alice がレポートの所有者のマネージャーである場合、ポリシーは に評価されます`ALLOW`。

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager
};
```

次の認可リクエストが Verified Permissions に送信され、サンプルポリシーによって評価されます。この例では、Alice は`viewSalary`リクエストを行うログインユーザーです。したがって、Alice はプリンシパルであり、エンティティはタイプ です`Employee`。Alice が実行しようとしているアクションは で`viewSalary`、`viewSalary`表示されるリソースは の値`Salary`を持つ タイプです`Salary-Bob`。Alice が`Salary-Bob`リソースを表示できるかどうかを評価するには、 型の`Employee`値を `Alice` `manager` 属性にリンクするエンティティ構造を指定する必要があります。このエンティティ構造は、 型の `owner` 属性を の値`Salary`に関連付ける必要があります`Salary-Bob`。この構造を で指定します。ここで`entityList`、 に関連付けられた属性`Salary`には、タイプ `Employee`と値 `entityIdentifier`を含む を指定する所有者が含まれます`Bob`。Verified Permissions はまず `owner` 属性をチェックし、 属性は タイプ`Employee`と値 に評価されます`Bob`。次に、Verified Permissions は、関連付けられた`manager`属性を評価し`Employee`、提供されたプリンシパルと比較して認可の決定を行います。この場合、 `principal `と `resource.owner.manager` 属性は同等`ALLOW`であるため、決定は です。

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Alice"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "None"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Alice"
            }
          }
        },
       "parents": []
      }
    ]
  }
}
```

この例のこれまでのところ、 `viewSalary`メソッドに関連する 2 つのビジネスルールが提供されました。*従業員は自分の給与を表示でき*、*従業員は自分の部下の給与を表示でき*、Verified Permissions は各ビジネスルールの条件を個別に満たすポリシーとして確認できます。単一の Verified Permissions ポリシーを使用して、両方のビジネスルールの条件を満たすこともできます。

*従業員は、自分の給与と、自分の部下の給与を表示できます。*

前の認可リクエストを使用する場合、次のポリシーは、アクション`ALLOW`が `viewSalary`であり、リクエスト内のリソースに `owner.manager`と等しい属性があるか`principal`、 と`owner`等しい属性があるかを に評価します`principal`。

```
permit (
    principal,
    action == PayrollApp::Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager ||
    principal == resource.owner
};
```

たとえば、Alice が給与レポートをリクエストするログインユーザーであり、Alice が所有者のマネージャーまたはレポートの所有者である場合、ポリシーは に評価されます`ALLOW`。

Cedar ポリシーで論理演算子を使用する方法の詳細については、[Cedar ドキュメント](https://docs.cedarpolicy.com/policies/syntax-operators.html)を参照してください。

# 例 2: Verified Permissions と Cedar を使用した基本的な RBAC
<a name="avp-basic-rbac-examples"></a>

この例では、Verified Permissions と Cedar を使用して基本的な RBAC を示します。前述のように、Cedar の基本コンストラクトはエンティティです。開発者は独自のエンティティを定義し、オプションでエンティティ間の関係を作成できます。次の例には、`Users`、、 の 3 種類のエンティティが含まれています`Problems`。 `Students` および は、 タイプのエンティティと見な`Role,`す`Teachers`ことができ`Roles`、それぞれを 0 または のいずれかに関連付ける`User`ことができます`Roles`。

![\[PDP を実装するための Amazon Verified Permissions と Cedar を使用した基本的な RBAC 実装の例\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-2.png)


Cedar では、これらの関係は `Role``Student`を親`User``Bob`として にリンクすることで表現されます。この関連付けは、すべての学生ユーザーを 1 つのグループに論理的にグループ化します。Cedar でのグループ化の詳細については、[Cedar ドキュメント](https://docs.cedarpolicy.com/overview/terminology.html#term-group)を参照してください。

次のポリシーは、タイプ `Students`の論理グループにリンクされている`submitProblem,`すべてのプリンシパル`ALLOW`のアクションの決定を評価します`Role`。

```
permit (
    principal in ElearningApp::Role::"Students",
    action == ElearningApp::Action::"submitProblem",
    resource
);
```

次のポリシーは、タイプ `Teachers`の論理グループにリンクされているすべてのプリンシパルについて`answerProblem`、`ALLOW`アクション `submitProblem`または の決定を評価します`Role`。

```
permit (
    principal in ElearningApp::Role::"Teachers",
    action in [
        ElearningApp::Action::"submitProblem",
        ElearningApp::Action::"answerProblem"
    ],
    resource
);
```

これらのポリシーを使用してリクエストを評価するには、評価エンジンは、認可リクエスト内で参照されるプリンシパルが適切なグループのメンバーであるかどうかを知る必要があります。したがって、アプリケーションは認可リクエストの一部として関連するグループメンバーシップ情報を評価エンジンに渡す必要があります。これは `entities`プロパティを通じて行われます。これにより、認可呼び出しに関連するプリンシパルとリソースの属性とグループのメンバーシップデータを Cedar 評価エンジンに提供できます。次のコードでは、グループメンバーシップは、 `User::"Bob"`を という親として定義することで示されます`Role::"Students"`。

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Bob"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Students"
                } 
            ]
        },
        {
          "identifier": {
            "entityType": "ElearningApp::Problem",
            "entityId": "SomeProblem"
          },
          "attributes": {},
          "parents": []
        }
      ]
  }
}
```

この例では、Bob は`answerProblem`リクエストを行うログインユーザーです。したがって、Bob はプリンシパルであり、エンティティはタイプ です`User`。Bob が実行しようとしているアクションは です`answerProblem`。Bob が`answerProblem`アクションを実行できるかどうかを評価するには、エンティティを の値`User`にリンク`Bob`し、親エンティティを としてリストしてグループメンバーシップを割り当てるエンティティ構造を指定する必要があります`Role::"Students"`。ユーザーグループのエンティティ`Role::"Students"`はアクションを実行することしか許可されないため`submitProblem`、この認可リクエストは に評価されます`DENY`。

一方、 の値を持ち、 グループの一部`User`である タイプが`answerProblem`アクションを実行`Role::"Teachers"` しようとする`Alice`と、ポリシーはグループ内のプリンシパルがすべてのリソース`answerProblem`に対してアクションを実行することを許可するように指示するため`ALLOW`、認可リクエスト`Role::"Teachers"`は に評価されます。次のコードは、 に評価されるこのタイプの 認可リクエストを示しています`ALLOW`。

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Alice"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Teachers"
                } 
            ]
        },
        {
            "identifier": {
                "entityType": "ElearningApp::Problem",
                "entityId": "SomeProblem"
            },
            "attributes": {},
            "parents": []
        }
      ]
  }
}
```

# 例 3: RBAC によるマルチテナントアクセスコントロール
<a name="avp-mt-abac-examples"></a>

前の RBAC の例について詳しく説明するために、SaaS プロバイダーの一般的な要件である SaaS マルチテナンシーを含めるように要件を拡張できます。マルチテナントソリューションでは、リソースアクセスは常に特定のテナントに代わって提供されます。つまり、テナント A のユーザーは、データがシステムに論理的または物理的にコロケーションされている場合でも、テナント B のデータを表示できません。次の例は、複数の [Verified Permissions ポリシーストア](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policy-stores.html)を使用してテナント分離を実装する方法と、ユーザーロールを使用してテナント内のアクセス許可を定義する方法を示しています。

テナントごとのポリシーストアの設計パターンを使用することは、Verified Permissions によるアクセス制御を実装しながら、テナントの分離を維持するためのベストプラクティスです。このシナリオでは、テナント A とテナント B のユーザーリクエストは、`DATAMICROSERVICE_POLICYSTORE_B`それぞれ個別のポリシーストア `DATAMICROSERVICE_POLICYSTORE_A`および に対して検証されます。マルチテナント SaaS アプリケーションの Verified Permissions 設計上の考慮事項の詳細については、[「Verified Permissions マルチテナント設計上の考慮事項](avp-design-considerations.md)」セクションを参照してください。

![\[RBAC、Amazon Verified Permissions、Cedar を使用したマルチテナントアクセスコントロールの例\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-3.png)


次のポリシーは、`DATAMICROSERVICE_POLICYSTORE_A`ポリシーストアにあります。プリンシパルがタイプ `allAccessRole`のグループの一部であることを確認します`Role`。この場合、プリンシパルはテナント A に関連付けられているすべてのリソースに対して `viewData`および `updateData`アクションを実行できます。

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
);
```

次のポリシーは、`DATAMICROSERVICE_POLICYSTORE_B`ポリシーストアにあります。最初のポリシーは、プリンシパルがタイプ の`updateDataRole`グループの一部であることを確認します`Role`。その場合、テナント B に関連付けられているリソースに対して`updateData`アクションを実行するアクセス許可をプリンシパルに付与します。

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
);
```

この 2 番目のポリシーでは、 タイプの`viewDataRole`グループの一部であるプリンシパルに、テナント B に関連付けられているリソースに対して `viewData`アクションを実行することを許可`Role`する必要があります。

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
);
```

テナント A から行われた認可リクエストは、`DATAMICROSERVICE_POLICYSTORE_A`ポリシーストアに送信され、そのストアに属するポリシーによって検証される必要があります。この場合、この例の一部として前述した最初のポリシーによって検証されます。この認可リクエストでは、 の値`User`を持つ タイプのプリンシパル`Alice`が `viewData`アクションの実行をリクエストしています。プリンシパルはタイプ `allAccessRole`のグループに属します`Role`。Alice は`SampleData`リソースに対して `viewData`アクションを実行しようとしています。Alice には `allAccessRole`ロールがあるため、この評価の結果が`ALLOW`決定されます。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

代わりに、 によってテナント B から行われたリクエストを表示すると`User Bob`、次のような承認リクエストが表示されます。リクエストはテナント B から送信されるため、`DATAMICROSERVICE_POLICYSTORE_B`ポリシーストアに送信されます。このリクエストでは、プリンシパルはリソース `updateData`に対してアクションを実行`Bob`したいと考えています`SampleData`。ただし、 `Bob`はそのリソース`updateData`の アクションにアクセスできるグループの一部ではありません。したがって、リクエストは`DENY`決定になります。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_B",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Bob"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Bob"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "viewDataRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

この 3 番目の例では、 はリソース に対して `viewData`アクションを実行`User Alice `しようとします`SampleData`。このリクエストは、プリンシパルがテナント A に`Alice`属しているため、`DATAMICROSERVICE_POLICYSTORE_A`ポリシーストアに送信されます。 `Alice`は `allAccessRole`タイプの グループの一部であり`Role`、 リソースに対して`viewData`アクションを実行することを許可します。そのため、リクエストは`ALLOW`決定になります。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

# 例 4: RBAC と ABAC によるマルチテナントアクセスコントロール
<a name="avp-mt-abac-rbac-examples"></a>

前のセクションの RBAC の例を強化するために、ユーザーに属性を追加して、マルチテナントアクセスコントロールの RBAC-ABAC ハイブリッドアプローチを作成できます。この例では、前の例と同じロールが含まれていますが、ユーザー属性 `account_lockout_flag`とコンテキストパラメータ を追加します`uses_mfa`。この例では、RBAC と ABAC の両方を使用してマルチテナントアクセスコントロールを実装するアプローチも異なり、テナントごとに異なるポリシーストアではなく 1 つの共有ポリシーストアを使用します。

![\[RBAC、ABAC、Amazon Verified Permissions、Cedar を使用したマルチテナントアクセスコントロールの例\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-4.png)


この例は、前の例と同様に、テナント A とテナント B の承認決定を行う必要があるマルチテナント SaaS ソリューションを表します。

ユーザーロック機能を実装するために、この例では、認可リクエストの`User`エンティティプリンシパル`account_lockout_flag`に 属性を追加します。このフラグは、システムへのユーザーアクセスをロックし、ロックアウトされたユーザーに対する`DENY`すべての権限を付与します。`account_lockout_flag` 属性は`User`エンティティに関連付けられ、フラグが複数のセッションにわたってアクティブに取り消`User`されるまで に対して有効です。この例では、 `when`条件を使用して を評価します`account_lockout_flag`。

この例では、リクエストとセッションに関する詳細も追加します。コンテキスト情報は、セッションが多要素認証を使用して認証されたことを指定します。この検証を実装するために、この例では `when`条件を使用して、コンテキストフィールドの一部として `uses_mfa`フラグを評価します。コンテキストを追加するためのベストプラクティスの詳細については、[Cedar](https://docs.cedarpolicy.com/auth/entities-syntax.html) ドキュメントを参照してください。

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

このポリシーは、リソースがリクエスト元のプリンシパルの `Tenant` 属性と同じグループにある場合を除き、リソースへのアクセスを禁止します。テナント分離を維持するためのこのアプローチは、*1 つの共有マルチテナントポリシーストア*アプローチと呼ばれます。マルチテナント SaaS アプリケーションの Verified Permissions 設計上の考慮事項の詳細については、[「Verified Permissions マルチテナント設計上の考慮事項](avp-design-considerations.md)」セクションを参照してください。

このポリシーは、プリンシパルが のメンバーであることも保証`allAccessRole`し、アクションを `viewData`および に制限します`updateData`。さらに、このポリシーは、 `account_lockout_flag`が `false`であり、 のコンテキスト値が に`uses_mfa`評価されることを確認します`true`。

同様に、次のポリシーでは、プリンシパルとリソースの両方が同じテナントに関連付けられていることを確認し、クロステナントアクセスを防止します。このポリシーは、プリンシパルが のメンバーであることも保証`viewDataRole`し、アクションを に制限します`viewData`。さらに、 `account_lockout_flag`が `false`であり、 のコンテキスト値が に`uses_mfa`評価されることを確認します`true`。

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

3 番目のポリシーは、前のポリシーと似ています。このポリシーでは、リソースが で表されるエンティティに対応するグループのメンバーであることが必要です`principal.Tenant`。これにより、プリンシパルとリソースの両方がテナント B に関連付けられ、クロステナントアクセスが防止されます。このポリシーは、プリンシパルが のメンバーであることを保証`updateDataRole`し、アクションを に制限します`updateData`。さらに、このポリシーは、 `account_lockout_flag`が であり、 のコンテキスト値が に`uses_mfa`評価`false`されることを確認します`true`。

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

次の認可リクエストは、このセクションで前述した 3 つのポリシーによって評価されます。この認可リクエストでは、 型のプリンシパル`User`と の値が のプリンシパルは、ロール を使用して`updateData`リクエスト`Alice`を行います`allAccessRole`。 `Alice` には、値が `Tenant`である 属性があります`Tenant::"TenantA"`。実行`Alice`しようとしているアクションは `updateData,`で、適用するリソースのタイプは `SampleData` です`Data`。 `SampleData` は親エンティティ`TenantA`として を持ちます。

ポリシーストアの最初の`<DATAMICROSERVICE_POLICYSTOREID>`ポリシーに従って、 はポリシーの `when`句の条件が満たされていると仮定して、リソースに対して `updateData` アクションを実行`Alice`できます。最初の条件では、 `principal.Tenant` 属性を に評価する必要があります`TenantA`。2 番目の条件では、プリンシパルの 属性を `account_lockout_flag`にする必要があります`false`。最後の条件では、コンテキストを に`uses_mfa`する必要があります`true`。3 つの条件がすべて満たされるため、リクエストは`ALLOW`決定を返します。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "context": {
    "contextMap": {
        "uses_mfa": {
            "boolean": true
        }
    }
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {
            {
                "account_lockout_flag": {
                    "boolean": false
                },
                "Tenant": {
                   "entityIdentifier": {
                        "entityType":"MultitenantApp::Tenant",
                        "entityId":"TenantA"
                   }
                }
            }
        },
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
        },
     {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Tenant",
                "entityId": "TenantA"
            }
        ]
      }
    ]
  }
}
```

# 例 5: Verified Permissions と Cedar を使用した UI フィルタリング
<a name="avp-ui-filtering-examples"></a>

Verified Permissions を使用して、承認されたアクションに基づいて UI 要素の RBAC フィルタリングを実装することもできます。これは、マルチテナント SaaS アプリケーションの場合に、特定のユーザーまたはテナントに関連付けられる可能性のあるコンテキスト依存の UI 要素を持つアプリケーションにとって非常に役立ちます。

次の例では、 `Users`の `Role``viewer`は更新を実行できません。これらのユーザーの場合、UI は更新ボタンをレンダリングしないでください。

![\[Amazon Verified Permissions と Cedar を使用した UI フィルタリングの例\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-5.png)


この例では、単一ページのウェブアプリケーションには 4 つのボタンがあります。表示されるボタンは、現在アプリケーションにログインしている`Role`ユーザーの によって異なります。単一ページのウェブアプリケーションが UI をレンダリングすると、Verified Permissions にクエリを実行して、ユーザーが実行を許可されているアクションを決定し、承認の決定に基づいてボタンを生成します。

次のポリシーでは、値が の タイプ`Role`がユーザーとデータの両方を表示`viewer`できることを指定します。このポリシーの承認`ALLOW`決定には、 `viewData`または `viewUsers`アクションが必要であり、リソースをタイプ `Data`または に関連付ける必要もあります`Users`。`ALLOW` 決定により、UI は `viewDataButton`と の 2 つのボタンをレンダリングできます`viewUsersButton`。

```
permit (
    principal in GuiAPP::Role::"viewer",
    action in [GuiAPP::Action::"viewData", GuiAPP::Action::"viewUsers"],
    resource 
)
when {
   resource in [GuiAPP::Type::"Data", GuiAPP::Type::"Users"]
};
```

次のポリシーでは、値が の 型`Role`がデータのみを表示`viewerDataOnly`できることを指定します。このポリシーの承認`ALLOW`決定には `viewData`アクションが必要であり、 タイプに関連付けるリソースも必要です`Data`。`ALLOW` 決定により、UI はボタン をレンダリングできます`viewDataButton`。

```
permit (
    principal in GuiApp::Role::"viewerDataOnly",
    action in [GuiApp::Action::"viewData"],
    resource in [GuiApp::Type::"Data"] 
);
```

次のポリシーでは、値が の タイプ`Role`がデータとユーザーを編集して表示`admin`できるように指定します。このポリシーの承認`ALLOW`決定には、`updateData`、、`updateUsers``viewData,`または のアクションが必要です。また`viewUsers`、リソースをタイプ `Data`または に関連付ける必要があります`Users`。`ALLOW` 決定により、UI は 、`updateDataButton`、`updateUsersButton`、 `viewDataButton`の 4 つのボタンをすべてレンダリングできます`viewUsersButton`。

```
permit (
    principal in GuiApp::Role::"admin",
    action in [
        GuiApp::Action::"updateData",
        GuiApp::Action::"updateUsers",
        GuiApp::Action::"viewData", 
        GuiApp::Action::"viewUsers"
       ],
    resource 
)
when {
   resource in [GuiApp::Type::"Data", GuiApp::Type::"Users"]
};
```