Skip to content

feat: improve SSAR and SSRR performance and usability#1069

Open
lukasboettcher wants to merge 1 commit into
projectcapsule:mainfrom
lukasboettcher:fix/slow-auth-response
Open

feat: improve SSAR and SSRR performance and usability#1069
lukasboettcher wants to merge 1 commit into
projectcapsule:mainfrom
lukasboettcher:fix/slow-auth-response

Conversation

@lukasboettcher

@lukasboettcher lukasboettcher commented Jul 7, 2026

Copy link
Copy Markdown

This PR lets authorizationMiddleware requests pass through to the upstream apiserver if bearer token auth is used. The SSAR response gets modified to include cluster-wide permissions for namespaced resources.
Additionally this PR lets non tenant owners get namespace list permissions from GlobalProxySettings.
This has a few advantages:

  • all upstream SSAR/SSRR permissions are kept, capsule-proxy only appends the permissions it additionally grants
  • the response times are drastically improved for users with lots of groups / roles in their id token claims
  • the SSAR response correctly display the permissions for kubectl get pods -A
  • non-owners can be explicitly assigned cluster scoped namespace permissions without reliance on the rolebinding reflector

Reasoning: we use AKS with capsule/-proxy. In AKS clusters it is common for users to have more than 300 groups assigned in Entra ID for large tenants. If we let capsule-proxy impersonate each group of the user's token, the upstream apiserver needs to perform the permission review for each impersonated group individually.
This is extremely slow and causes timeouts in lots of k8s clients.

Could be related to #989

Example for a user with ~300 groups:

before

$ time kubectl auth can-i --list
Resources                          Non-Resource URLs   Resource Names   Verbs
namespaces                         []                  []               [List]
nodes./v1                          []                  []               [list]
storageclasses.storage.k8s.io/v1   []                  []               [list]

real    0m14.439s
user    0m0.279s
sys     0m0.082s

$ kubectl auth can-i list pods --all-namespaces
no

$ kubectl get ns
test-1

after

$ time kubectl auth can-i --list
Resources                                       Non-Resource URLs   Resource Names   Verbs
namespaces                                      []                  []               [create patch list]
selfsubjectreviews.authentication.k8s.io        []                  []               [create]
selfsubjectaccessreviews.authorization.k8s.io   []                  []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                  []               [create]
                                                [/api/*]            []               [get]
                                                [/api]              []               [get]
                                                [/apis/*]           []               [get]
                                                [/apis]             []               [get]
                                                [/healthz]          []               [get]
                                                [/healthz]          []               [get]
                                                [/livez]            []               [get]
                                                [/livez]            []               [get]
                                                [/openapi/*]        []               [get]
                                                [/openapi]          []               [get]
                                                [/readyz]           []               [get]
                                                [/readyz]           []               [get]
                                                [/version/]         []               [get]
                                                [/version/]         []               [get]
                                                [/version]          []               [get]
                                                [/version]          []               [get]
nodes./v1                                       []                  []               [list]
storageclasses.storage.k8s.io/v1                []                  []               [list]

real    0m0.584s
user    0m0.295s
sys     0m0.079s

$ kubectl auth can-i list pods --all-namespaces
yes

$ kubectl get ns
asdf-1
test-1

config:

values:
          disableCaching: true
          extraArgs:
            - "--feature-gates=ProxyClusterScoped=true"
            - "--feature-gates=ProxyAllNamespaced=true"
---
apiVersion: capsule.clastix.io/v1beta1
kind: GlobalProxySettings
metadata:
  name: global-proxy-settings
spec:
  rules:
    - subjects:
        - name: uuid
          kind: Group
      clusterResources:
        - apiGroups:
            - "storage.k8s.io/v1"
          resources:
            - "storageclasses"
          operations:
            - List
          selector:
            matchExpressions:
              - key: private
                operator: DoesNotExist
        - apiGroups:
            - "/v1"
          resources:
            - "nodes"
          operations:
            - List
          selector:
            matchExpressions:
              - key: private
                operator: DoesNotExist
        - apiGroups:
            - "/v1"
          resources:
            - "namespaces"
          operations:
            - List
          selector:
            matchLabels:
              capsule.clastix.io/tenant: asdf
---
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: test
spec:
  owners:
    - name: uuid
      kind: Group
---
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: asdf
spec:
  additionalRoleBindings:
  - clusterRoleName: edit
    subjects:
    - name: uuid
      kind: Group

Copilot AI review requested due to automatic review settings July 7, 2026 21:21
@lukasboettcher lukasboettcher changed the title fix: improve SSAR SSRR response times for bearerTokens fix: improve SAR SRR response times Jul 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves performance and fidelity of Kubernetes SelfSubjectAccessReview (SSAR) / SelfSubjectRulesReview (SSRR) handling by forwarding self-review requests to the upstream API server using the caller’s bearer token when available, then appending capsule-proxy-granted permissions (instead of impersonating each group).

Changes:

  • Add bearer-token detection and, for SSAR/SSRR paths, proxy upstream using the caller’s bearer token to avoid per-group impersonation overhead.
  • Adjust authorization mutation logic to (a) avoid panics on nil attributes, (b) use lowercase RBAC verbs where appropriate, and (c) merge SSRR rules instead of overwriting upstream results.
  • Add unit tests covering SSRR merge behavior and SSAR namespace list behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
internal/webserver/webserver.go Forward SSAR/SSRR upstream directly when bearer token is present; make decoding/mutation flow more defensive.
internal/authorization/middleware.go Refine SSAR/SSRR mutation: safer attribute handling, merge behavior for SSRR, and clearer “granted” status updates.
internal/authorization/middleware_test.go Add tests validating SSRR merge semantics and SSAR grant behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/webserver/webserver.go
Comment thread internal/webserver/webserver.go Outdated
@lukasboettcher lukasboettcher force-pushed the fix/slow-auth-response branch 2 times, most recently from d2b0e54 to c9fa5a1 Compare July 8, 2026 13:38
@lukasboettcher lukasboettcher changed the title fix: improve SAR SRR response times feat: improve SSAR and SSRR performance and usability Jul 8, 2026
@lukasboettcher lukasboettcher requested a review from Copilot July 8, 2026 13:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread internal/webserver/webserver.go
Comment thread internal/webserver/webserver.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread internal/webserver/webserver.go
Comment thread internal/webserver/webserver.go Outdated
Comment thread internal/authorization/middleware.go
@lukasboettcher lukasboettcher force-pushed the fix/slow-auth-response branch from f84c093 to efcdd8c Compare July 8, 2026 16:18
Signed-off-by: Lukas Boettcher <1340215+lukasboettcher@users.noreply.github.com>
@lukasboettcher lukasboettcher force-pushed the fix/slow-auth-response branch from efcdd8c to 18752f9 Compare July 8, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants