kcp-dev / helm-charts

Helm chart repo for KCP
Apache License 2.0
5 stars 22 forks source link

bug: ServiceAccounts need `access` permission on their "home" workspace to pass front-proxy #103

Closed embik closed 2 months ago

embik commented 3 months ago

Describe the bug

When using ServiceAccounts to talk to kcp, we discovered that they behave differently depending on whether you are talking to a kcp server directly or to kcp-front-proxy. When talking to kcp itself, a ServiceAccount only needs permissions to access respective resources within their home workspace to function. kcp-front-proxy however adds the requirement to have the access verb on / in the "home" workspace that the ServiceAccount exists in. This does not exist when talking to kcp directly.

As per this Slack thread, ServiceAccounts should have implicit access to the workspace they have been created in.

Steps To Reproduce

  1. Create a workspace, e.g. via kubectl ws create wildwest --enter.
  2. Create a ServiceAccount:
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: example-controller
  3. Create and bind a ClusterRole giving access to all API resources (but not the / nonResourceURL):
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
    name: manager-role
    rules:
    - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
    ---  
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
    name: manager-rolebinding
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: manager-role
    subjects:
    - kind: ServiceAccount
    name: example-controller
    namespace: default
  4. Impersonate the ServiceAccount and attempt to get any resources while connecting to the kcp-front-proxy:
    $ kubectl get workspaces --as=system:serviceaccount:default:example-controller
    Error from server (Forbidden): workspaces.tenancy.kcp.io is forbidden: User "system:serviceaccount:default:example-controller" cannot list resource "workspaces" in API group "tenancy.kcp.io" at the cluster scope: access denied
  5. Use a kubeconfig that points to kcp directly and run the same command, observing that it returns the list of workspaces.
  6. Amend the ClusterRole from above with the following rule:
    - nonResourceURLs:
    - /
    verbs:
    - access
  7. Observe impersonating the ServiceAccount through kcp-front-proxy working.

Expected Behaviour

ServiceAccounts should not need the / nonResourceURL access permission when accessing a workspace through the front-proxy.

Additional Context

No response

embik commented 3 months ago

I think the difference is that front-proxy strips some (crucial) information from the request. This is kubectl auth whoami via front-proxy:

$ kubectl auth whoami --token='$(kubectl create token example-controller)'
ATTRIBUTE   VALUE
Username    system:serviceaccount:default:example-controller
Groups      [system:authenticated system:serviceaccounts system:serviceaccounts:default]

This is it via kcp directly:

$ kubectl auth whoami --token="$(kubectl create token example-controller)"
ATTRIBUTE                                           VALUE
Username                                            system:serviceaccount:default:example-controller
UID                                                 efa18c76-0d94-4308-9c4b-2cff46251e69
Groups                                              [system:serviceaccounts system:serviceaccounts:default system:authenticated]
Extra: authentication.kubernetes.io/cluster-name    [2ex1t1t6emfti3sc]
Extra: authentication.kubernetes.io/credential-id   [JTI=79cbeb53-d476-43df-99a8-70e66e038810]