Skip to content

bug: access denied for permissionClaim on tenancy.kcp.io resources #3840

@ljmsc

Description

@ljmsc

Describe the bug

I have a kcp setup with three workspaces (root, provider and consumer). In the provider workspace I have an APIExport which looks like this:

apiVersion: apis.kcp.io/v1alpha2
kind: APIExport
metadata:
  name: example.com
spec:
  resources:
    - group: example.com
      name: testresources
      schema: provider-v20260217.testresources.example.com
      storage:
        crd: {}
  permissionClaims:
    - group: ""
      resource: events
      verbs: ["list", "watch", "get"]
    - group: tenancy.kcp.io
      resource: workspaces
      identityHash: <identityHash>
      verbs: ["get", "list", "watch"]

For the controller which should access the resulting virtual workspace, I have an service account (also in the provider workspace) and a role + rolebinding to grant permission to the content of the virtual workspace.

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sa-role
rules:
  - apiGroups: ["apis.kcp.io"]
    verbs: ["list", "watch", "get"]
    resources:
      - apiexportendpointslices
  - apiGroups: ["apis.kcp.io"]
    verbs: ["*"]
    resources: ["apiexports/content"]
    resourceNames: ["example.com"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: sa-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: sa-role
subjects:
  - kind: ServiceAccount
    name: provider-sa
    namespace: provider-ns

In the consumer workspace I have an APIBinding which looks like this:

apiVersion: apis.kcp.io/v1alpha2
kind: APIBinding
metadata:
  name: example.com
spec:
  reference:
    export:
      name: example.com
      path: "root:provider"
  permissionClaims:
    - group: ""
      resource: events
      verbs: ["list", "watch", "get"]
      selector:
        matchAll: true
      state: Accepted
    - group: tenancy.kcp.io
      resource: workspaces
      identityHash: <identityHash>
      verbs: ["get", "list", "watch"]
      selector:
        matchAll: true
      state: Accepted

When I try to access the virtual workspace with the service account I can access the resources defined in the APIExport but not the ones from the permissionClaim in the group tenancy.kcp.io.

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "workspaces.tenancy.kcp.io is forbidden: User \"system:serviceaccount:provider-ns:provider-sa\" cannot list resource \"workspaces\" in API group \"tenancy.kcp.io\" at the cluster scope: access denied",
  "reason": "Forbidden",
  "details": {
    "group": "tenancy.kcp.io",
    "kind": "workspaces"
  },
  "code": 403
}

If I use the "admin-token", I can access everything just fine. Do I need to extend the role / rolebinding somehow?

Steps To Reproduce

Create a APIExport with an permissionClaim to workspaces.tenancy.kcp.io in an extra workspace.

Expected Behaviour

I can access the resource information from workspaces.tenancy.kcp.io since I granted access to the apiexports/content resource in the provider workspace.

Additional Context

For debugging I use the following command:

$ curl -k -XGET "https://kcp:8443/services/apiexport/<provider workspace cluster id>/example.com/clusters/*/apis/tenancy.kcp.io/v1alpha1/workspaces" \
--header "Authorization: Bearer <sa-token>"

Metadata

Metadata

Labels

kind/bugCategorizes issue or PR as related to a bug.priority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next release.

Type

No type

Projects

Status

Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions