---
title: "Amazon Verified Permissionsとは？Cedarの書き方と料金・API Gateway連携の手順"
url: "https://www.issoh.co.jp/tech/details/4766/"
published: 2025-01-09
updated: 2026-10-20
categories: ["AWS"]
publisher: "株式会社一創"
---

# Amazon Verified Permissionsとは？Cedarの書き方と料金・API Gateway連携の手順

Amazon Verified Permissions（AVP）は、アプリケーションの「このユーザーはこの操作をしてよいか」という認可判定を、コードの外に置いたCedarポリシーで行うAWSのマネージドサービスです。AWSリソースへのアクセスを制御するIAMとは対象が違い、自社アプリの画面やAPIの権限を扱います。この記事では、Cedarポリシーの書き方と評価ルール、4つの認可APIの使い分け、料金の計算方法、API GatewayとCognitoでの導入手順、クォータを、2026年10月時点の公式ドキュメントとCedar CLI 4.13.0での実行結果をもとに整理します。

## まとめ：Amazon Verified Permissionsの要点

- AVPは自社アプリの認可判定サービスで、ポリシーはCedarで書きます。IAMはAWSリソース用なので役割が重なりません。
- Cedarは既定で拒否し、forbidに1件でも当たればpermitより優先されます。
- 料金は単一の認可リクエストが1回0.000005ドル（100万回で5ドル）です。バッチは月間最初の4,000万回が1回0.00015ドルで、最大30件をまとめてようやく単一30回と同額になります。それを超える区間では単価が下がり、15件や8件で同額になります。
- CognitoやOIDCのトークンをそのまま渡せるのはIsAuthorizedWithToken系で、IDソースはポリシーストアごとに1つまでです。
- API Gatewayのクイックスタートは検証用の出発点で、本番はCloudFormationへ書き出して管理します。

以下、仕組み、Cedarの書き方、APIと料金、導入、制約の順に説明します。

## Amazon Verified Permissionsの役割とIAM・Cognitoとの分担

### ポリシーストア・スキーマ・ポリシー・IDソースの関係

AVPの設定はポリシーストアという入れ物にまとまります。中にはエンティティの型と属性を定義するスキーマ、判定ルールであるポリシーとポリシーテンプレート、トークン発行元を登録するIDソースが入ります。アプリは認可が必要な場面で「誰が（principal）」「何を（action）」「どれに（resource）」をAPIに渡し、ALLOWかDENYと、判定を決めたポリシーのIDを受け取ります。

| 構成要素       | 中身                           | 上限（既定値）          |
| ---------- | ---------------------------- | ---------------- |
| ポリシーストア    | アプリ単位・テナント単位の入れ物             | 1リージョン30,000個    |
| スキーマ       | エンティティ型・属性・アクション             | 100,000バイト       |
| ポリシー       | Cedarのpermit／forbid          | 1本10,000バイト      |
| ポリシーテンプレート | ?principal・?resourceの穴あきポリシー | ストアあたり40個        |
| IDソース      | CognitoユーザープールかOIDCプロバイダ     | ストアあたり1個（引き上げ不可） |

エンティティの属性や所属グループはAVP側に保存されず、リクエストごとに渡します。文書の所有者やテナントIDといった判定材料は、アプリが自分のデータベースから読み出して添える前提です。

### IAM・Cognitoグループ・Verified Accessとの違い

| サービス                 | 守る対象               | 判定の単位              |
| -------------------- | ------------------ | ------------------ |
| Verified Permissions | 自社アプリの操作・データ       | ユーザー×操作×リソース       |
| IAM                  | AWSのAPIとリソース       | IAMプリンシパル×AWSアクション |
| Cognitoのグループ         | グループ情報・IAMロール情報の提供 | 判定はアプリ側のコード        |
| Verified Access      | 社内アプリへのネットワーク到達    | VPNなしの接続可否         |

名前の似たAWS Verified Accessは、社内アプリへの接続をVPNなしで制御するゼロトラスト型のアクセスサービスで、アプリ内の権限判定はしません。Cognitoのグループだけで「管理者なら全部」程度のロール判定が済むなら、AVPを足す必要は薄いでしょう。テナント・所有者・状態のような属性で判定が分かれ始めた段階がAVPの出番です。ロールと属性による設計の違いは[RBACの仕組みと導入判断](/tech/details/6488/)と[ABACとRBACの使い分け](/tech/details/16407/)で詳しく扱っています。

## Cedarポリシーの書き方と評価ルール

### permit・forbidとスコープ・条件の構文

Cedarのポリシーは、permit（許可）かforbid（禁止）に、principal・action・resourceのスコープと、when（成立条件）・unless（除外条件）を付けて書きます。次は文書管理アプリを想定した例で、スキーマとポリシーをCedar CLI 4.13.0で検証しています。

```
// schema.cedarschema
namespace DocApp {
  entity User in [Team] { tenant: String, level: Long };
  entity Team;
  entity Document { owner: User, tenant: String, locked: Bool };
  action "view", "edit" appliesTo {
    principal: User,
    resource: Document,
    context: { mfa: Bool }
  };
}
```

```
// 同じテナントの編集チームは閲覧・編集できる
permit (
  principal in DocApp::Team::"editors",
  action in [DocApp::Action::"view", DocApp::Action::"edit"],
  resource
)
when { resource.tenant == principal.tenant };

// 所有者は自分の文書を閲覧できる
permit (principal, action == DocApp::Action::"view", resource)
when { resource.owner == principal };

// ロック中の文書は、MFA未使用なら誰も編集できない
forbid (principal, action == DocApp::Action::"edit", resource)
when { resource.locked }
unless { context.mfa };
```

`principal in DocApp::Team::"editors"` の `in` は、エンティティの親子関係（グループ所属）をたどって判定します。`when` の中では `resource.tenant` のようにエンティティの属性を、`context.mfa` のように要求ごとに渡す文脈情報を参照できます。

### 既定拒否とforbid優先の評価結果

Cedarはどのpermitにも当たらなければDENYを返し、forbidに1件でも当たればpermitの有無にかかわらずDENYにします。上のポリシーを並べた順にpolicy0〜policy2として、テナントt1・所有者bob・ロック中の文書d1への要求を `cedar authorize` で評価します（aliceはeditorsチーム所属でテナントt1、bobはチーム無所属でテナントt2）。

スキーマを `schema.cedarschema`、ポリシーを `policies.cedar` として保存し、エンティティを `entities.json`、文脈を `ctx.json` として次の内容で用意します。拒否ケースを試すときは `ctx.json` の `mfa` を `false` に変えます。5通りの要求の結果は、コマンドの後の表のとおりです。

```
[
  {"uid":{"type":"DocApp::User","id":"alice"},"attrs":{"tenant":"t1","level":3},
   "parents":[{"type":"DocApp::Team","id":"editors"}]},
  {"uid":{"type":"DocApp::User","id":"bob"},"attrs":{"tenant":"t2","level":1},"parents":[]},
  {"uid":{"type":"DocApp::Team","id":"editors"},"attrs":{},"parents":[]},
  {"uid":{"type":"DocApp::Document","id":"d1"},
   "attrs":{"owner":{"__entity":{"type":"DocApp::User","id":"bob"}},"tenant":"t1","locked":true},
   "parents":[]}
]
```

```
{"mfa": true}
```

```
cedar authorize --schema schema.cedarschema --policies policies.cedar \
  --entities entities.json --principal 'DocApp::User::"alice"' \
  --action 'DocApp::Action::"edit"' --resource 'DocApp::Document::"d1"' \
  --context ctx.json -v
```

| 要求          | mfa   | 結果    | 決めたポリシー         |
| ----------- | ----- | ----- | --------------- |
| aliceがd1を編集 | false | DENY  | policy2（forbid） |
| aliceがd1を編集 | true  | ALLOW | policy0         |
| aliceがd1を閲覧 | false | ALLOW | policy0         |
| bobがd1を閲覧   | false | ALLOW | policy1（所有者）    |
| bobがd1を編集   | true  | DENY  | 該当なし（既定拒否）      |

1行目はpolicy0のpermitにも当たっていますが、forbidが勝っています。5行目は所有者でも編集を許すpermitが無いため、どのポリシーにも当たらずDENYです。CLIはDENYのとき終了コード2を返すので、CIで「この要求は拒否されるべき」というテストをそのまま書けます。スキーマ検証も同じCLIで行え、policy0の `resource.tenant` を `resource.tenantId` と書き違えると `` attribute `tenantId` on entity type `DocApp::Document` not found `` と `` did you mean `tenant`? `` を出して終了コード3で止まりました。

forbidは既存のpermitに優先する禁止ルールを足す仕組みです。「退職処理中のユーザーは全操作禁止」のような横断ルールを1本のforbidで書けば、個々のpermitを書き換えずに済みます。ただし、評価中にエラーになったポリシーは判定から外されるため、参照する属性が要求に欠けているとforbidが効きません。スキーマ検証と、応答に含まれる評価エラーの監視を併用してください（出典：[Cedarの認可評価ルール](https://docs.cedarpolicy.com/auth/authorization.html)）。

### ポリシーテンプレートによるユーザー別の文書共有

「この文書をこのユーザーに共有する」のように、同じ形のポリシーを人と対象だけ変えて大量に作る場合はテンプレートを使います。

```
permit (
  principal == ?principal,
  action == DocApp::Action::"view",
  resource == ?resource
);
```

共有のたびに `CreatePolicy` でテンプレートリンクポリシーを作り、?principalと?resourceに実際の値を入れます。リンクは作成後も保たれ、テンプレートの文面を直すと、以後の判定ではリンク済みの全ポリシーが新しい文面で評価されます。AVPはCedar本体より制約が厳しく、principalとresourceには両方ともスコープ制約が必要で、どちらか一方でも無制約のテンプレートは受け付けません。`permit(principal, action == Action::"view", resource == ?resource);` はCedarでは有効でも、AVPでは拒否されます。

## 認可APIの選び方：IsAuthorizedとWithToken・バッチ

| API                        | 主体の渡し方          | 1回の判定数 | 既定RPS |
| -------------------------- | --------------- | ------ | ----- |
| IsAuthorized               | principalを自分で指定 | 1      | 200   |
| IsAuthorizedWithToken      | IDトークンかアクセストークン | 1      | 200   |
| BatchIsAuthorized          | principalを自分で指定 | 最大30   | 30    |
| BatchIsAuthorizedWithToken | IDトークンかアクセストークン | 最大30   | 30    |

RPSはポリシーストアごと・リージョンごとの既定値で、引き上げ申請ができます。WithToken系はIDソースに登録したCognitoやOIDCプロバイダのトークンを検証し、クレームを判定材料に変換します。IDトークンのクレームはprincipalの属性になるので、部署や役職による属性ベースの判定向きです。アクセストークンのクレームはcontextに入り、スコープやグループによるロール判定に使います。どちらもgroupsなどのクレームをグループ所属に対応付けられます。

BatchIsAuthorizedはprincipalかresourceのどちらかを全要求でそろえます。BatchIsAuthorizedWithTokenは1つのトークンから得た同じprincipalについて、複数の要求をまとめます。一覧画面で1人のユーザーが30件の文書それぞれを閲覧できるかを判定する、といった使い方です。バッチ専用のIAM権限はなく、BatchIsAuthorizedには `verifiedpermissions:IsAuthorized`、BatchIsAuthorizedWithTokenには `verifiedpermissions:IsAuthorizedWithToken` を許可します。

boto3からIsAuthorizedを呼び、entitiesのentityList形式を使う場合、エンティティの属性は型名で包みます。次の形はbotocore 1.42.97のパラメータ検証を通ることを確認しています。実行にはboto3、AWS認証情報、IsAuthorizedのIAM権限、掲載ポリシーを登録したポリシーストアが必要です。policyStoreIdを実際のIDに置き換えてください。この確認はAVP実サービスでの認可結果を保証するものではありません。

```
import boto3

avp = boto3.client("verifiedpermissions", region_name="ap-northeast-1")
res = avp.is_authorized(
    policyStoreId="PSEXAMPLEabcdefg111111",
    principal={"entityType": "DocApp::User", "entityId": "alice"},
    action={"actionType": "DocApp::Action", "actionId": "edit"},
    resource={"entityType": "DocApp::Document", "entityId": "d1"},
    context={"contextMap": {"mfa": {"boolean": True}}},
    entities={"entityList": [
        {"identifier": {"entityType": "DocApp::User", "entityId": "alice"},
         "attributes": {"tenant": {"string": "t1"}},
         "parents": [{"entityType": "DocApp::Team", "entityId": "editors"}]},
        {"identifier": {"entityType": "DocApp::Document", "entityId": "d1"},
         "attributes": {"tenant": {"string": "t1"}, "locked": {"boolean": True},
                        "owner": {"entityIdentifier": {"entityType": "DocApp::User", "entityId": "bob"}}}},
    ]},
)
print(res["decision"], res["determiningPolicies"])
```

Cedar単体のJSONでは `{"tenant": "t1"}` と書ける属性が、entityList形式では `{"tenant": {"string": "t1"}}` になります。Cedarで使っていたエンティティJSONをそのまま流用したいなら、entitiesに `cedarJson` を指定してJSON文字列で渡せば、この変換は要りません。

## 料金の計算方法とバッチが割高になる条件

料金は全リージョン共通で、前払いや最低利用料はありません。単一認可の単価は2025年6月12日に現行の0.000005ドルへ引き下げられ、バッチ認可とポリシー管理の単価はこのとき変わっていません。

| 区分                           | 単価（1回）     | 100万回あたり |
| ---------------------------- | ---------- | -------- |
| 単一認可（IsAuthorized／WithToken） | 0.000005ドル | 5ドル      |
| バッチ認可 月4,000万回まで             | 0.00015ドル  | 150ドル    |
| バッチ認可 次の6,000万回              | 0.000075ドル | 75ドル     |
| バッチ認可 1億回超                   | 0.00004ドル  | 40ドル     |
| ポリシー管理（CreatePolicy等）        | 0.00004ドル  | 40ドル     |

バッチは中の判定件数にかかわらず1回として課金され、最初の区間の単価は単一の30倍です。月4,000万回までは30件を詰めてようやく単一30回と同額で、10件ずつなら単一で呼ぶより3倍高くつきます。この区間でバッチを選ぶ理由は料金ではなく、一覧画面などでAPIの往復回数を減らすことです。

単価が下がる区間では損益分岐も変わります。月4,000万回超〜1億回の区間は1バッチ15件で単一と同額・16件以上で割安、1億回超の区間は8件で同額・9件以上で割安です。これは区間ごとの比較で、月額は区間ごとの料金を合算して求めます（出典：[AWS公式料金表](https://aws.amazon.com/verified-permissions/pricing/)、2026年10月1日確認）。

公式の試算例では、API Gatewayのクイックスタートで作ったLambdaオーソライザーが月500万回判定するケースが月25ドルです。`BatchGetPolicies` は返したポリシー数で課金されるため、ポリシーを定期取得してアプリ内で評価する構成（公式例ではavp-local-agent）では、判定そのものは無料でもポリシー管理の料金が積み上がります。公式例では20台のエージェントが月432万回取得して172.80ドルでした。

## API GatewayとCognitoで始める導入手順

### API連携ポリシーストアの自動生成リソースと本番移行

ポリシーストア作成時に「Set up with API Gateway and an identity provider」を選ぶと、既存のREST APIとCognitoユーザープール（または任意のOIDCプロバイダ）から、APIのメソッドとパスをアクションにしたスキーマ、グループ単位のポリシー、Lambdaオーソライザーをまとめて作ります。オーソライザーとその依存リソースは自動生成のCloudFormationスタックに入ります。

1. API GatewayのREST APIとステージ、IDソース（CognitoユーザープールかOIDCプロバイダ）を選ぶ
2. 各メソッドを呼べるユーザーグループ（Cognitoなら `cognito:groups` クレームのグループ）を割り当てる
3. デプロイ後、Authorizationヘッダにトークンを付けてAPIを呼び、許可と拒否を確認する

公式ドキュメントはこのストアを「テスト環境」と位置づけています。AVPがAPIの構造を読むのは作成時の1回だけで、あとからAPIにパスを足してもスキーマは更新されません。本番ではスキーマとポリシーを `AWS::VerifiedPermissions::PolicyStore`・`IdentitySource`・`Policy` としてCloudFormationテンプレートへ書き出し、Lambdaオーソライザー一式と合わせて管理する手順が推奨されています。

### アプリのコードから呼ぶ場合の組み込み先

API単位でなくデータ単位で判定したい場合は、アプリのコードからAPIを呼びます。Express.js向けには `@cedar-policy/authorization-for-expressjs`（0.3.0）と `@verifiedpermissions/authorization-clients-js`（0.2.0）があり、OpenAPI定義からCedarスキーマを生成してミドルウェアで判定できます。ユーザー認証とトークン発行はCognitoに任せ、AVPのIsAuthorizedWithTokenには発行されたトークン、アクション、リソースと必要な属性を渡し、IDソースの設定に基づくトークン検証と認可判定をAVPに任せる分担にすると、判定ロジックがアプリから消えます。Cognito側の構築は[Cognitoで認証基盤を実装する手順](/tech/details/17445/)を参照してください。

## クォータと運用で詰まりやすい制約

- **検証モード**：`STRICT` にするとスキーマに合わないポリシーの作成・更新が拒否されます。公式は開発中はOFF、テスト以降と本番はSTRICTを推奨しています。
- **リソースあたりのポリシー容量**：特定のリソースを参照するポリシーの合計は既定200,000バイトです。resourceを指定しないポリシーは別枠の200,000バイトを共有します。
- **階層の深さ**：1つのprincipalが持てる推移的な親は100までで、引き上げできません。グループを多段に入れ子にする設計は早めに数えておきます。
- **リクエストサイズ**：1回の認可リクエストは1MBまでです。大量の属性を毎回載せる設計はここで止まります。
- **カスタマー管理キー**：KMSのカスタマー管理キーでポリシーストアを暗号化できますが、一度使ったキーは後から変更も解除もできません。

上限値は2026年10月1日時点の既定値です（出典：[Amazon Verified Permissionsのクォータ](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/quotas.html)）。CloudTrailは管理系のAPIを記録しますが、IsAuthorizedなどの判定呼び出しはデータイベント扱いで、証跡を作っただけでは記録されません。監査で「いつ誰が何を拒否されたか」を追うなら、データイベントの記録を明示的に有効にしておきます。記録された判定結果のALLOW／DENYは `responseElements` ではなく `additionalEventData` に入るので、検索条件を組むときに注意してください。2025年2月にはポリシーストアのエイリアス、2025年3月にはポリシー名が加わり、IDの代わりに名前で参照できるようになりました。

## Cedar単体とAVPの使い分けと採用を見送る場面

CedarはAWSが公開したOSSで、2025年10月8日にCNCFのSandboxプロジェクトになりました。Rust版の `cedar-policy` は2026年9月15日公開の4.13.0が最新で、アプリに組み込めばAWSへの認可API呼び出しなしで評価できます。ただし、公式資料で示されるAVP内蔵Cedarは4.7で、単体版4.13.0とは異なるため、使用する構文・機能の互換性を確認します。AVPを選ぶ理由は、ポリシーの保管・更新、Cognito/OIDCトークン検証、CloudTrailによる変更・認可APIの監査をマネージドで持てることです。ポリシーの版履歴と復元手順は、Gitなどを使って別途管理します。

次の条件に当てはまるなら、AVPは見送るべきです。

- 判定がロール数個で完結する。Cognitoグループとアプリ内のif文で十分です。
- 1画面で数百件のリソースについて可否を出す。バッチは30件ずつで、「このユーザーが見られる文書一覧」を検索条件として返す機能もありません。一覧はデータベース側で絞り込む設計が要ります。
- 判定ごとのネットワーク往復が許されない。毎回AVPの認可APIを呼ぶ構成は避け、Cedarライブラリでのプロセス内評価や、AVPをポリシー管理だけに使うローカル評価（avp-local-agent）と比べます。
- Kubernetesのマニフェストなどインフラ設定の検査が目的。汎用のポリシーエンジンなら[OPAのRego](/tech/details/7523/)のほうが事例もツールも多くあります。

逆に、マルチテナントSaaSで顧客ごとに権限ルールが増え、監査で判定根拠を示す必要がある場合はAVPが向いています。応答には判定を決めたポリシーのIDが含まれ、明示的なforbidによる拒否ならそのIDで理由を追えます。一致するpermitがない既定拒否では決定ポリシーの一覧は空になるため、要求データや評価エラーも調べる必要があります。認可専用のOSSを比較したい場合は[Aserto Topazの現状](/tech/details/4609/)も参考になります。

## Amazon Verified Permissionsのよくある質問

### Amazon Verified PermissionsとAWS Verified Accessは何が違いますか？

Verified Permissionsはアプリ内の操作やデータへの権限を判定し、Verified Accessは社内アプリへのネットワーク接続をVPNなしで許可するかを判定します。守る層が違うので、両方を併用する構成もあります。

### 無料枠はありますか？

料金ページに無料利用枠の記載はなく、使った分だけの従量課金です。単一の認可リクエストは100万回で5ドルです。検証全体の費用には、ポリシー管理APIや、併用するLambda・API Gatewayなどの料金も含めて見積もります。

### IAMポリシーの代わりになりますか？

なりません。IAMはAWSのAPIとリソースへのアクセスを制御し、AVPは自社アプリのユーザーの権限を判定します。AVP自体のAPIを呼ぶ権限はIAMで付与します。組織のAWSアカウント権限の設計は[IAM Identity Centerの権限セット設計](/tech/details/15900/)が参考になります。

### Cognito以外の認証基盤でも使えますか？

2024年6月からOIDCプロバイダをIDソースに登録でき、Auth0やOktaなどのトークンをIsAuthorizedWithTokenで渡せます。IDソースを使わずIsAuthorizedでprincipalを直接指定する方法もあります。

### 東京リージョンや大阪リージョンで使えますか？

使えます。AWS SDK（botocore 1.42.97）のエンドポイント定義には東京（ap-northeast-1）と大阪（ap-northeast-3）を含む34リージョンが載っており、料金もリージョンによる差がありません。ポリシーストアはリージョン単位の資源なので、複数リージョンで使う場合はCloudFormationで同じストアを各リージョンに配ります。

## 関連記事

- [ABACとは？属性ベースアクセス制御の仕組みとRBACとの使い分けを実装視点で解説](/tech/details/16407/)
- [RBACとは？ロールベースアクセス制御の仕組みと導入判断を実装視点で解説](/tech/details/6488/)
- [Cognitoで認証基盤を実装する手順：ユーザープール構築からJWT検証まで](/tech/details/17445/)
- [Regoとは？OPA 1.0（Rego v1）の書き方とv0コード移行・テストの実装ガイド](/tech/details/7523/)
- [Aserto Topazとは？商用サービス終了後もOSSで使えるのか【2026年8月時点】](/tech/details/4609/)

---

出典: [Amazon Verified Permissionsとは？Cedarの書き方と料金・API Gateway連携の手順](<https://www.issoh.co.jp/tech/details/4766/>)（株式会社一創）
