Skip to content

fix(webhook): pre-filter BindDefinitions by RoleBindings via field index#275

Open
MaxRink wants to merge 2 commits intotelekom:mainfrom
MaxRink:fix/unscoped-bd-list
Open

fix(webhook): pre-filter BindDefinitions by RoleBindings via field index#275
MaxRink wants to merge 2 commits intotelekom:mainfrom
MaxRink:fix/unscoped-bd-list

Conversation

@MaxRink
Copy link
Copy Markdown
Collaborator

@MaxRink MaxRink commented Apr 15, 2026

Summary

authorizeViaBindDefinitions in the namespace validating webhook performed an unscoped client.List of all BindDefinitions in the cluster on every namespace CREATE/UPDATE/DELETE admission call. BindDefinitions that only have clusterRoleBindings (no namespace-scoped bindings) were fetched and then immediately skipped inside the iteration loop — wasted work proportional to their count.

Changes

  • pkg/indexer/indexer.go: Add BindDefinitionHasRoleBindingsField constant, BindDefinitionHasRoleBindingsTrue sentinel, and BindDefinitionHasRoleBindingsFunc extractor. Register the new index in SetupIndexes.
  • internal/webhook/authorization/namespace_validating_webhook.go: Pass client.MatchingFields{indexer.BindDefinitionHasRoleBindingsField: indexer.BindDefinitionHasRoleBindingsTrue} to the List call, restricting the result set to BindDefinitions with at least one RoleBinding.

Since client.List is served from the controller-runtime informer cache, the field index lookup is an in-process O(1) hash lookup rather than an additional API call. Cluster-only BindDefinitions are excluded before iteration.

Testing

go build ./...
go test ./pkg/indexer/...

All tests pass.

Risk

Low — the SetupIndexes call must be invoked before the webhook starts (it already is in cmd/main.go). If the index is not registered (e.g. standalone webhook without SetupIndexes), the List will return a field-index error. This is the same pattern used by the existing WebhookAuthorizerHasNamespaceSelectorField index.

authorizeViaBindDefinitions listed ALL BindDefinitions cluster-wide on
every namespace admission request with no server-side filter, causing
O(N) in-memory scans where N is total BindDefinitions in the cluster.
BindDefinitions with only ClusterRoleBindings (cluster-only) were still
iterated only to be skipped inside the loop.

Add a new field index BindDefinitionHasRoleBindingsField and a matching
extractor BindDefinitionHasRoleBindingsFunc to pkg/indexer. Use
client.MatchingFields to restrict the List to only BindDefinitions that
carry at least one RoleBinding, eliminating cluster-only entries from the
webhook hot path and reducing scan cost to O(K) where K <= N.
@MaxRink MaxRink requested a review from a team as a code owner April 15, 2026 12:03
Copilot AI review requested due to automatic review settings April 15, 2026 12:03
Copy link
Copy Markdown

Copilot AI left a comment

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 optimizes the namespace validating webhook’s BindDefinition authorization path by avoiding a full cluster-wide BindDefinition list on every namespace admission request, instead leveraging a controller-runtime cache field index to pre-filter candidates.

Changes:

  • Added a BindDefinition field index (.spec.hasRoleBindings) and extractor to identify BindDefinitions that contain namespace-scoped RoleBindings.
  • Registered the new index in indexer.SetupIndexes.
  • Updated the namespace validating webhook to List BindDefinitions using client.MatchingFields so only namespace-scoped BindDefinitions are fetched from cache.

Reviewed changes

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

File Description
pkg/indexer/indexer.go Adds and registers a new field index + extractor for “has RoleBindings” filtering.
internal/webhook/authorization/namespace_validating_webhook.go Uses the new field index to restrict BindDefinition listing to namespace-scoped candidates.

Comment thread internal/webhook/authorization/namespace_validating_webhook.go
Comment thread pkg/indexer/indexer.go
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