mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
feat(proxy): auth_v2 governs mcp_server and guardrail admin surfaces
Governs the collection-level management operations (register/list/health/ submissions) for MCP servers and guardrails, mapped to read/write with wildcard objects since they are not per-id. Runtime guardrail verbs (apply_guardrail, test_custom_code) remain loud-open as data/runtime concerns, not management.
This commit is contained in:
parent
04bb7f2361
commit
4ffb474945
2 changed files with 25 additions and 4 deletions
|
|
@ -87,6 +87,16 @@ _GOVERNED: Dict[str, GovernedRoute] = {
|
|||
"/customer/list": GovernedRoute("customer", "read"),
|
||||
"/customer/block": GovernedRoute("customer", "write", _CUSTOMER_ID_FIELDS),
|
||||
"/customer/unblock": GovernedRoute("customer", "write", _CUSTOMER_ID_FIELDS),
|
||||
# MCP server and guardrail admin surfaces expose collection-level operations
|
||||
# (register/list/health/submissions), so objects stay at "<resource>:*"; the
|
||||
# runtime verbs (apply_guardrail, test_custom_code) are not management and are
|
||||
# intentionally left to the data/runtime path.
|
||||
"/v1/mcp/server/register": GovernedRoute("mcp_server", "write"),
|
||||
"/v1/mcp/server/health": GovernedRoute("mcp_server", "read"),
|
||||
"/v1/mcp/server/submissions": GovernedRoute("mcp_server", "read"),
|
||||
"/guardrails/register": GovernedRoute("guardrail", "write"),
|
||||
"/guardrails/list": GovernedRoute("guardrail", "read"),
|
||||
"/guardrails/submissions": GovernedRoute("guardrail", "read"),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -98,12 +98,23 @@ def test_customer_resource_is_governed():
|
|||
assert match_route("/customer/info").id_fields == ["user_id"]
|
||||
|
||||
|
||||
def test_deferred_nonuniform_surfaces_are_still_loud_open():
|
||||
# Guardrails/MCP/credentials have non-CRUD verbs; deliberately not governed yet.
|
||||
def test_mcp_server_and_guardrail_admin_surfaces_are_governed():
|
||||
assert match_route("/v1/mcp/server/register").resource == "mcp_server"
|
||||
assert match_route("/v1/mcp/server/register").action == "write"
|
||||
assert match_route("/v1/mcp/server/health").action == "read"
|
||||
assert match_route("/guardrails/register").resource == "guardrail"
|
||||
assert match_route("/guardrails/register").action == "write"
|
||||
assert match_route("/guardrails/list").action == "read"
|
||||
# Collection-level operations carry no per-id field.
|
||||
assert match_route("/v1/mcp/server/register").id_fields == []
|
||||
|
||||
|
||||
def test_runtime_guardrail_verbs_stay_loud_open():
|
||||
# Applying/testing a guardrail is runtime, not management; deliberately not
|
||||
# governed by the control-plane RBAC map.
|
||||
for route in (
|
||||
"/guardrails/apply_guardrail",
|
||||
"/guardrails/register",
|
||||
"/v1/mcp/server/register",
|
||||
"/guardrails/test_custom_code",
|
||||
):
|
||||
assert match_route(route) is None
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue