Add authorization policy reference and enhance Cedar docs#664
Add authorization policy reference and enhance Cedar docs#664
Conversation
The existing Cedar policies page lacked a complete dictionary of entity types, actions, attributes, and annotations that policy authors can reference. This adds a dedicated reference page and enhances the concept page with annotation-based policies, group membership, real-world profiles, and troubleshooting for the new features. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Adds comprehensive documentation for ToolHive Cedar authorization policy authoring by introducing a new reference page and expanding the existing Cedar policies concept page, plus wiring the new doc into the sidebar navigation.
Changes:
- Added a new “Authorization policy reference” page covering entity types, actions, attributes, annotations, groups, list filtering, and HTTP PDP mapping.
- Expanded “Cedar policies” concepts doc with group-based access control, tool annotation policy patterns, and real-world policy profiles/troubleshooting.
- Updated
sidebars.tsto include the new reference page.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| sidebars.ts | Adds the new authorization policy reference doc to the ToolHive sidebar. |
| docs/toolhive/reference/authz-policy-reference.mdx | New, detailed Cedar/ToolHive authorization reference page. |
| docs/toolhive/concepts/cedar-policies.mdx | Enhances the Cedar policies concept doc with groups/annotations/profiles and additional troubleshooting. |
| List operations (`tools/list`, `prompts/list`, `resources/list`) work | ||
| differently from other operations. ToolHive always allows the list request | ||
| itself, but filters the response to include only items the caller is authorized | ||
| to access. | ||
|
|
||
| For each item in the list response, ToolHive runs a policy check using the | ||
| corresponding action: | ||
|
|
||
| | List method | Per-item check uses | | ||
| | ---------------- | ---------------------------------------------------------- | | ||
| | `tools/list` | `Action::"call_tool"` against each `Tool::"<name>"` | | ||
| | `prompts/list` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | ||
| | `resources/list` | `Action::"read_resource"` against each `Resource::"<uri>"` | | ||
|
|
||
| This means you don't need separate list policies. Your `call_tool`, | ||
| `get_prompt`, and `read_resource` policies automatically control what appears in | ||
| list responses. |
There was a problem hiding this comment.
The list-operation semantics are internally inconsistent: this section says tools/list/prompts/list/resources/list are “always allowed”, but earlier the page lists Action::"list_*" as actions that require authorization. Please clarify whether list methods are authorization-checked, and update either the actions table or this section so they match the actual behavior.
| List operations (`tools/list`, `prompts/list`, `resources/list`) work | |
| differently from other operations. ToolHive always allows the list request | |
| itself, but filters the response to include only items the caller is authorized | |
| to access. | |
| For each item in the list response, ToolHive runs a policy check using the | |
| corresponding action: | |
| | List method | Per-item check uses | | |
| | ---------------- | ---------------------------------------------------------- | | |
| | `tools/list` | `Action::"call_tool"` against each `Tool::"<name>"` | | |
| | `prompts/list` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | |
| | `resources/list` | `Action::"read_resource"` against each `Resource::"<uri>"` | | |
| This means you don't need separate list policies. Your `call_tool`, | |
| `get_prompt`, and `read_resource` policies automatically control what appears in | |
| list responses. | |
| List operations (`tools/list`, `prompts/list`, `resources/list`) have two | |
| authorization steps. First, ToolHive authorizes the list request itself using | |
| the corresponding `list_*` action. Then it filters the response to include only | |
| items the caller is authorized to access. | |
| For each supported list method, ToolHive performs the following checks: | |
| | List method | Request-level action | Per-item check uses | | |
| | ---------------- | ------------------------------- | ---------------------------------------------------------- | | |
| | `tools/list` | `Action::"list_tools"` | `Action::"call_tool"` against each `Tool::"<name>"` | | |
| | `prompts/list` | `Action::"list_prompts"` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | |
| | `resources/list` | `Action::"list_resources"` | `Action::"read_resource"` against each `Resource::"<uri>"` | | |
| This means your policies can control both whether a caller may use a list | |
| method at all and which items appear in the response. `list_*` policies govern | |
| access to the list operation itself, while `call_tool`, `get_prompt`, and | |
| `read_resource` policies govern the contents of list responses. |
| If you want explicit control over list operations (for example, to allow listing | ||
| but deny individual access), you can write policies using the `list_tools`, | ||
| `list_prompts`, or `list_resources` actions against `FeatureType::` entities. |
There was a problem hiding this comment.
This note suggests you can “allow listing but deny individual access” using list_tools/list_prompts/list_resources against FeatureType:: entities, but just above you state list responses are filtered per-item using call_tool/get_prompt/read_resource. Under that model, permitting list_* would not make items appear if the per-item actions are denied. Please adjust the guidance to reflect the real filtering/authorization flow (or update the per-item check description if list_* policies are actually used for filtering).
| If you want explicit control over list operations (for example, to allow listing | |
| but deny individual access), you can write policies using the `list_tools`, | |
| `list_prompts`, or `list_resources` actions against `FeatureType::` entities. | |
| If you want explicit control over whether a list operation itself is allowed, | |
| you can write policies using the `list_tools`, `list_prompts`, or | |
| `list_resources` actions against `FeatureType::` entities. These actions do not | |
| override per-item filtering: items still only appear in list responses when the | |
| corresponding `call_tool`, `get_prompt`, or `read_resource` check succeeds. |
| ### Observe profile (read-only) | ||
|
|
||
| Allow listing and reading MCP capabilities, but block all tool calls: | ||
|
|
There was a problem hiding this comment.
The “Observe profile” says it allows listing capabilities while blocking all tool calls, but elsewhere the docs state tools/list is filtered based on call_tool permissions. If that filtering is accurate, denying all call_tool will yield an empty tool list, which contradicts “see what’s available”. Consider clarifying the expected behavior and/or revising the profile to match how list filtering works.
| | List method | Per-item check uses | | ||
| | ---------------- | ---------------------------------------------------------- | | ||
| | `tools/list` | `Action::"call_tool"` against each `Tool::"<name>"` | | ||
| | `prompts/list` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | ||
| | `resources/list` | `Action::"read_resource"` against each `Resource::"<uri>"` | | ||
|
|
||
| This means you don't need separate list policies. Your `call_tool`, | ||
| `get_prompt`, and `read_resource` policies automatically control what appears in | ||
| list responses. |
There was a problem hiding this comment.
In the entity-type table above, Resource IDs are described as Resource::"<sanitized_uri>", but this per-item list check table shows Resource::"<uri>" for resources/list. Please make the identifier format consistent (or explicitly call out that the list filter uses the sanitized form while also exposing the original URI via an attribute).
| | List method | Per-item check uses | | |
| | ---------------- | ---------------------------------------------------------- | | |
| | `tools/list` | `Action::"call_tool"` against each `Tool::"<name>"` | | |
| | `prompts/list` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | |
| | `resources/list` | `Action::"read_resource"` against each `Resource::"<uri>"` | | |
| This means you don't need separate list policies. Your `call_tool`, | |
| `get_prompt`, and `read_resource` policies automatically control what appears in | |
| list responses. | |
| | List method | Per-item check uses | | |
| | ---------------- | ---------------------------------------------------------------------- | | |
| | `tools/list` | `Action::"call_tool"` against each `Tool::"<name>"` | | |
| | `prompts/list` | `Action::"get_prompt"` against each `Prompt::"<name>"` | | |
| | `resources/list` | `Action::"read_resource"` against each `Resource::"<sanitized_uri>"` | | |
| This means you don't need separate list policies. Your `call_tool`, | |
| `get_prompt`, and `read_resource` policies automatically control what appears in | |
| list responses. For resources, the per-item check uses the sanitized | |
| `Resource` entity ID, while the original URI remains available via the | |
| `resource.uri` attribute. |
Summary
Policy authors lacked a complete dictionary of Cedar entity types, actions, attributes, and annotations available when writing ToolHive authorization policies. The existing Cedar policies concept page also had no coverage of tool annotations, group membership, or real-world policy profiles.
This PR adds a dedicated reference page and enhances the concept page to close these gaps.
Changes
New:
reference/authz-policy-reference.mdxComplete reference dictionary covering:
hasoperator guidance and trust boundary explanationentities_jsonUpdated:
concepts/cedar-policies.mdxTHVGroupandinoperatorhasoperator, annotation examples, and forbid patternsgroup_claim_nameto configuration fieldsUpdated:
sidebars.tsauthz-policy-referenceto sidebarTest plan
npm run buildpasses with no new warnings or broken linksGenerated with Claude Code