Cedar ポリシー (Cedar Policies)
Griptape Nodes のパーミッションテンプレートは、Amazon のオープンソース認可言語である Cedar を使用しています。パーミッションエディタ (Permission Editor) では、パーミッションビルダー (Permission Builder) が GUI 上での選択内容を Cedar ポリシーに自動変換します。このページは、Raw Cedar テンプレートを直接記述する場合や、ビルダーによって生成された Cedar コードを監査する場合に参照してください。
ビルダーの機能カタログで表現できない高度なルールが必要な場合にのみ、Raw Cedar を選択してください。
ポリシーの入力構造 (Policy inputs)
Cedar は各認可判定を 4 つの入力 (principal, action, resource, context) に基づいて行います。Griptape Nodes は各認可チェックポイントとライセンスデータを以下の Cedar 入力にマッピングします:
| 要素 | 保持するデータ | 用途 |
|---|---|---|
principal |
固定のプレースホルダー User::"<anonymous>"。 |
使用しません。条件なしのままにしておきます。 |
action |
認可チェックポイント(例: Action::"LoadLibrary")。 |
ルールが対象とする操作の名前指定。 |
resource |
チェックポイントで解決されたライブラリ、ノードタイプ、プロジェクト、モデル、またはコーデック。 | 特定のオブジェクトやその属性とのマッチング。 |
context |
アクティブなプロジェクト、エンジン、ライブラリ、ライセンスの情報。 | 特定のプロジェクトやライセンスタイプへのルールのスコープ限定。 |
判定の組み合わせルール (Combining decisions)
Cedar は複数のテンプレートを組み合わせる際、以下の 2 つの基本ルールに従います:
- 少なくとも 1 つの一致する
permit文が操作を許可している必要があります。 - 一致する
forbid文は、他のテンプレートからの許可も含め、すべてのpermitを上書き(拒否が最優先) します。
ビルダーが生成する Cedar の設計パターン:
- Exploration (Allow all):
permit(principal, action, resource);から始まり、例外的にブロックしたい対象にforbid文を追加します。 - Production (Deny All): 包括的な許可文を排除し、明示的に許可する操作に対してのみ
permit文を追加します。
デフォルト拒否とハードブロック
Cedar は少なくとも 1 つのステートメントが明示的に許可しない限り、操作を拒否します。したがって、forbid 文のみを含むポリシーセットは、マッチした操作だけでなく、すべての操作を拒否 してしまいます。ブラックリスト(拒否リスト)を作成する場合は、必ず包括的な permit と組み合わせてください:
permit(principal, action, resource);
forbid(principal, action, resource)
when { resource has lifecycle_stage && resource.lifecycle_stage == "LABS" };
permit を記述しないことは「完全なブロック(ハードブロック)」を意味しません。別のテンプレートにある permit によって操作が許可される可能性があります。いかなる許可も上書きさせたくない場合は、明示的に forbid を使用してください。Cedar はライセンスキーに紐付くすべてのテンプレートを 1 つのポリシーセットとして評価するため、permit と forbid が別々のテンプレートに存在していても正しく機能します。
チェックポイント (Checkpoints)
以下のアクションは、エンジンがアクセス制御を行う操作(チェックポイント)を定義しています。拒否(Deny)された場合の結果はチェックポイントごとに異なります。
| アクション | 発火タイミング | リソース | 拒否された場合の挙動 |
|---|---|---|---|
Action::"LoadLibrary" |
ライブラリがメタデータ読み込み以降に進むとき。 | Library |
ライブラリが使用不能(Unusable)とマークされ、エラーアイコンに理由が表示されます。 |
Action::"InstantiateNode" |
ノードが作成されるとき。 | NodeType |
本物のノードの代わりにエラープロキシ(Error Proxy)ノードが配置されます。拒否されたノードタイプはライブラリ上にも事前に一覧表示されます。 |
Action::"LoadProject" |
プロジェクトテンプレートが読み込まれるとき。 | Project |
プロジェクトの読み込みに失敗します。 |
Action::"ActivateProject" |
プロジェクトが現在のアクティブプロジェクトになるとき。 | Project |
切り替えが失敗し、現在のプロジェクトのまま維持されます。 |
Action::"OfferModel" |
モデル選択ピッカーが構築されるとき。 | Model |
モデルがピッカーからフィルタリングされ、非表示になります。 |
Action::"InvokeModel" |
ノードがモデルを呼び出すとき。 | Model |
呼び出しが失敗します。 |
Action::"ReadVideoCodec" |
動画の読み込み時、およびピッカー構築時。 | VideoCodec |
読み込みが拒否されるか、コーデックが除外されます。 |
Action::"WriteVideoCodec" |
動画の書き出し時、およびピッカー構築時。 | VideoCodec |
書き出しが拒否されるか、コーデックが除外されます。 |
リソース属性 (Resource attributes)
明記されていない限り、すべてのリソース属性はオプショナル(存在しない場合がある)です。オプショナルな属性を読み取る前に、必ず has を使用して存在確認を行ってください。必須の記述パターンについては オプショナル属性の保護 を参照してください。
Library
| 属性 | 型 | 存在条件 |
|---|---|---|
id |
string | 常に存在。ライブラリ名。 |
lifecycle_stage |
string | ライブラリがステージを宣言している場合。 |
NodeType
| 属性 | 型 | 存在条件 |
|---|---|---|
id |
string | 常に存在。ノードタイプ名。 |
executes_arbitrary_code |
bool | 常に存在。ライブラリ宣言で任意の Python 実行が明記されている場合は true。 |
lifecycle_stage |
string | ノードがステージを宣言しているか、ライブラリから継承している場合。 |
model_ids |
set |
ノードがモデルの使用を宣言している場合。 |
provider_ids |
set |
ノードがモデルまたはプロバイダーの使用を宣言している場合。 |
model_families |
set |
ノードの宣言モデルがライブラリのモデルカタログ内でファミリーに解決される場合。 |
Project
| 属性 | 型 | 存在条件 |
|---|---|---|
id |
string | 常に存在。プロジェクトの一意な不透明 ID(エディタ作成時は GUID)。 |
name |
string | テンプレートの読み込みが進み名前が判明した時点。 |
人間が読めるルールには name を、完全一致が必要な場合は id を使用します。permit では id を優先してください。プロジェクト名はテンプレートがロードされた後にのみ利用可能となるため、名前に依存した permit が一致しないと拒否されてしまうためです。
Model
| 属性 | 型 | 存在条件 |
|---|---|---|
id |
string | 常に存在。カタログ内の安定したモデルキー。 |
provider_id |
string | キーがモデルカタログ内で解決される場合。 |
model_families |
set |
解決されたモデルがファミリーを宣言している場合(その 1 つのファミリーを保持)。 |
| 単一のモデルではなくプロバイダー全体にマッチさせる場合は、エンティティ階層 を参照してください。 |
VideoCodec
| 属性 | 型 | 存在条件 |
|---|---|---|
id |
string | 常に存在。検出されたコーデック名(例: h264、hevc)。 |
container_format |
string | コンテナ形式が既知の場合(例: mp4、mov)。 |
エンティティ階層 (Entity hierarchy)
ModelProvider
各 Model はそれを提供するプロバイダーの下に位置付けられているため、個別に名前を列挙しなくても in 演算子を使用してプロバイダー配下のすべてのモデルを一括指定できます。
例:
forbid(principal, action, resource)
unless { resource in ModelProvider::"anthropic" };
プロバイダー ID は、ライブラリの model_catalog 内のプロバイダーキー(anthropic、ollama など)です。
コンテキスト情報 (Context facts)
コンテキスト情報の保護
すべてのコンテキスト情報はオプショナルです。Griptape Nodes は解決可能な情報のみを含め、それ以外は省略するため、読み取る前に必ず has でチェックしてください。
レコードの存在を保護した上で、プロパティを読み取ります:
when {
context has loaded_libraries &&
context.loaded_libraries.names.contains("My Library")
}
| 情報 | 型 | 備考 |
|---|---|---|
active_project.id |
string | エンジンレジストリキーとして使用される不透明なプロジェクト ID。 |
active_project.name |
string | 表示名(テンプレートが読み込まれた場合)。個別の has 保護が必要。 |
engine.id |
string | アクティブなエンジンの ID。 |
loaded_libraries.names |
set |
これまでに読み込まれたライブラリ名のセット。 |
license_id |
string | ライセンスキーの ID。 |
org_id |
string | ライセンスが属する組織の ID。 |
license_type |
string | "headless" または "interactive"。 |
プロジェクトスコープ (Project scope)
ビルダーは、関連付けられたプロジェクトを使用して、Project-scoped テンプレートのすべての文に以下の条件を自動付与します:
when { context has active_project && context.active_project.id == "<project id>" }
Griptape Nodes は、アクティブなプロジェクトの継承チェーンに含まれるすべてのプロジェクトに対してポリシーを評価します。これには 2 つの重要な帰結があります。
祖先プロジェクトを含める必要があります。 あるプロジェクトが親プロジェクトから継承している場合、ポリシーはチェーン内の各プロジェクトに対して実行されます:まずアクティブなプロジェクト、次に各祖先プロジェクト。すべての実行において操作が許可されなければなりません。したがって、親プロジェクトにスコープされた forbid はその子プロジェクトもブロックし、プロジェクトの許可リストにはチェーン内のすべてのプロジェクトを含める必要があります。
例えば、Shot 42 が Studio Defaults を継承しているとします。Shot 42 でライブラリを許可するには、両方のプロジェクト ID に対する permit が必要です:
permit(principal, action == Action::"LoadLibrary", resource)
when {
context has active_project &&
context.active_project.id == "<Shot 42 id>"
};
permit(principal, action == Action::"LoadLibrary", resource)
when {
context has active_project &&
context.active_project.id == "<Studio Defaults id>"
};
1 つ目の permit だけでは Shot 42 のチェックは通りますが、Studio Defaults のチェックで拒否されます。また、Studio Defaults に一致する forbid がある場合、Shot 42 での操作も拒否されます。
デフォルトプロジェクトの考慮。 別途設定されない限り、エンジンは デフォルトプロジェクト(ID は <system-defaults>)で起動します。この ID を明示的に許可する必要はありませんが、明示的な forbid ルールは依然として適用されます。
拒否アノテーション (Denial annotations)
Cedar は操作を拒否したルールを特定しますが、ユーザーに何の権限が不足しているのかまでは説明しません。Griptape Nodes は 3 つのアノテーションを使用してその情報を補加します。これらは Griptape の独自規則であり、Cedar のポリシー評価エンジン自体はこれらを無視します。
| アノテーション | 目的 |
|---|---|
@id("<slug>") |
ルールの安定した識別名。位置による代替名ではなく、拒否理由画面に表示されます。 |
@capability("<name>") |
ユーザーに不足している機能(例: arbitrary-code-execution)。 |
@advice("<text>") |
解決のためのアドバイス。ユーザーが画面で読む説明文です。 |
@id("nodes/no-arbitrary-code")
@capability("arbitrary-code-execution")
@advice("任意コードを実行するノードはこのライセンスでは利用できません。スタジオ管理者に有効化を依頼してください。")
forbid(principal, action == Action::"InstantiateNode", resource)
when { resource has executes_arbitrary_code && resource.executes_arbitrary_code };
記述するすべての forbid 文にこれらのアノテーションを付与してください。@advice がないと、ユーザーにはポリシー ID のみが表示され、拒否を解決するための具体的な指示が表示されません。
@capability の値は自由形式であり、Cedar による検証は行われません。テンプレート間での一貫性を保つため、ビルダーが生成する以下の標準名を使用することを推奨します:
librarylibrary-lifecyclenode-lifecyclearbitrary-code-executionprojectmodelmodel-providermodel-familyvideo-codec
実装例 (Examples)
以下の各例は、完全な Raw Cedar ポリシーです。
任意コード実行ノードのブロック
包括的な許可(permit)を含め、完全なブロックリストテンプレートとした例:
permit(principal, action, resource);
@id("nodes/no-arbitrary-code")
@capability("arbitrary-code-execution")
@advice("任意コードを実行するノードはこのライセンスでは利用できません。")
forbid(principal, action == Action::"InstantiateNode", resource)
when { resource has executes_arbitrary_code && resource.executes_arbitrary_code };
不安定なライブラリとノードのブロック
ライブラリとノードで別々のステートメントを使用します。これにより、拒否画面でユーザーに不足している機能が正確に表示されます。
permit(principal, action, resource);
@id("lifecycle/no-experimental-libraries")
@capability("library-lifecycle")
@advice("実験的ライブラリはこのライセンスではブロックされています。承認済みライブラリについてスタジオ管理者に確認してください。")
forbid(principal, action == Action::"LoadLibrary", resource)
when {
resource has lifecycle_stage &&
(resource.lifecycle_stage == "LABS" || resource.lifecycle_stage == "ALPHA")
};
@id("lifecycle/no-experimental-nodes")
@capability("node-lifecycle")
@advice("実験的ノードはこのライセンスではブロックされています。STABLE または BETA の代替ノードを使用してください。")
forbid(principal, action == Action::"InstantiateNode", resource)
when {
resource has lifecycle_stage &&
(resource.lifecycle_stage == "LABS" || resource.lifecycle_stage == "ALPHA")
};
特定の 2 つのモデルプロバイダーのみを許可
unless 句で条件を反転させ、指定した 2 つ以外のすべてのプロバイダーをブロックします。in 演算子は親を持たないリソースに対してもエラーにならず false を返すため、has による保護は不要です。
モデルを制限する場合は、両方のモデルチェックポイントを指定します。OfferModel は拒否されたモデルをピッカーから除外し、InvokeModel は既存ノードからの呼び出しをブロックします。
permit(principal, action, resource);
@id("models/approved-providers")
@capability("model-provider")
@advice("このライセンスでは Anthropic および OpenAI のモデルのみが承認されています。")
forbid(principal, action in [Action::"OfferModel", Action::"InvokeModel"], resource)
unless { resource in ModelProvider::"anthropic" || resource in ModelProvider::"openai" };
特定のモデルファミリーのブロック
model_families はセット型であるため、contains を使用して値をチェックします:
permit(principal, action, resource);
@id("models/no-claude-3")
@capability("model-family")
@advice("Claude 3 モデルはこのライセンスでは廃止されました。Claude 4 を使用してください。")
forbid(principal, action in [Action::"OfferModel", Action::"InvokeModel"], resource)
when { resource has model_families && resource.model_families.contains("Claude 3") };
特定のプロジェクトのみを許可
エンジンはプロジェクトの読み込み(Load)と有効化(Activate)を個別に制御するため、両方のチェックポイントを指定します。
permit(principal, action, resource);
@id("projects/approved")
@capability("project")
@advice("このプロジェクトはお使いのライセンスに含まれていません。スタジオ管理者にアクセス権を依頼してください。")
forbid(principal, action in [Action::"LoadProject", Action::"ActivateProject"], resource)
unless {
resource has id &&
(resource.id == "8f2c1a04-9d3e-4b7a-9f10-2c5d6e8a1b33" || resource.id == "c07b5e91-4a2d-4f88-bd63-1e9f7a205c48")
};
動画コーデック書き出しの制限
書き込みチェックポイントのみを指定します。
permit(principal, action, resource);
@id("video/no-prores-writes")
@capability("video-codec")
@advice("ProRes の書き出しはこのライセンスでは許可されていません。H.264 でレンダリングしてください。")
forbid(principal, action == Action::"WriteVideoCodec", resource)
when { resource has id && resource.id == "prores" };
ルールを 1 つのプロジェクトにスコープ限定
Cedar は複数の when 句を AND 条件で結合するため、プロジェクトのスコープ指定とリソースの条件を分けて記述できます:
permit(principal, action, resource);
@id("show-a/no-experimental-nodes")
@capability("node-lifecycle")
@advice("Show A では安定版(STABLE)ノードのみに固定されています。")
forbid(principal, action == Action::"InstantiateNode", resource)
when {
context has active_project &&
context.active_project has name &&
context.active_project.name == "Show A"
}
when { resource has lifecycle_stage && resource.lifecycle_stage == "LABS" };
ヘッドレスライセンスの制限
permit(principal, action, resource);
@id("headless/no-model-invocation")
@capability("model")
@advice("このプランではヘッドレスライセンスによるモデル呼び出しはできません。")
forbid(principal, action == Action::"InvokeModel", resource)
when { context has license_type && context.license_type == "headless" };
注意点と落とし穴 (Gotchas)
オプショナル属性の保護
存在しない属性を直接読み取るとエラーが発生します。Cedar はエラーを含む条件を「不成立」として扱いますが、エンジン側はクリーンに評価できなかった操作を安全のためにすべて拒否します。したがって、保護のない読み取りを行うと、属性を持たないリソースに対する forbid が空振りしたり、その情報を持たない正当な操作がブロックされたりします。
// 誤り。ライフサイクルステージが宣言されていないすべてのノードタイプが拒否されてしまいます。
forbid(principal, action == Action::"InstantiateNode", resource)
when { resource.lifecycle_stage == "LABS" };
// 正しい記述。
forbid(principal, action == Action::"InstantiateNode", resource)
when { resource has lifecycle_stage && resource.lifecycle_stage == "LABS" };
&& は短絡評価されるため、必ず has ガードを左側に配置してください。
ネストされた情報も各階層ごとに保護してください。context has active_project であっても、そのアクティブプロジェクトが name を持っているとは限りません:
when {
context has active_project &&
context.active_project has name &&
context.active_project.name == "Show A"
}
名前のスペルミスに注意
エンジンは Cedar ポリシーをスキーマに照らし合わせて厳密検証しません。resource.lifecycle_stge や Action::"LoadLibrry" のようなスペルミスは構文的には正常にパースされますが、何もマッチしないため、一見動作していないように見えるルールになってしまいます。
必要なすべてのチェックポイントを許可する
厳格な Production テンプレートで LoadLibrary のみを許可した場合、ライブラリの読み込みは成功しますが、デフォルト拒否によってノードの配置など他のチェックポイント操作がすべてブロックされてしまいます。ワークフローが必要とするすべての操作を明示的に指定するか、それらを許可する別のテンプレートを組み合わせてください。
// ライブラリの読み込みのみを許可
permit(principal, action == Action::"LoadLibrary", resource);
// 現在のすべてのチェックポイントを包括的に許可
permit(principal, action in [
Action::"LoadLibrary",
Action::"InstantiateNode",
Action::"LoadProject",
Action::"ActivateProject",
Action::"OfferModel",
Action::"InvokeModel",
Action::"ReadVideoCodec",
Action::"WriteVideoCodec"
], resource);