Add denylist for system namespaces in targetNamespace validation#3507
Add denylist for system namespaces in targetNamespace validation#3507mvanhorn wants to merge 2 commits into
Conversation
CommonSpec.validate() previously accepted any non-empty targetNamespace on Kubernetes, allowing components to be installed into well-known system namespaces such as kube-system, kube-public, kube-node-lease, or default. Add a defense-in-depth denylist that rejects those four reserved namespaces on both Kubernetes and OpenShift, while preserving the existing OpenShift-only openshift-operators rejection. Because validate() is the shared method called by every component validator, the denylist applies to all of them with no caller changes. Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
TektonResult.Validate calls TektonResultSpec.validate, which did not call the embedded CommonSpec.validate, so the new system-namespace denylist (and the pre-existing empty-field check) was bypassed for TektonResult. Wire the common validation into TektonResultSpec.validate so the denylist is enforced consistently across every CommonSpec-backed component. Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
|
||
| func (ta *CommonSpec) validate(path string) *apis.FieldError { | ||
| var errs *apis.FieldError | ||
| targetNamespace := ta.GetTargetNamespace() |
There was a problem hiding this comment.
this is cleaner than calling GetTargetNamespace() multile time
| }, | ||
| Spec: TektonResultSpec{ | ||
| CommonSpec: CommonSpec{ | ||
| TargetNamespace: "kube-system", |
There was a problem hiding this comment.
this skips validation kube-public, kube-node-lease, default, and the OpenShift openshift-operators case, without any failing test at the TektonResult level.
|
@mvanhorn thank you for you contribution, would you add the validation to pkg/apis/operator/v1alpha1/tektonscheduler_validation.go:27–41 |
There was a problem hiding this comment.
Pull request overview
Adds defense-in-depth validation to prevent installing Tekton components into well-known Kubernetes system namespaces via spec.targetNamespace, and ensures TektonResult applies the shared CommonSpec validation path so the denylist (and existing empty check) are enforced consistently.
Changes:
- Add a reserved system namespace denylist (
kube-system,kube-public,kube-node-lease,default) toCommonSpec.validate()across platforms, while preserving the OpenShift-onlyopenshift-operatorsrestriction. - Ensure
TektonResultSpec.validate()invokes the embeddedCommonSpec.validate()so TektonResult no longer bypasses shared validation. - Extend unit tests to cover denylisted namespaces and the TektonResult validation path.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| pkg/apis/operator/v1alpha1/common_validation.go | Adds reserved namespace denylist enforcement to shared CommonSpec validation. |
| pkg/apis/operator/v1alpha1/common_validation_test.go | Updates CommonSpec validation tests for reserved namespace denylist (Kubernetes + one OpenShift case). |
| pkg/apis/operator/v1alpha1/tektonresult_validation.go | Ensures TektonResultSpec runs shared CommonSpec validation. |
| pkg/apis/operator/v1alpha1/tektonresult_validation_test.go | Adds a test covering TektonResult’s denylisted targetNamespace validation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {name: "ns-openshift-operators", targetNamespace: "openshift-operators", err: "", isOpenshift: false}, | ||
| {name: "openshift-ns-default", targetNamespace: "default", err: "invalid value: default: spec.targetNamespace\n'default' is a reserved system namespace and is not allowed", isOpenshift: true}, | ||
| {name: "openshift-ns-openshift-operators", targetNamespace: "openshift-operators", err: "invalid value: openshift-operators: spec.targetNamespace\n'openshift-operators' namespace is not allowed", isOpenshift: true}, | ||
| {name: "openshift-ns-openshift-pipelines", targetNamespace: "openshift-pipelines", err: "", isOpenshift: true}, |
Changes
CommonSpec.validate()previously accepted any non-emptytargetNamespaceon Kubernetes, so a component could be told to install into a well-known system namespace such askube-system,kube-public,kube-node-lease, ordefault. On OpenShift onlyopenshift-operatorswas blocked.This adds a defense-in-depth denylist that rejects those four reserved system namespaces on both Kubernetes and OpenShift, while preserving the existing OpenShift-only
openshift-operatorsrejection. Becausevalidate()is the shared method called by every component validator, the denylist applies across components with no caller changes.While wiring this up I found that
TektonResultbypassed the shared validation entirely:TektonResult.ValidatecallsTektonResultSpec.validate, which never invoked the embeddedCommonSpec.validate. This change also calls the common validation fromTektonResultSpec.validateso the denylist (and the pre-existing empty-field check) is enforced consistently forTektonResulttoo.Tests cover the happy path, each denied namespace on both platforms, the preserved
openshift-operatorsrejection, the empty-namespace case, and theTektonResultpath.Fixes #3248
Submitter Checklist
These are the criteria that every PR should meet, please check them off as you
review them:
make test lintbefore submitting a PRSee the contribution guide for more details.
Release Notes