Skip to content
Open
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
4 changes: 2 additions & 2 deletions kubernetes/helm/platform-api-helm-chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ config:
# Roles the mapping file defines, each a name and the scopes it grants.
# Only ap_admin is shipped here — the file-mode admin below names it.
# platform-api/resources/role-to-scope-mapping.yaml is the full sample set (ap_admin,
# ap_operator, ap_publisher, ap_subscriber, ap_viewer); copy the entries you
# need from it. An ap: scope the Platform API's OpenAPI spec does not declare
# ap_operator, ap_publisher, ap_developer, ap_subscriber, ap_viewer); copy the
# entries you need from it. An ap: scope the Platform API's OpenAPI spec does not declare
# fails startup; dp: scopes (API Portal) are checked for shape only.
# A resource-level :manage already covers that resource's subresources
# (each subresource operation lists the parent :manage in its own accepted
Expand Down
5 changes: 3 additions & 2 deletions platform-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ key silently ignored.
#### Role-Based Access Control (RBAC)

Per-route scope checks are enforced when `platform_api.auth.authorization.enabled = true`. The
shipped [`resources/role-to-scope-mapping.yaml`](resources/role-to-scope-mapping.yaml) defines five roles, each granting scopes in
shipped [`resources/role-to-scope-mapping.yaml`](resources/role-to-scope-mapping.yaml) defines six roles, each granting scopes in
both the `ap:*` (Platform API) and `dp:*` (Developer Portal) namespaces — one role covers a persona
across both components:

Expand All @@ -357,6 +357,7 @@ across both components:
| `ap_admin` | Platform administrator | Every resource and operation, both components |
| `ap_operator` | Platform operator / CI-CD service account | Gateways, deployments, subscription plans, key managers, webhooks; reads everything else |
| `ap_publisher` | API publisher | Full API/MCP/LLM lifecycle and its Developer Portal content; reads applications, subscriptions, plans |
| `ap_developer` | API developer | Creates, updates and deploys APIs/proxies in an existing project and calls them through its own application and keys; deletes the APIs and proxies it created, but not projects or secrets, and publishes no portal content |
| `ap_subscriber` | API consumer | Own applications, subscriptions and keys; reads the API/MCP catalog and plans |
| `ap_viewer` | Auditor | Read-only across both components |

Expand Down Expand Up @@ -410,7 +411,7 @@ roles = ["ap_admin"] # expanded via auth.authorization.rol
```

`roles` is a list, so a user whose persona spans two shipped roles names both rather than needing a
sixth role defined for the combination — `roles = ["ap_publisher", "ap_subscriber"]` grants the union
seventh role defined for the combination — `roles = ["ap_publisher", "ap_subscriber"]` grants the union
of the two, most-permissive wins, with duplicate scopes collapsed.

The issued token carries **both**: the expanded scopes as the `scope` claim, and the role names as the
Expand Down
38 changes: 38 additions & 0 deletions platform-api/resources/role-to-scope-mapping.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,44 @@ roles:
- dp:webhook_subscriber:manage
- dp:event:read

# API developer — builds APIs, MCP proxies and LLM proxies in an existing
# project and calls them through its own application; owns the APIs and
# proxies it creates but cannot delete projects or secrets.
- name: ap_developer
Comment thread
Thushani-Jayasekera marked this conversation as resolved.
scopes:
# Platform API
- ap:organization:read
- ap:project:read
- ap:rest_api:manage
- ap:mcp_proxy:manage
- ap:llm_proxy:manage
- ap:llm_provider:read
- ap:llm_template:read
- ap:gateway:read
- ap:gateway:manifest:read
- ap:gateway_custom_policy:read
- ap:secret:create
- ap:secret:read
- ap:secret:update
Comment on lines +123 to +125

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we just provide ap:secret:read only?

- ap:application:manage
- ap:subscription:manage
- ap:subscription_plan:read
- ap:api_key:read
- dp:application:manage
- dp:application_key:manage
- dp:application_key:revoke
- dp:subscription:manage
- dp:api_key:manage
- dp:mcp_server_key:manage
- dp:organization:read
- dp:organization_content:read
- dp:api:read
- dp:mcp_server:read
- dp:mcp_server_content:read
- dp:subscription_plan:read
- dp:view:read
- dp:label:read
- dp:event:read
# Platform operator / CI-CD service account — runs gateways, deployments,
# subscription plans, key managers and webhooks; reads everything else.
- name: ap_operator
Expand Down
5 changes: 5 additions & 0 deletions portals/ai-workspace/bff/internal/auth/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ func (o *OIDC) Close() {
o.closeOnce.Do(func() { close(o.done) })
}

// TokenEndpoint is the endpoint discovered from the issuer. Exposed so a token
// exchange configured without an explicit endpoint override can post to the same
// IDP the user logged in to, without repeating discovery.
func (o *OIDC) TokenEndpoint() string { return o.disco.TokenEndpoint }

func fetchDiscovery(ctx context.Context, client *http.Client, issuer string) (discoveryDoc, error) {
u := strings.TrimRight(issuer, "/") + "/.well-known/openid-configuration"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
Expand Down
Loading
Loading