Skip to content

reject user operations on rancher-managed resource quota and limit range resources - #1757

Open
andreas-kupries with Copilot wants to merge 6 commits into
mainfrom
copilot/create-webhook-fix-proposal
Open

reject user operations on rancher-managed resource quota and limit range resources#1757
andreas-kupries with Copilot wants to merge 6 commits into
mainfrom
copilot/create-webhook-fix-proposal

Conversation

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Issue:

rancher/rancher#54690

Companion PR r/rancher rancher/rancher#56780

backport 2.15.2 rancher/rancher#56773 - PR rancher/rancher#56801 - PR webhook 0.11 #1797
backport 2.14.6 rancher/rancher#56774 - PR rancher/rancher#56804 - PR webhook 0.10 #1798

Problem

The NRQR (Rancher-managed namespace ResourceQuota, identified by label resourcequota.management.cattle.io/default-resource-quota: true) was enforced only at namespace creation time. Any user with RBAC access to resourcequotas could subsequently edit the object directly, fully bypassing project-level enforcement.

The same is true for the LimitRange resource managed by Rancher.

Solution

Added validating webhooks for ResourceQuota and LimitRange objects.
The companion PR modifies Rancher to send its requests using the webhook bypass.
This means that the new validators see only user initiated requests, and only have to reject operations involving the marker label. IOW

  • Reject attempts to create resources bearing the marker label
  • Reject attempts to delete resources bearing the marker label
  • Reject attempts to change resources bearing the marker label
    • This includes changes attempting to strip the marker (demotion to unmanaged)
  • Reject attempts to add a marker to to un-marked resources (i.e. prevent promotion to managed)

Copilot AI changed the title fix(resourcequota): add webhook to enforce project quota limits on Rancher-managed ResourceQuota fix(resourcequota): enforce project quota limits on Rancher-managed namespace ResourceQuota Aug 11, 2026
Copilot AI requested a review from andreas-kupries August 11, 2026 12:35
@andreas-kupries

Copy link
Copy Markdown
Contributor

Issue:

rancher/rancher#54690

Problem

The NRQR (Rancher-managed namespace ResourceQuota, identified by label resourcequota.management.cattle.io/default-resource-quota: true) was enforced only at namespace creation time. Any user with RBAC access to resourcequotas could subsequently edit the object directly to raise its spec.hard limits beyond the owning project's quota, fully bypassing project-level enforcement.

The spec.hard should actually be less than the namespace's quota annotation, which is the origin for the resourcequota resource itself.

* **Quota-limit enforcement on create/update** — For any request touching an NRQR, looks up the namespace's `field.cattle.io/projectId` annotation, fetches the project, and rejects `spec.hard` values that exceed `spec.resourceQuota.limit` on the project. Uses the same field-name mapping already present in the project validator.

See above, this feels bogus.

* Writes via the `rancher-webhook-sudo` bypass SA skip the webhook entirely, consistent with the existing pattern for all Rancher-internal writes.

@andreas-kupries andreas-kupries left a comment

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.

Given the rancher-webhook-sudo bypass I wonder if we can simply reject anything with the marker label. Will have to verify that rancher resource quota code always uses the bypass for its own quota resource, i.e. that the validator will never see any ops for the NRQR. Best done using a local setup, with logging in the webhook, and no rejections during that test

Comment thread pkg/server/handlers.go Outdated
Comment thread pkg/resources/core/v1/resourcequota/validator.go Outdated
Comment thread pkg/resources/core/v1/resourcequota/validator.go Outdated
Comment thread pkg/resources/core/v1/resourcequota/validator.go Outdated
}

// Both objects have the marker label: validate that the new limits do not exceed the project quota.
return a.validateAgainstProjectQuota(newRQ)

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.

validate against the namespace annotation!?

Comment thread pkg/resources/core/v1/resourcequota/validator.go Outdated
@andreas-kupries

andreas-kupries commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Setting things up locally and using an always-accept validator for inspection I find that the rancher backend does not use the rancher-webhook-sudo bypass to avoid the webhook. I see this only for GlobalRole and RoleTemplates so far.

To make this PR suitable rancher's RQ operations have to be modified to use the bypass.
If we do the PR itself can be made much simpler as the validator will see only user requests.
We can simply reject anything which has the marker label in either the old or the new resource, or both.

@JonCrowther As the person who worked most recently on GR and RT, is my reasoning above sensible ? If yes, where in the GR/RT code would I find the setup of the webhook bypass ?

@andreas-kupries
andreas-kupries force-pushed the copilot/create-webhook-fix-proposal branch 2 times, most recently from e2d2fff to 146652e Compare August 19, 2026 14:42
@andreas-kupries
andreas-kupries marked this pull request as ready for review August 19, 2026 14:57
@andreas-kupries
andreas-kupries requested a review from a team as a code owner August 19, 2026 14:57
@andreas-kupries andreas-kupries added this to the 2.16 milestone Aug 19, 2026
@andreas-kupries andreas-kupries changed the title fix(resourcequota): enforce project quota limits on Rancher-managed namespace ResourceQuota reject user operatrions on rancher-managed resource quota and limit range resources Aug 20, 2026
@andreas-kupries
andreas-kupries requested a lite review from Copilot August 21, 2026 11:55

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

Adds validating webhooks to protect Rancher-managed ResourceQuota and LimitRange objects from user modifications.

Changes:

  • Registers validators for create, update, and delete operations.
  • Adds marker-label enforcement with Rancher bypass support.
  • Adds generated decoders, tests, documentation, and effective setting validation.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Reviewed changes Final comments
pkg/server/handlers.go Registers validators. No final comments.
pkg/resources/management.cattle.io/v3/setting/validator.go Validates effective setting values. moderate (2 votes): Add cases covering empty Value with valid and invalid Default values.
pkg/resources/core/v1/resourcequota/validator.go Validates managed ResourceQuota operations. moderate (2 votes): Correct the update-promotion message that incorrectly says the resource is being created (lines 102 and 106).
pkg/resources/core/v1/resourcequota/validator_test.go Tests ResourceQuota validation. nit (3 votes): Rename unmnaged to unmanaged.
pkg/resources/core/v1/resourcequota/Resourcequota.md Documents ResourceQuota validation. No final comments.
pkg/resources/core/v1/limitrange/validator.go Validates managed LimitRange operations. moderate (2 votes): Correct the update-promotion message that incorrectly says the resource is being created (lines 103 and 106).
pkg/resources/core/v1/limitrange/validator_test.go Tests LimitRange validation. nit (3 votes): Rename unmnaged to unmanaged.
pkg/resources/core/v1/limitrange/Limitrange.md Documents LimitRange validation. No final comments.
pkg/generated/objects/core/v1/objects.go Adds generated object decoders. No final comments.
pkg/codegen/main.go Includes new core types in code generation. No final comments.
docs.md Updates generated documentation. No final comments.
Suppressed comments (5)

pkg/resources/core/v1/limitrange/Limitrange.md:1

  • The filename uses Limitrange, but the Kubernetes API type is LimitRange. The docs generator uses the markdown filename as the resource heading (pkg/codegen/docs.go:64,124), so this typo propagates into docs.md; rename this file to LimitRange.md and regenerate the aggregate documentation.
## Validation Checks

pkg/resources/core/v1/limitrange/validator.go:110

  • The namespace controller deletes namespaced contents with DELETECOLLECTION, and Kubernetes runs the delete admission callback for each old object as system:serviceaccount:kube-system:namespace-controller. That identity is not the Rancher bypass, so a managed LimitRange hits this branch and is rejected, leaving its namespace stuck in Terminating. Exempt that system cleanup path while keeping direct user deletes denied.
	case admissionv1.Delete:
		if hasMarkerLabel(oldRq) {
			// Reject the user's attempt to delete the
			// rancher-managed quota resource
			return admission.ResponseBadRequest(

pkg/resources/core/v1/resourcequota/Resourcequota.md:1

  • The filename uses Resourcequota, but the Kubernetes API type is ResourceQuota. The docs generator uses the markdown filename as the resource heading (pkg/codegen/docs.go:64,124), so this typo propagates into docs.md; rename this file to ResourceQuota.md and regenerate the aggregate documentation.
## Validation Checks

pkg/resources/core/v1/resourcequota/validator.go:110

  • The namespace controller deletes namespaced contents with DELETECOLLECTION, and Kubernetes runs the delete admission callback for each old object as system:serviceaccount:kube-system:namespace-controller. That identity is not the Rancher bypass, so a managed quota hits this branch and is rejected, leaving its namespace stuck in Terminating. Exempt that system cleanup path while keeping direct user deletes denied.
		if hasMarkerLabel(oldRq) {
			// Reject the user's attempt to delete the
			// rancher-managed quota resource
			return admission.ResponseBadRequest(
				"users are forbidden from deleting resources managed by Rancher",

pkg/resources/management.cattle.io/v3/setting/validator.go:379

  • Now that this validation uses effectiveValue(s), an object with an empty Value and an invalid Default is rejected, but the error still reports s.Value (the empty string) rather than the value that was parsed. Use a local effective value for both parsing and the reported bad value.
	if _, err := time.ParseDuration(effectiveValue(s) + "s"); err != nil {

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pkg/resources/core/v1/limitrange/validator.go Outdated
Comment thread pkg/resources/core/v1/limitrange/validator_test.go Outdated
Comment thread pkg/resources/core/v1/resourcequota/validator.go Outdated
Comment thread pkg/resources/core/v1/resourcequota/validator_test.go Outdated
Comment thread pkg/resources/management.cattle.io/v3/setting/validator.go Outdated
@andreas-kupries andreas-kupries changed the title reject user operatrions on rancher-managed resource quota and limit range resources reject user operations on rancher-managed resource quota and limit range resources Aug 21, 2026
andreas-kupries and others added 6 commits August 21, 2026 14:44
….github.com>

boilerplate from copilot still present. unit tests and checks completely rewritten

added validators for resource quota to webhook
added docs, extended webhook codegen

the new validator rejects creation, edition, deletion of rancher managed resources.
the new validator further rejects promotion of unmanaged to managed resource, and vice versa.
the managed resource is recognized by its marker label.

the validator is written with the assumption that rancher requests are tagged
with webhook bypass and therefore do not reach the validator.

unit tests.

all of the above for limit range resources as well.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@andreas-kupries
andreas-kupries force-pushed the copilot/create-webhook-fix-proposal branch from 2b159f5 to e6d91a5 Compare August 21, 2026 12:45
@andreas-kupries

andreas-kupries commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

note to self:

pkg/resources/core/v1/limitrange/validator.go:110

The namespace controller deletes namespaced contents with DELETECOLLECTION, and Kubernetes runs the delete admission callback for each old object as system:serviceaccount:kube-system:namespace-controller. That identity is not the Rancher bypass, so a managed LimitRange hits this branch and is rejected, leaving its namespace stuck in Terminating. Exempt that system cleanup path while keeping direct user deletes denied.

trial

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 10 out of 11 changed files in this pull request and generated 2 comments.

Suppressed comments (1)

pkg/resources/management.cattle.io/v3/setting/validator.go:379

  • The auth-user-info-max-age-seconds tests always populate newSetting.Value, so they never exercise the new effectiveValue fallback to Default. Please add create/update cases with a valid and invalid default (while Value is empty) to verify the behavior this change introduces and prevent regressions.
	toValidate := effectiveValue(s)

), nil
}
case admissionv1.Delete:
if hasMarkerLabel(oldRq) {
}
case admissionv1.Delete:
if hasMarkerLabel(oldRq) {
// Reject the user's attempt to delete the
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants