Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion deployments/charts/osmo/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1644,7 +1644,6 @@ configuration:
- app:*
- auth:Token
- credentials:*
- mcp:Access
- pool:List
- profile:Read
- profile:Update
Expand Down
1 change: 0 additions & 1 deletion deployments/charts/service/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@ services:
- "app:*"
- "auth:Token"
- "credentials:*"
- "mcp:Access"
- "pool:List"
- "profile:Read"
- "profile:Update"
Expand Down
4 changes: 2 additions & 2 deletions src/service/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ failures.
## Deployment validation

The MCP smoke target requires an MCP-enabled deployment with JWT
authentication. Its token needs `mcp:Access`, `profile:Read`, and
`workflow:Create` for `OETF_POOL`.
authentication. Its token needs `profile:Read` and `workflow:Create`
for `OETF_POOL`.

```bash
bazel run //test/oetf:run -- --env <mcp-enabled-env> --tags mcp
Expand Down
1 change: 0 additions & 1 deletion src/utils/connectors/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -4824,7 +4824,6 @@ def merge_default_role_policies(existing_role: Role, default_role: Role) -> bool
'app:*',
'auth:Token',
'credentials:*',
'mcp:Access',
'pool:List',
'profile:Read',
'profile:Update',
Expand Down
1 change: 0 additions & 1 deletion src/utils/connectors/tests/test_default_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ def test_osmo_user_default_role_allows_only_workflow_read_list_on_all_pools(self
'app:*',
'auth:Token',
'credentials:*',
'mcp:Access',
'pool:List',
'profile:Read',
'profile:Update',
Expand Down
10 changes: 0 additions & 10 deletions src/utils/roles/action_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const (
resourceTypeConfig = "config"
resourceTypeProfile = "profile"
resourceTypeWorkflow = "workflow"
resourceTypeMCP = "mcp"
resourceTypeInternal = "internal"
)

Expand All @@ -60,7 +59,6 @@ const (
ResourceTypeConfig ResourceType = resourceTypeConfig
ResourceTypeProfile ResourceType = resourceTypeProfile
ResourceTypeWorkflow ResourceType = resourceTypeWorkflow
ResourceTypeMCP ResourceType = resourceTypeMCP
ResourceTypeInternal ResourceType = resourceTypeInternal
)

Expand Down Expand Up @@ -111,9 +109,6 @@ const (
ActionAuthRefresh = resourceTypeAuth + ":Refresh"
ActionAuthToken = resourceTypeAuth + ":Token"

// MCP actions
ActionMCPAccess = resourceTypeMCP + ":Access"

// System actions (public)
ActionSystemHealth = resourceTypeSystem + ":Health"
ActionSystemVersion = resourceTypeSystem + ":Version"
Expand Down Expand Up @@ -288,11 +283,6 @@ var ActionRegistry = map[string][]EndpointPattern{
{Path: "/api/auth/user/*/access_token/*", Methods: []string{"*"}},
},

// ==================== MCP ====================
ActionMCPAccess: {
{Path: "/mcp", Methods: []string{"GET", "POST", "DELETE"}},
},

// ==================== SYSTEM (PUBLIC) ====================
ActionSystemHealth: {
{Path: "/health", Methods: []string{"*"}},
Expand Down
84 changes: 0 additions & 84 deletions src/utils/roles/action_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,90 +42,6 @@ func TestGetAllActions(t *testing.T) {
}
}

func TestMCPActionRegistry(t *testing.T) {
tests := []struct {
name string
path string
method string
wantAction string
}{
{name: "GET", path: "/mcp", method: "GET", wantAction: ActionMCPAccess},
{name: "POST", path: "/mcp", method: "POST", wantAction: ActionMCPAccess},
{name: "DELETE", path: "/mcp", method: "DELETE", wantAction: ActionMCPAccess},
{name: "unsupported PUT", path: "/mcp", method: "PUT"},
{name: "unsupported PATCH", path: "/mcp", method: "PATCH"},
{name: "unsupported OPTIONS", path: "/mcp", method: "OPTIONS"},
{name: "nested path", path: "/mcp/tools", method: "GET"},
{name: "adjacent path", path: "/mcp-extra", method: "GET"},
{
name: "protected resource metadata path",
path: "/.well-known/oauth-protected-resource/mcp",
method: "GET",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
action, resource := ResolvePathToAction(
context.Background(), tt.path, tt.method, nil,
)
if action != tt.wantAction {
t.Errorf("ResolvePathToAction(%q, %q) action = %q, want %q",
tt.path, tt.method, action, tt.wantAction)
}
if resource != "" {
t.Errorf("ResolvePathToAction(%q, %q) resource = %q, want empty",
tt.path, tt.method, resource)
}
})
}
}

func TestMCPActionAuthorization(t *testing.T) {
osmoUser := &Role{
Name: "osmo-user",
Policies: []RolePolicy{
{
Effect: EffectAllow,
Actions: RoleActions{{Action: ActionMCPAccess}},
Resources: []string{"*"},
},
},
}
roleWithoutMCP := &Role{
Name: "role-without-mcp",
Policies: []RolePolicy{
{
Effect: EffectAllow,
Actions: RoleActions{{Action: ActionProfileRead}},
Resources: []string{"*"},
},
},
}

for _, method := range []string{"GET", "POST", "DELETE"} {
t.Run(method, func(t *testing.T) {
result := CheckRolesAccess(
context.Background(), []*Role{osmoUser}, "/mcp", method, nil,
)
if !result.Allowed {
t.Fatalf("osmo-user should be allowed to %s /mcp", method)
}
if result.MatchedAction != ActionMCPAccess {
t.Errorf("MatchedAction = %q, want %q", result.MatchedAction, ActionMCPAccess)
}

result = CheckRolesAccess(
context.Background(), []*Role{roleWithoutMCP}, "/mcp", method, nil,
)
if result.Allowed {
t.Errorf("role without %s should not be allowed to %s /mcp",
ActionMCPAccess, method)
}
})
}
}

func TestMatchMethodRegistry(t *testing.T) {
tests := []struct {
name string
Expand Down