Feature Request: Authorization Context Enrichment via Rego Policies
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
ToolHive's authorization middleware currently produces generic, coarse-grained
operation and resource identifiers for MCP requests. For example, a tools/call
to list_commits on the GitHub MCP server produces:
- operation:
mcp:tool:call - resource:
mrn:mcp:github:tool:list_commits
These identifiers are sufficient for policies like "allow all tool calls on the
github server", but they carry no argument context. This makes it impossible to
write fine-grained policies such as "allow list_commits only on repos the user
owns" because the target repository is never surfaced to the PDP.
Proposed Solution
Add a context enrichment stage to the authorization pipeline. Before a
non-list MCP request is sent to the PDP, an optional user-defined Rego policy
runs and may transform the operation/resource identifiers based on full request
context (tool arguments, server ID, feature, etc.).
With enrichment enabled, the same list_commits call could produce:
- operation:
mcp:tool:github:commit:list - resource:
mrn:toolhive:github:repo:owner/my-repo
The PDP can then enforce repository-scoped or verb-scoped policies that would
not be possible today.
Design
New pkg/authz/enrichment package
Enricherinterface –Enrich(Input) (*Result, error). Implementations
can use Rego, schema inference, or any other mechanism.Pipeline– runs enrichers in order; returns the first non-nil result.
Errors are logged and skipped so enrichment failures never block requests.RegoEnricher– evaluates a Rego policy in package
toolhive.authz.enrichment; the policy defines a rule namedresultthat
maps input fields tooperationandresourcestrings.Input/Resulttypes – carry feature, operation, resource ID,
arguments, and server ID into the policy; carry back enriched strings.
Config
Add an optional enrichment block to the existing authz YAML config:
version: "1.0"
type: httpv1
enrichment:
rego_policy: "/path/to/enrichment.rego"
# OR inline:
# rego_policy_inline: |
# package toolhive.authz.enrichment
# default result := {}
# result := { "operation": ..., "resource": ... } if { ... }
pdp:
http:
url: "http://localhost:9000"
claim_mapping: "standard"
context:
include_args: true
Configs without the enrichment section continue to work unchanged. Exactly
one of rego_policy (file path) or rego_policy_inline may be set.
Middleware integration
- authz.Middleware gains an optional *enrichment.Pipeline parameter (nil
disables enrichment; existing callers are unaffected in behavior). - For non-list operations the middleware runs applyEnrichment before calling
the authorizer. The enrichment result is stored in the request context. - The HTTP PDP authorizer reads the enriched operation/resource from context and
substitutes them into the PORC before dispatching to the PDP. The
context.mcp fields retain the original unenriched values so the PDP has
access to both. - List operations are not enriched (they use the existing filter-on-response
path).
Example policies
Provide a full example enrichment policy for the GitHub MCP server
(examples/enrichment-github.rego) covering all 41 GitHub tools across six
resource scopes (repo, owner, org, search, user, global) with a consistent
noun:verb operation convention, plus an accompanying config example
(examples/authz-httpv1-enrichment-config.yaml).
Scope / Limitations
- Phase 1: HTTP PDP authorizer (httpv1) only. Cedar (cedarv1) support is
deferred to a follow-up. - Enrichment policies must use OPA v1 syntax (the if keyword is required
before rule bodies). - Only non-list operations are enriched.
Acceptance Criteria
- pkg/authz/enrichment package with Enricher, Pipeline, RegoEnricher,
Input, Result, and Config types, with unit tests. - authz.Middleware accepts an optional *enrichment.Pipeline; nil is a
no-op (no behaviour change for existing users). - HTTP PDP authorizer substitutes enriched operation/resource when an
enrichment result is present in context. - enrichment block in authz YAML config (rego_policy / rego_policy_inline).
- docs/authz.md updated with a "Context enrichment" section including
the input/output contract, configuration reference, and examples. - Example Rego policy and config file added under examples/.
- All existing authz tests continue to pass.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing authz middleware and HTTP PDP authorizer, then inspect the requested pkg/authz/enrichment package boundaries and acceptance criteria. Implement and test the enrichment pipeline, configuration, context handling, and HTTP integration described in the issue; update docs/authz.md and add the two examples under examples/. Run the existing authz tests and the new enrichment unit tests to verify unchanged behavior without enrichment.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authorization, backend-api-design, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100