From 819cfcdf516598a8a77647b6a152b6a8c097190b Mon Sep 17 00:00:00 2001 From: William Lightning Date: Thu, 13 Sep 2018 11:11:29 -0700 Subject: [PATCH 01/10] #872 Add certificates and issuers to aggregated RBAC for view, edit and admin ClusterRoles. Signed-off-by: William Lightning --- .../charts/cert-manager/templates/rbac.yaml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/contrib/charts/cert-manager/templates/rbac.yaml b/contrib/charts/cert-manager/templates/rbac.yaml index d6503c871..c05376631 100644 --- a/contrib/charts/cert-manager/templates/rbac.yaml +++ b/contrib/charts/cert-manager/templates/rbac.yaml @@ -36,4 +36,37 @@ subjects: - name: {{ template "cert-manager.serviceAccountName" . }} namespace: {{ .Release.Namespace | quote }} kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-view + labels: + app: {{ template "cert-manager.name" . }} + chart: {{ template "cert-manager.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cert-manager.fullname" . }}-edit + labels: + app: {{ template "cert-manager.name" . }} + chart: {{ template "cert-manager.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] {{- end -}} From 6e66f5eedce1e7f95a0844a6956f6c1e6f8f4392 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Thu, 13 Sep 2018 13:58:38 -0700 Subject: [PATCH 02/10] Bump cert-manager helm chart version to v0.6.0-dev.1 Signed-off-by: William Lightning --- contrib/charts/cert-manager/Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/charts/cert-manager/Chart.yaml b/contrib/charts/cert-manager/Chart.yaml index ece783c73..c599221ad 100644 --- a/contrib/charts/cert-manager/Chart.yaml +++ b/contrib/charts/cert-manager/Chart.yaml @@ -1,6 +1,6 @@ name: cert-manager -version: v0.6.0-dev.0 -appVersion: v0.6.0-dev.0 +version: v0.6.0-dev.1 +appVersion: v0.6.0-dev.1 description: A Helm chart for cert-manager home: https://github.com/jetstack/cert-manager keywords: From 9b6685825eb83dbd1e767fabf0de870306e88415 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Thu, 13 Sep 2018 14:06:39 -0700 Subject: [PATCH 03/10] Update deploy manifests with chart cert-manager-v0.6.0-dev.1 Signed-off-by: William Lightning --- contrib/manifests/cert-manager/with-rbac.yaml | 47 ++++++++++++++++--- .../manifests/cert-manager/without-rbac.yaml | 8 ++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/contrib/manifests/cert-manager/with-rbac.yaml b/contrib/manifests/cert-manager/with-rbac.yaml index fe371d2ff..e3d5ae725 100644 --- a/contrib/manifests/cert-manager/with-rbac.yaml +++ b/contrib/manifests/cert-manager/with-rbac.yaml @@ -18,7 +18,7 @@ metadata: namespace: "cert-manager" labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller --- @@ -31,7 +31,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -55,7 +55,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -75,7 +75,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -93,7 +93,7 @@ metadata: name: cert-manager labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller rules: @@ -113,7 +113,7 @@ metadata: name: cert-manager labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller roleRef: @@ -125,6 +125,39 @@ subjects: namespace: "cert-manager" kind: ServiceAccount --- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cert-manager-view + labels: + app: cert-manager + chart: cert-manager-v0.6.0-dev.1 + release: cert-manager + heritage: Tiller + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: cert-manager-edit + labels: + app: cert-manager + chart: cert-manager-v0.6.0-dev.1 + release: cert-manager + heritage: Tiller + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: ["certmanager.k8s.io"] + resources: ["certificates", "issuers"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] +--- # Source: cert-manager/templates/deployment.yaml apiVersion: apps/v1beta1 kind: Deployment @@ -133,7 +166,7 @@ metadata: namespace: "cert-manager" labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: diff --git a/contrib/manifests/cert-manager/without-rbac.yaml b/contrib/manifests/cert-manager/without-rbac.yaml index 8dad7b541..c6ce23ea5 100644 --- a/contrib/manifests/cert-manager/without-rbac.yaml +++ b/contrib/manifests/cert-manager/without-rbac.yaml @@ -19,7 +19,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -43,7 +43,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -63,7 +63,7 @@ metadata: "helm.sh/hook": crd-install labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: @@ -82,7 +82,7 @@ metadata: namespace: "cert-manager" labels: app: cert-manager - chart: cert-manager-v0.6.0-dev.0 + chart: cert-manager-v0.6.0-dev.1 release: cert-manager heritage: Tiller spec: From 57bf83dea493069b67762128e4c83d9c1a6602d6 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Fri, 14 Sep 2018 16:12:06 -0700 Subject: [PATCH 04/10] Add basic tests for certificate permissions Signed-off-by: William Lightning --- Gopkg.lock | 2 + test/e2e/certificate/BUILD.bazel | 5 + test/e2e/certificate/certificate_rbac.go | 159 +++++++++++++++++++++++ test/e2e/framework/framework.go | 5 + 4 files changed, 171 insertions(+) create mode 100644 test/e2e/certificate/certificate_rbac.go diff --git a/Gopkg.lock b/Gopkg.lock index c81fa4edb..3ab9bcb1a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1377,9 +1377,11 @@ "golang.org/x/oauth2/google", "google.golang.org/api/dns/v1", "k8s.io/api/admission/v1beta1", + "k8s.io/api/authorization/v1", "k8s.io/api/batch/v1", "k8s.io/api/core/v1", "k8s.io/api/extensions/v1beta1", + "k8s.io/api/rbac/v1", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset", "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1", diff --git a/test/e2e/certificate/BUILD.bazel b/test/e2e/certificate/BUILD.bazel index 8c9b1ca27..0572fccbd 100644 --- a/test/e2e/certificate/BUILD.bazel +++ b/test/e2e/certificate/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "certificate_acme.go", "certificate_acme_dns01.go", "certificate_ca.go", + "certificate_rbac.go", "certificate_selfsigned.go", "certificate_vault.go", ], @@ -21,9 +22,13 @@ go_library( "//test/util/vault:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/k8s.io/api/authorization/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go new file mode 100644 index 000000000..33e8b15f5 --- /dev/null +++ b/test/e2e/certificate/certificate_rbac.go @@ -0,0 +1,159 @@ +/* +Copyright 2018 The Jetstack cert-manager contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package certificate + +import ( + "time" + + "github.com/jetstack/cert-manager/test/e2e/framework" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + authorizationv1 "k8s.io/api/authorization/v1" + "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +var _ = framework.CertManagerDescribe("Service Account", func() { + f := framework.NewDefaultFramework("test-view") + + Context("with read access", func() { + It("shouldn't be able to create certificates", func() { + serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) + roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + + viewServiceAccountName := "test-view-create" + + By("Creating a service account") + viewServiceAccount := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: viewServiceAccountName, + }, + } + _, err := serviceAccountClient.Create(viewServiceAccount) + Expect(err).NotTo(HaveOccurred()) + + By("Creating ClusterRoleBinding to view user role") + viewRoleBinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: viewServiceAccountName + "-rb", + }, + Subjects: []rbacv1.Subject{ + {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: "view", + }, + } + _, err = roleBindingClient.Create(viewRoleBinding) + Expect(err).NotTo(HaveOccurred()) + + By("Sleeping for a second.") // to allow RBAC to propagate + time.Sleep(time.Second) + + By("Impersonating the Service Account") + var impersonateConfig *rest.Config + impersonateConfig = f.Config + impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName + impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) + Expect(err).NotTo(HaveOccurred()) + + By("Submitting a self subject access review") + sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() + + sar := &authorizationv1.SelfSubjectAccessReview{ + Spec: authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: f.Namespace.Name, + Verb: "create", + Group: "certmanager.k8s.io", + Resource: "certificates", + }, + }, + } + + response, err := sarClient.Create(sar) + Expect(err).NotTo(HaveOccurred()) + Expect(response.Status.Allowed).Should(BeFalse()) + }) + + It("should be able to get certificates", func() { + serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) + roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + + viewServiceAccountName := "test-view-get" + + By("Creating a service account") + viewServiceAccount := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: viewServiceAccountName, + }, + } + _, err := serviceAccountClient.Create(viewServiceAccount) + Expect(err).NotTo(HaveOccurred()) + + By("Creating ClusterRoleBinding to view user role") + viewRoleBinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: viewServiceAccountName + "-rb", + }, + Subjects: []rbacv1.Subject{ + {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: "view", + }, + } + _, err = roleBindingClient.Create(viewRoleBinding) + Expect(err).NotTo(HaveOccurred()) + + By("Sleeping for a second.") // to allow RBAC to propagate + time.Sleep(time.Second) + + By("Impersonating the Service Account") + var impersonateConfig *rest.Config + impersonateConfig = f.Config + impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName + impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) + Expect(err).NotTo(HaveOccurred()) + + By("Submitting a self subject access review") + sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() + + sar := &authorizationv1.SelfSubjectAccessReview{ + Spec: authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: f.Namespace.Name, + Verb: "get", + Group: "certmanager.k8s.io", + Resource: "certificates", + }, + }, + } + + response, err := sarClient.Create(sar) + Expect(err).NotTo(HaveOccurred()) + Expect(response.Status.Allowed).Should(BeTrue()) + }) + }) +}) diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 2059867cc..0661f33f8 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -20,6 +20,7 @@ import ( "k8s.io/api/core/v1" apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -41,6 +42,9 @@ type Framework struct { // Namespace in which all test resources should reside Namespace *v1.Namespace + // Config which was used to create the connection. + Config *rest.Config + // To make sure that this framework cleans up after itself, no matter what, // we install a Cleanup action before each test and clear it after. If we // should abort, the AfterSuite hook should run all Cleanup actions. @@ -67,6 +71,7 @@ func (f *Framework) BeforeEach() { By("Creating a kubernetes client") kubeConfig, err := LoadConfig(TestContext.KubeConfig, TestContext.KubeContext) Expect(err).NotTo(HaveOccurred()) + f.Config = kubeConfig f.KubeClientSet, err = kubernetes.NewForConfig(kubeConfig) Expect(err).NotTo(HaveOccurred()) From d22a62d7a4c5bde5b11b8e01a89ea8192576eb6a Mon Sep 17 00:00:00 2001 From: William Lightning Date: Tue, 18 Sep 2018 15:57:23 -0700 Subject: [PATCH 05/10] Refactor common rbac test code into function Signed-off-by: William Lightning --- test/e2e/certificate/certificate_rbac.go | 182 +++++++++-------------- 1 file changed, 68 insertions(+), 114 deletions(-) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go index 33e8b15f5..4ed36545c 100644 --- a/test/e2e/certificate/certificate_rbac.go +++ b/test/e2e/certificate/certificate_rbac.go @@ -35,125 +35,79 @@ var _ = framework.CertManagerDescribe("Service Account", func() { Context("with read access", func() { It("shouldn't be able to create certificates", func() { - serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) - roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + clusterRole := "view" + verb := "create" + resource := "certificates" - viewServiceAccountName := "test-view-create" - - By("Creating a service account") - viewServiceAccount := &v1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: viewServiceAccountName, - }, - } - _, err := serviceAccountClient.Create(viewServiceAccount) - Expect(err).NotTo(HaveOccurred()) - - By("Creating ClusterRoleBinding to view user role") - viewRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: viewServiceAccountName + "-rb", - }, - Subjects: []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: "view", - }, - } - _, err = roleBindingClient.Create(viewRoleBinding) - Expect(err).NotTo(HaveOccurred()) - - By("Sleeping for a second.") // to allow RBAC to propagate - time.Sleep(time.Second) - - By("Impersonating the Service Account") - var impersonateConfig *rest.Config - impersonateConfig = f.Config - impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName - impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) - Expect(err).NotTo(HaveOccurred()) - - By("Submitting a self subject access review") - sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() - - sar := &authorizationv1.SelfSubjectAccessReview{ - Spec: authorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &authorizationv1.ResourceAttributes{ - Namespace: f.Namespace.Name, - Verb: "create", - Group: "certmanager.k8s.io", - Resource: "certificates", - }, - }, - } - - response, err := sarClient.Create(sar) - Expect(err).NotTo(HaveOccurred()) - Expect(response.Status.Allowed).Should(BeFalse()) + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) }) It("should be able to get certificates", func() { - serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) - roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + clusterRole := "view" + verb := "get" + resource := "certificates" - viewServiceAccountName := "test-view-get" - - By("Creating a service account") - viewServiceAccount := &v1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: viewServiceAccountName, - }, - } - _, err := serviceAccountClient.Create(viewServiceAccount) - Expect(err).NotTo(HaveOccurred()) - - By("Creating ClusterRoleBinding to view user role") - viewRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: viewServiceAccountName + "-rb", - }, - Subjects: []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: "view", - }, - } - _, err = roleBindingClient.Create(viewRoleBinding) - Expect(err).NotTo(HaveOccurred()) - - By("Sleeping for a second.") // to allow RBAC to propagate - time.Sleep(time.Second) - - By("Impersonating the Service Account") - var impersonateConfig *rest.Config - impersonateConfig = f.Config - impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName - impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) - Expect(err).NotTo(HaveOccurred()) - - By("Submitting a self subject access review") - sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() - - sar := &authorizationv1.SelfSubjectAccessReview{ - Spec: authorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &authorizationv1.ResourceAttributes{ - Namespace: f.Namespace.Name, - Verb: "get", - Group: "certmanager.k8s.io", - Resource: "certificates", - }, - }, - } - - response, err := sarClient.Create(sar) - Expect(err).NotTo(HaveOccurred()) - Expect(response.Status.Allowed).Should(BeTrue()) + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) }) }) }) + +func rbacClusterRoleHasAccessToResource(f *framework.Framework, clusterRole string, verb string, resource string) bool { + By("Creating a service account") + viewServiceAccount := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "rbac-test-", + }, + } + serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) + serviceAccount, err := serviceAccountClient.Create(viewServiceAccount) + Expect(err).NotTo(HaveOccurred()) + viewServiceAccountName := serviceAccount.Name + + By("Creating ClusterRoleBinding to view " + clusterRole + " clusterRole") + viewRoleBinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: viewServiceAccountName + "-rb-", + }, + Subjects: []rbacv1.Subject{ + {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: clusterRole, + }, + } + roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + _, err = roleBindingClient.Create(viewRoleBinding) + Expect(err).NotTo(HaveOccurred()) + + By("Sleeping for a second.") + // to allow RBAC to propagate + time.Sleep(time.Second) + + By("Impersonating the Service Account") + var impersonateConfig *rest.Config + impersonateConfig = f.Config + impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName + impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) + Expect(err).NotTo(HaveOccurred()) + + By("Submitting a self subject access review") + sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() + sar := &authorizationv1.SelfSubjectAccessReview{ + Spec: authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: f.Namespace.Name, + Verb: verb, + Group: "certmanager.k8s.io", + Resource: resource, + }, + }, + } + response, err := sarClient.Create(sar) + Expect(err).NotTo(HaveOccurred()) + return response.Status.Allowed +} From 12713c8679e4f1033e205bb9b444dd2f036d4271 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Tue, 18 Sep 2018 18:15:11 -0700 Subject: [PATCH 06/10] Add comprehensive tests around certificate rbac user facing roles Signed-off-by: William Lightning --- test/e2e/certificate/certificate_rbac.go | 186 ++++++++++++++++++++++- 1 file changed, 183 insertions(+), 3 deletions(-) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go index 4ed36545c..b3a354b68 100644 --- a/test/e2e/certificate/certificate_rbac.go +++ b/test/e2e/certificate/certificate_rbac.go @@ -33,9 +33,9 @@ import ( var _ = framework.CertManagerDescribe("Service Account", func() { f := framework.NewDefaultFramework("test-view") - Context("with read access", func() { + Context("with namespace view access", func() { + clusterRole := "view" It("shouldn't be able to create certificates", func() { - clusterRole := "view" verb := "create" resource := "certificates" @@ -43,14 +43,194 @@ var _ = framework.CertManagerDescribe("Service Account", func() { Expect(hasAccess).Should(BeFalse()) }) + It("shouldn't be able to delete certificates", func() { + verb := "delete" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to delete collections of certificates", func() { + verb := "deletecollection" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to patch certificates", func() { + verb := "patch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to update certificates", func() { + verb := "update" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + It("should be able to get certificates", func() { - clusterRole := "view" verb := "get" resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) + + It("should be able to list certificates", func() { + verb := "list" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch certificates", func() { + verb := "watch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + }) + Context("with namespace edit access", func() { + clusterRole := "edit" + It("should be able to create certificates", func() { + verb := "create" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete certificates", func() { + verb := "delete" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete collections of certificates", func() { + verb := "deletecollection" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to patch certificates", func() { + verb := "patch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to update certificates", func() { + verb := "update" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to get certificates", func() { + verb := "get" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to list certificates", func() { + verb := "list" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch certificates", func() { + verb := "watch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + }) + + Context("with namespace admin access", func() { + clusterRole := "admin" + It("should be able to create certificates", func() { + verb := "create" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete certificates", func() { + verb := "delete" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete collections of certificates", func() { + verb := "deletecollection" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to patch certificates", func() { + verb := "patch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to update certificates", func() { + verb := "update" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to get certificates", func() { + verb := "get" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to list certificates", func() { + verb := "list" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch certificates", func() { + verb := "watch" + resource := "certificates" + + hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) }) }) From 8dcfd76be58345b8734b2510a21b97a5268d7209 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Wed, 19 Sep 2018 10:04:09 -0700 Subject: [PATCH 07/10] certificate_rbac test: move defintion of resource up in the unit test, so we're not defining it on every it Signed-off-by: William Lightning --- test/e2e/certificate/certificate_rbac.go | 25 +----------------------- 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go index b3a354b68..053b55ef7 100644 --- a/test/e2e/certificate/certificate_rbac.go +++ b/test/e2e/certificate/certificate_rbac.go @@ -32,12 +32,12 @@ import ( var _ = framework.CertManagerDescribe("Service Account", func() { f := framework.NewDefaultFramework("test-view") + resource := "certificates" // this file is related to certificates Context("with namespace view access", func() { clusterRole := "view" It("shouldn't be able to create certificates", func() { verb := "create" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) @@ -45,7 +45,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("shouldn't be able to delete certificates", func() { verb := "delete" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) @@ -53,7 +52,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("shouldn't be able to delete collections of certificates", func() { verb := "deletecollection" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) @@ -61,7 +59,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("shouldn't be able to patch certificates", func() { verb := "patch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) @@ -69,7 +66,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("shouldn't be able to update certificates", func() { verb := "update" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) @@ -77,7 +73,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to get certificates", func() { verb := "get" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -85,7 +80,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to list certificates", func() { verb := "list" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -93,7 +87,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to watch certificates", func() { verb := "watch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -103,7 +96,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { clusterRole := "edit" It("should be able to create certificates", func() { verb := "create" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -111,7 +103,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to delete certificates", func() { verb := "delete" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -119,7 +110,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to delete collections of certificates", func() { verb := "deletecollection" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -127,7 +117,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to patch certificates", func() { verb := "patch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -135,7 +124,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to update certificates", func() { verb := "update" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -143,7 +131,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to get certificates", func() { verb := "get" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -151,7 +138,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to list certificates", func() { verb := "list" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -159,7 +145,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to watch certificates", func() { verb := "watch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -170,7 +155,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { clusterRole := "admin" It("should be able to create certificates", func() { verb := "create" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -178,7 +162,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to delete certificates", func() { verb := "delete" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -186,7 +169,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to delete collections of certificates", func() { verb := "deletecollection" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -194,7 +176,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to patch certificates", func() { verb := "patch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -202,7 +183,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to update certificates", func() { verb := "update" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -210,7 +190,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to get certificates", func() { verb := "get" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -218,7 +197,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to list certificates", func() { verb := "list" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) @@ -226,7 +204,6 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to watch certificates", func() { verb := "watch" - resource := "certificates" hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) From 3d09d98bd7a80918ae4bead9887a19cd0c81e6d0 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Wed, 19 Sep 2018 10:19:04 -0700 Subject: [PATCH 08/10] extract rbacClusterRoleHasAccessToResource out of certificate_rbac test to test framework util Signed-off-by: William Lightning --- test/e2e/certificate/BUILD.bazel | 4 - test/e2e/certificate/certificate_rbac.go | 114 +++++------------------ test/e2e/framework/BUILD.bazel | 2 + test/e2e/framework/util.go | 60 ++++++++++++ 4 files changed, 86 insertions(+), 94 deletions(-) diff --git a/test/e2e/certificate/BUILD.bazel b/test/e2e/certificate/BUILD.bazel index 0572fccbd..640746d6a 100644 --- a/test/e2e/certificate/BUILD.bazel +++ b/test/e2e/certificate/BUILD.bazel @@ -22,13 +22,9 @@ go_library( "//test/util/vault:go_default_library", "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", - "//vendor/k8s.io/api/authorization/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", ], ) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go index 053b55ef7..020b1edc7 100644 --- a/test/e2e/certificate/certificate_rbac.go +++ b/test/e2e/certificate/certificate_rbac.go @@ -17,17 +17,9 @@ limitations under the License. package certificate import ( - "time" - "github.com/jetstack/cert-manager/test/e2e/framework" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - authorizationv1 "k8s.io/api/authorization/v1" - "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" ) var _ = framework.CertManagerDescribe("Service Account", func() { @@ -39,56 +31,56 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("shouldn't be able to create certificates", func() { verb := "create" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) }) It("shouldn't be able to delete certificates", func() { verb := "delete" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) }) It("shouldn't be able to delete collections of certificates", func() { verb := "deletecollection" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) }) It("shouldn't be able to patch certificates", func() { verb := "patch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) }) It("shouldn't be able to update certificates", func() { verb := "update" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeFalse()) }) It("should be able to get certificates", func() { verb := "get" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to list certificates", func() { verb := "list" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to watch certificates", func() { verb := "watch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) }) @@ -97,56 +89,56 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to create certificates", func() { verb := "create" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to delete certificates", func() { verb := "delete" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to delete collections of certificates", func() { verb := "deletecollection" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to patch certificates", func() { verb := "patch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to update certificates", func() { verb := "update" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to get certificates", func() { verb := "get" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to list certificates", func() { verb := "list" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to watch certificates", func() { verb := "watch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) }) @@ -156,115 +148,57 @@ var _ = framework.CertManagerDescribe("Service Account", func() { It("should be able to create certificates", func() { verb := "create" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to delete certificates", func() { verb := "delete" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to delete collections of certificates", func() { verb := "deletecollection" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to patch certificates", func() { verb := "patch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to update certificates", func() { verb := "update" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to get certificates", func() { verb := "get" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to list certificates", func() { verb := "list" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) It("should be able to watch certificates", func() { verb := "watch" - hasAccess := rbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) Expect(hasAccess).Should(BeTrue()) }) }) }) - -func rbacClusterRoleHasAccessToResource(f *framework.Framework, clusterRole string, verb string, resource string) bool { - By("Creating a service account") - viewServiceAccount := &v1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "rbac-test-", - }, - } - serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) - serviceAccount, err := serviceAccountClient.Create(viewServiceAccount) - Expect(err).NotTo(HaveOccurred()) - viewServiceAccountName := serviceAccount.Name - - By("Creating ClusterRoleBinding to view " + clusterRole + " clusterRole") - viewRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: viewServiceAccountName + "-rb-", - }, - Subjects: []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: clusterRole, - }, - } - roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() - _, err = roleBindingClient.Create(viewRoleBinding) - Expect(err).NotTo(HaveOccurred()) - - By("Sleeping for a second.") - // to allow RBAC to propagate - time.Sleep(time.Second) - - By("Impersonating the Service Account") - var impersonateConfig *rest.Config - impersonateConfig = f.Config - impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName - impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) - Expect(err).NotTo(HaveOccurred()) - - By("Submitting a self subject access review") - sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() - sar := &authorizationv1.SelfSubjectAccessReview{ - Spec: authorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &authorizationv1.ResourceAttributes{ - Namespace: f.Namespace.Name, - Verb: verb, - Group: "certmanager.k8s.io", - Resource: resource, - }, - }, - } - response, err := sarClient.Create(sar) - Expect(err).NotTo(HaveOccurred()) - return response.Status.Allowed -} diff --git a/test/e2e/framework/BUILD.bazel b/test/e2e/framework/BUILD.bazel index 149e01f25..af2ec9150 100644 --- a/test/e2e/framework/BUILD.bazel +++ b/test/e2e/framework/BUILD.bazel @@ -16,7 +16,9 @@ go_library( "//vendor/github.com/onsi/ginkgo:go_default_library", "//vendor/github.com/onsi/ginkgo/config:go_default_library", "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/k8s.io/api/authorization/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index 4d965ece7..112268d23 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -23,7 +23,9 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + authorizationv1 "k8s.io/api/authorization/v1" "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -306,3 +308,61 @@ func podRunning(c kubernetes.Interface, podName, namespace string) wait.Conditio return false, nil } } + +func RbacClusterRoleHasAccessToResource(f *Framework, clusterRole string, verb string, resource string) bool { + By("Creating a service account") + viewServiceAccount := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "rbac-test-", + }, + } + serviceAccountClient := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name) + serviceAccount, err := serviceAccountClient.Create(viewServiceAccount) + Expect(err).NotTo(HaveOccurred()) + viewServiceAccountName := serviceAccount.Name + + By("Creating ClusterRoleBinding to view " + clusterRole + " clusterRole") + viewRoleBinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: viewServiceAccountName + "-rb-", + }, + Subjects: []rbacv1.Subject{ + {Kind: "ServiceAccount", Name: viewServiceAccountName, Namespace: f.Namespace.Name}, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: clusterRole, + }, + } + roleBindingClient := f.KubeClientSet.RbacV1().ClusterRoleBindings() + _, err = roleBindingClient.Create(viewRoleBinding) + Expect(err).NotTo(HaveOccurred()) + + By("Sleeping for a second.") + // to allow RBAC to propagate + time.Sleep(time.Second) + + By("Impersonating the Service Account") + var impersonateConfig *rest.Config + impersonateConfig = f.Config + impersonateConfig.Impersonate.UserName = "system:serviceaccount:" + f.Namespace.Name + ":" + viewServiceAccountName + impersonateClient, err := kubernetes.NewForConfig(impersonateConfig) + Expect(err).NotTo(HaveOccurred()) + + By("Submitting a self subject access review") + sarClient := impersonateClient.AuthorizationV1().SelfSubjectAccessReviews() + sar := &authorizationv1.SelfSubjectAccessReview{ + Spec: authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: f.Namespace.Name, + Verb: verb, + Group: "certmanager.k8s.io", + Resource: resource, + }, + }, + } + response, err := sarClient.Create(sar) + Expect(err).NotTo(HaveOccurred()) + return response.Status.Allowed +} From 180af301ebb6217ca33c51f9986c5dfe23571104 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Wed, 19 Sep 2018 10:20:32 -0700 Subject: [PATCH 09/10] Update certificate_rbac test framework initialization basename Signed-off-by: William Lightning --- test/e2e/certificate/certificate_rbac.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/certificate/certificate_rbac.go b/test/e2e/certificate/certificate_rbac.go index 020b1edc7..cb32c488d 100644 --- a/test/e2e/certificate/certificate_rbac.go +++ b/test/e2e/certificate/certificate_rbac.go @@ -23,7 +23,7 @@ import ( ) var _ = framework.CertManagerDescribe("Service Account", func() { - f := framework.NewDefaultFramework("test-view") + f := framework.NewDefaultFramework("certificate-rbac") resource := "certificates" // this file is related to certificates Context("with namespace view access", func() { From 7d8c7ddea5ec8471caf333385a0f24b48e062bc5 Mon Sep 17 00:00:00 2001 From: William Lightning Date: Wed, 19 Sep 2018 10:26:18 -0700 Subject: [PATCH 10/10] Build out issuer_rbac tests based on certificate_rbac tests Signed-off-by: William Lightning --- test/e2e/issuer/BUILD.bazel | 1 + test/e2e/issuer/issuer_rbac.go | 204 +++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 test/e2e/issuer/issuer_rbac.go diff --git a/test/e2e/issuer/BUILD.bazel b/test/e2e/issuer/BUILD.bazel index 6e32968ee..e799d59e4 100644 --- a/test/e2e/issuer/BUILD.bazel +++ b/test/e2e/issuer/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "issuer_acme.go", "issuer_ca.go", + "issuer_rbac.go", "issuer_vault.go", ], importpath = "github.com/jetstack/cert-manager/test/e2e/issuer", diff --git a/test/e2e/issuer/issuer_rbac.go b/test/e2e/issuer/issuer_rbac.go new file mode 100644 index 000000000..0ee7d5706 --- /dev/null +++ b/test/e2e/issuer/issuer_rbac.go @@ -0,0 +1,204 @@ +/* +Copyright 2018 The Jetstack cert-manager contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package issuer + +import ( + "github.com/jetstack/cert-manager/test/e2e/framework" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = framework.CertManagerDescribe("Service Account", func() { + f := framework.NewDefaultFramework("issuer-rbac") + resource := "issuers" // this file is related to issuers + + Context("with namespace view access", func() { + clusterRole := "view" + It("shouldn't be able to create issuers", func() { + verb := "create" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to delete issuers", func() { + verb := "delete" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to delete collections of issuers", func() { + verb := "deletecollection" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to patch issuers", func() { + verb := "patch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("shouldn't be able to update issuers", func() { + verb := "update" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeFalse()) + }) + + It("should be able to get issuers", func() { + verb := "get" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to list issuers", func() { + verb := "list" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch issuers", func() { + verb := "watch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + }) + Context("with namespace edit access", func() { + clusterRole := "edit" + It("should be able to create issuers", func() { + verb := "create" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete issuers", func() { + verb := "delete" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete collections of issuers", func() { + verb := "deletecollection" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to patch issuers", func() { + verb := "patch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to update issuers", func() { + verb := "update" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to get issuers", func() { + verb := "get" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to list issuers", func() { + verb := "list" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch issuers", func() { + verb := "watch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + }) + + Context("with namespace admin access", func() { + clusterRole := "admin" + It("should be able to create issuers", func() { + verb := "create" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete issuers", func() { + verb := "delete" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to delete collections of issuers", func() { + verb := "deletecollection" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to patch issuers", func() { + verb := "patch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to update issuers", func() { + verb := "update" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to get issuers", func() { + verb := "get" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to list issuers", func() { + verb := "list" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + + It("should be able to watch issuers", func() { + verb := "watch" + + hasAccess := framework.RbacClusterRoleHasAccessToResource(f, clusterRole, verb, resource) + Expect(hasAccess).Should(BeTrue()) + }) + }) +})