diff --git a/e2e/namespace_hijacking_test.go b/e2e/namespace_hijacking_test.go index e628b49b..038998cc 100644 --- a/e2e/namespace_hijacking_test.go +++ b/e2e/namespace_hijacking_test.go @@ -54,7 +54,7 @@ var _ = Describe("creating several Namespaces for a Tenant", Label("namespace"), }) - It("Can't hijack offlimits namespace", func() { + It("Can't hijack offlimits namespace (Ownerreferences)", func() { tenant := &capsulev1beta2.Tenant{} Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed()) @@ -72,6 +72,40 @@ var _ = Describe("creating several Namespaces for a Tenant", Label("namespace"), } }) + It("Can't hijack offlimits namespace (Labels)", func() { + tenant := &capsulev1beta2.Tenant{} + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed()) + + // Get the namespace + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: kubeSystem.GetName()}, kubeSystem)).Should(Succeed()) + + for _, owner := range tnt.Spec.Owners { + cs := ownerClient(owner) + + patch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`, "capsule.clastix.io/tenant", tenant.GetName())) + + _, err := cs.CoreV1().Namespaces().Patch(context.TODO(), kubeSystem.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + Expect(err).To(HaveOccurred()) + } + }) + + It("Can't hijack offlimits namespace (Annotations)", func() { + tenant := &capsulev1beta2.Tenant{} + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed()) + + // Get the namespace + Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: kubeSystem.GetName()}, kubeSystem)).Should(Succeed()) + + for _, owner := range tnt.Spec.Owners { + cs := ownerClient(owner) + + patch := []byte(fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, "capsule.clastix.io/tenant", tenant.GetName())) + + _, err := cs.CoreV1().Namespaces().Patch(context.TODO(), kubeSystem.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + Expect(err).To(HaveOccurred()) + } + }) + It("Owners can create and attempt to patch new namespaces but patches should not be applied", func() { for _, owner := range tnt.Spec.Owners { cs := ownerClient(owner) diff --git a/pkg/webhook/namespace/validation/patch.go b/pkg/webhook/namespace/validation/patch.go index 0f30858e..26a0dfcb 100644 --- a/pkg/webhook/namespace/validation/patch.go +++ b/pkg/webhook/namespace/validation/patch.go @@ -66,14 +66,14 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder admission.Decoder, reco return &response } - if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) { - recorder.Eventf(tnt, corev1.EventTypeWarning, "NamespacePatch", e) - response := admission.Denied(e) - - return &response + if utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) { + return nil } } - return nil + recorder.Eventf(ns, corev1.EventTypeWarning, "NamespacePatch", e) + response := admission.Denied(e) + + return &response } }