cert-manager/test/e2e/suite/certificaterequests/approval/approval.go
joshvanl 0b2cdf5a40 Adds e2e tests for CertificateRequest self signing controller; focussing
on requests being re-synced when the target Secret is up

Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-08-09 08:40:05 +01:00

497 lines
23 KiB
Go

/*
Copyright 2020 The cert-manager Authors.
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 approval
import (
"context"
"crypto/x509"
"fmt"
"strings"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
crdapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
crdclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
apiutil "github.com/cert-manager/cert-manager/pkg/api/util"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
clientset "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned"
"github.com/cert-manager/cert-manager/test/e2e/framework"
testutil "github.com/cert-manager/cert-manager/test/e2e/framework/util"
e2eutil "github.com/cert-manager/cert-manager/test/e2e/util"
"github.com/cert-manager/cert-manager/test/unit/gen"
)
// This test ensures that the approval condition may only be set by users who
// have the correct RBAC permissions.
var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
f := framework.NewDefaultFramework("approval-certificaterequests")
var (
sa *corev1.ServiceAccount
saclient clientset.Interface
request *cmapi.CertificateRequest
crd *crdapi.CustomResourceDefinition
crdclient crdclientset.Interface
group string
)
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a is not found error.
isNotFoundError := func(issuerRef cmmeta.ObjectReference, err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(
strings.TrimSpace(err.Error()),
fmt.Sprintf("Forbidden: referenced signer resource does not exist: %v", issuerRef),
) || strings.HasSuffix(strings.TrimSpace(err.Error()), "the server could not find the requested resource")
}
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a context deadline error.
isTimeoutError := func(err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(strings.TrimSpace(err.Error()), "context deadline exceeded")
}
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a permissions error when the client attempts to approve
// or deny a CertificateRequest.
isPermissionError := func(sa *corev1.ServiceAccount, issuerRef cmmeta.ObjectReference, err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(
strings.TrimSpace(err.Error()),
fmt.Sprintf("Forbidden: user \"system:serviceaccount:%s:%s\" does not have permissions to set approved/denied conditions for issuer %v",
sa.Namespace, sa.Name, issuerRef),
)
}
// retryNotFound returns true when either the resource is not found for the
// issuer, or the webhook returns a context deadline error. Useful for
// retrying a request when the expected response is a different or no error.
retryOnNotFound := func(issuerRef cmmeta.ObjectReference) func(error) bool {
return func(err error) bool {
return isNotFoundError(issuerRef, err) || isTimeoutError(err)
}
}
JustBeforeEach(func() {
var err error
crdclient, err = crdclientset.NewForConfig(f.KubeClientConfig)
Expect(err).NotTo(HaveOccurred())
group = e2eutil.RandomSubdomain("example.io")
sa, err = f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name).Create(context.TODO(), &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-sa-",
Namespace: f.Namespace.Name,
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
role, err := f.KubeClientSet.RbacV1().Roles(f.Namespace.Name).Create(context.TODO(), &rbacv1.Role{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "certificaterequest-creator-",
Namespace: f.Namespace.Name,
},
Rules: []rbacv1.PolicyRule{
{
Verbs: []string{"create"},
APIGroups: []string{"cert-manager.io"},
Resources: []string{"certificaterequests"},
},
{
Verbs: []string{"update"},
APIGroups: []string{"cert-manager.io"},
Resources: []string{"certificaterequests/status"},
},
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
By("Creating certificaterequest-creator rolebinding for ServiceAccount")
_, err = f.KubeClientSet.RbacV1().RoleBindings(f.Namespace.Name).Create(context.TODO(), &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "certificaterequest-creator-",
Namespace: f.Namespace.Name,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: sa.Name,
Namespace: f.Namespace.Name,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Role",
Name: role.Name,
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
// Manually create a Secret to be populated with Service Account token
// https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Create(context.TODO(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "sa-secret-",
Name: f.Namespace.Name,
Annotations: map[string]string{
"kubernetes.io/service-account.name": sa.Name,
},
},
Type: corev1.SecretTypeServiceAccountToken,
}, metav1.CreateOptions{})
var (
token []byte
ok bool
)
err = wait.PollImmediate(time.Second, time.Second*10,
func() (bool, error) {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.TODO(), secret.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
if len(secret.Data) == 0 {
return false, nil
}
if token, ok = secret.Data["token"]; !ok {
return false, nil
}
return true, nil
},
)
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Error: %s", err))
By("Building ServiceAccount kubernetes clientset")
kubeConfig, err := testutil.LoadConfig(f.Config.KubeConfig, f.Config.KubeContext)
Expect(err).NotTo(HaveOccurred())
kubeConfig.BearerToken = fmt.Sprintf("%s", token)
kubeConfig.CertData = nil
kubeConfig.KeyData = nil
kubeConfig.Timeout = time.Second * 20
saclient, err = clientset.NewForConfig(kubeConfig)
Expect(err).NotTo(HaveOccurred())
csr, _, err := gen.CSR(x509.RSA)
Expect(err).NotTo(HaveOccurred())
request = gen.CertificateRequest("",
gen.SetCertificateRequestNamespace(f.Namespace.Name),
gen.SetCertificateRequestCSR(csr),
gen.SetCertificateRequestIssuer(cmmeta.ObjectReference{
Name: "test-issuer",
Kind: "Issuer",
Group: group,
}),
)
request.GenerateName = "test-request-"
request, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).Create(context.TODO(), request, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
})
JustAfterEach(func() {
err := f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name).Delete(context.TODO(), sa.Name, metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred())
err = f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Delete(context.TODO(), request.Name, metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred())
if crd != nil {
By("Removing CustomResource Definition")
err = crdclient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{})
Expect(err).NotTo(HaveOccurred())
}
crd = nil
})
It("attempting to approve a certificate request without the approve permission should error", func() {
createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
approvedCR := request.DeepCopy()
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err := retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("attempting to deny a certificate request without the approve permission should error", func() {
createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
deniedCR := request.DeepCopy()
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err := retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("a service account with the approve permissions for a resource that doesn't exist attempting to approve should error", func() {
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Consistently(func() bool {
err := retry.OnError(retry.DefaultBackoff, isTimeoutError, func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
return isNotFoundError(approvedCR.Spec.IssuerRef, err)
}).Should(BeTrue())
})
It("a service account with the approve permissions for a resource that doesn't exist attempting to deny should error", func() {
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Consistently(func() bool {
err := retry.OnError(retry.DefaultBackoff, isTimeoutError, func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
return isNotFoundError(deniedCR.Spec.IssuerRef, err)
}).Should(BeTrue())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/* should be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/* should be able to deny requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/test-issuer should be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/test-issuer", group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/<namespace>.test-issuer should not be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/%s.test-issuer", f.Namespace.Name, group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/<namespace>.test-issuer should be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/%s.test-issuer", group, f.Namespace.Name))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/test-issuer should not be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/test-issuer", group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
//
It("a service account with the approve permissions for cluster scoped issuers.example.io/test-issuer should be able to deny requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/test-issuer", group))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/<namespace>.test-issuer should not be able to deny requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/%s.test-issuer", f.Namespace.Name, group))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/<namespace>.test-issuer should be able to deny requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/%s.test-issuer", group, f.Namespace.Name))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/test-issuer should not be able to denied requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/test-issuer", group))
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
})
func createCRD(crdclient crdclientset.Interface, group, plural, kind string, scope crdapi.ResourceScope) *crdapi.CustomResourceDefinition {
crd, err := crdclient.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), &crdapi.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s.%s", plural, group),
},
Spec: crdapi.CustomResourceDefinitionSpec{
Group: group,
Names: crdapi.CustomResourceDefinitionNames{
Kind: kind,
Plural: plural,
},
Versions: []crdapi.CustomResourceDefinitionVersion{
{
Name: "v1alpha1",
Served: true,
Storage: true,
Schema: &crdapi.CustomResourceValidation{
OpenAPIV3Schema: &crdapi.JSONSchemaProps{
Type: "object",
Properties: map[string]crdapi.JSONSchemaProps{},
},
},
},
},
Scope: scope,
},
}, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
return crd
}
func bindServiceAccountToApprove(f *framework.Framework, sa *corev1.ServiceAccount, resourceName string) {
clusterrole, err := f.KubeClientSet.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "certificaterequest-approver-",
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{"cert-manager.io"},
Resources: []string{"signers"},
Verbs: []string{"approve"},
ResourceNames: []string{resourceName},
},
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
_, err = f.KubeClientSet.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "certificaterequest-approver-",
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: sa.Name,
Namespace: sa.Namespace,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: clusterrole.Name,
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
}