-
Notifications
You must be signed in to change notification settings - Fork 198
Description
Bug description
We are using a single ArgoCD to roll out resources. Tenants get their own RBAC on ArgoCD so they can roll out only within their own tenant namespaces and see only their tenant resources in Argo. However, ArgoCD rolls out resource using it's own service account. To still make sure the namespaces created by ArgoCD still are attached to the appropriate tenant we've written a ClusterPolicy in kyverno that checks the name of the namespace against the known tenants and automatically set the appropriate label on the namespace. The problem is that the label is mutated onto the namespace resource, we get the following error:
Error from server: error when creating "tests/kyverno/apply-tenant-label/example-test.yml": admission webhook "namespaces.projectcapsule.dev" denied the request: namespace label "example" does not match owner reference ""
When we predefine the label onto the namespace the namespace resource is excepted by capsule and attached to the appropriate tenant.
How to reproduce
Steps to reproduce the behavior:
- Configure ArgoCD (and cluster-admin for testing purposes) as tenant administrator (using helm deployment)
manager:
options:
forceTenantPrefix: true
administrators:
- kind: ServiceAccount
name: system:serviceaccounts:argocd:argocd
- kind: Group
name: cluster-admins- Define a ClusterPolicy in kyverno that mutates a namespace automatically to be part of a tenant if it starts with a tenant prefix.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: apply-tenant-label
annotations:
policies.kyverno.io/title: Apply Capsule Tenant Label
policies.kyverno.io/category: Multi-Tenancy
policies.kyverno.io/minVersion: 1.6.0
policies.kyverno.io/description: |
This policy applies the capsule.clastix.io/tenant label to namespaces
that start with a tenant prefix. It fetches all existing tenants from the cluster
and enforces that namespaces with tenant prefixes are labeled appropriately.
spec:
background: false
rules:
- name: apply-tenant-label
match:
any:
- resources:
kinds:
- Namespace
operations:
- CREATE
- UPDATE
context:
- name: tenants
apiCall:
urlPath: "/apis/capsule.clastix.io/v1beta2/tenants"
jmesPath: items[].metadata.name
preconditions:
all:
- key: "{{ request.object.metadata.name | split(@, '-') | [0] }}"
operator: In
value: "{{ tenants }}"
mutate:
patchStrategicMerge:
metadata:
labels:
capsule.clastix.io/tenant: "{{ request.object.metadata.name | split(@, '-') | [0] }}"(this is verifies by running kyverno test with a kyverno test and on a cluster where the administrators are ignored by capsule, the label indeed get mutated on the resource)
- Example Tenant:
apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
labels:
kubernetes.io/metadata.name: example
managed-by: terraform-tenancy
spec:
cordoned: false
ingressOptions:
hostnameCollisionScope: Disabled
limitRanges: {}
networkPolicies: {}
owners:
- clusterRoles:
- capsule-namespace-provisioner
kind: Group
name: example-namespace-creator
- clusterRoles:
- capsule-namespace-deleter
kind: Group
name: example-namespace-creator
- clusterRoles:
- capsule-openshift-developer
- capsule-owner
kind: Group
name: example-openshift-developer
- clusterRoles:
- capsule-openshift-viewer
kind: Group
name: example-openshift-viewer
preventDeletion: false
resourceQuotas:
scope: Tenant- Apply (as a cluster admin) a namespace that starts with the
exampleprefix without the tenant label.
(Simulating what happens in ArgoCD)
apiVersion: v1
kind: Namespace
metadata:
name: example-testthis will result in
Error from server: error when creating "tests/kyverno/apply-tenant-label/example-test.yml": admission webhook "namespaces.projectcapsule.dev" denied the request: namespace label "example" does not match owner reference ""- Apply the same namespace with the label pre-applied before the admission control takes place:
apiVersion: v1
kind: Namespace
metadata:
name: example-test
labels:
capsule.clastix.io/tenant: exampleThis will be accepted and attached to the example tenant
Expected behavior
We expect the namespace mutated by kyverno to be accepted by capsule and attached to the appropriate tenant.
Logs
Logs of the kyverno controller after applying the namespace without a label:
2026-02-02T11:13:12Z TRC github.com/kyverno/kyverno/pkg/webhooks/resource/mutation/mutation.go:136 > mutation rules from policy applied successfully URLParams= clusterroles=["basic-user","calico-tiered-policy-passthrough","capsule-namespace-deleter","cluster-admin","cluster-status","console-extensions-reader","helm-chartrepos-viewer","self-access-reviewer","self-provisioner","system:basic-user","system:build-strategy-docker","system:build-strategy-jenkinspipeline","system:build-strategy-source","system:discovery","system:oauth-token-deleter","system:openshift:discovery","system:openshift:public-info-viewer","system:openshift:scc:restricted-v2","system:openshift:useroauthaccesstoken-manager","system:public-info-viewer","system:scope-impersonation","system:webhook"] gvk="/v1, Kind=Namespace" gvr={"group":"","resource":"namespaces","version":"v1"} kind=Namespace logger=webhooks/resource/mutate name=example-test6 namespace=example-test6 operation=CREATE policy=apply-tenant-label resource.gvk="/v1, Kind=Namespace" roles=["kube-system:extension-apiserver-authentication-reader","openshift-config-managed:console-public","openshift-config-managed:openshift-network-public-role","openshift-config-managed:system:openshift:oauth-servercert-trust","openshift-console-user-settings:user-settings-59fec644-9284-412a-be59-4dd12f3cc928-role","openshift:copied-csv-viewer","openshift:shared-resource-viewer"] rules=["apply-tenant-label"] uid=fd4b07e9-c01d-4e5b-a611-a9ba808f3b3a user={"extra":{"scopes.authorization.openshift.io":["user:full"]},"groups":["argocd-admins","cluster-admins","harbor-admins","openbao-admins","tenant-owners","system:authenticated:oauth","system:authenticated"],"uid":"59fec644-9284-412a-be59-4dd12f3cc928","username":"REDACTED"} v=2
The capsule controller log never seem to specify anything other that reconciliation of tenant resources and not admission. (Do I need to configure something for this)
Additional context
- Helm Chart version: 0.12.3
- Kyverno version: 0.16.2
- ArgoCD version: v3.2.3+2b6251d
- Openshift version: v1.32.8