From f82f36bfaad4e4eeab15a8ab90698dccdf19b61a Mon Sep 17 00:00:00 2001 From: joshvanl Date: Mon, 14 Jun 2021 20:25:40 +0100 Subject: [PATCH] Adds Vault Kubernetes Auth CSR E2E tests Signed-off-by: joshvanl --- test/e2e/suite/conformance/BUILD.bazel | 1 + .../certificatesigningrequests/BUILD.bazel | 1 + .../vault/BUILD.bazel | 40 ++++ .../vault/kubernetes.go | 182 ++++++++++++++++++ test/e2e/suite/conformance/import.go | 1 + 5 files changed, 225 insertions(+) create mode 100644 test/e2e/suite/conformance/certificatesigningrequests/vault/BUILD.bazel create mode 100644 test/e2e/suite/conformance/certificatesigningrequests/vault/kubernetes.go diff --git a/test/e2e/suite/conformance/BUILD.bazel b/test/e2e/suite/conformance/BUILD.bazel index ce0848454..c5397ea8a 100644 --- a/test/e2e/suite/conformance/BUILD.bazel +++ b/test/e2e/suite/conformance/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "//test/e2e/suite/conformance/certificates/venaficloud:go_default_library", "//test/e2e/suite/conformance/certificatesigningrequests/ca:go_default_library", "//test/e2e/suite/conformance/certificatesigningrequests/selfsigned:go_default_library", + "//test/e2e/suite/conformance/certificatesigningrequests/vault:go_default_library", "//test/e2e/suite/conformance/rbac:go_default_library", ], ) diff --git a/test/e2e/suite/conformance/certificatesigningrequests/BUILD.bazel b/test/e2e/suite/conformance/certificatesigningrequests/BUILD.bazel index 99b949ed3..254211343 100644 --- a/test/e2e/suite/conformance/certificatesigningrequests/BUILD.bazel +++ b/test/e2e/suite/conformance/certificatesigningrequests/BUILD.bazel @@ -38,6 +38,7 @@ filegroup( ":package-srcs", "//test/e2e/suite/conformance/certificatesigningrequests/ca:all-srcs", "//test/e2e/suite/conformance/certificatesigningrequests/selfsigned:all-srcs", + "//test/e2e/suite/conformance/certificatesigningrequests/vault:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/test/e2e/suite/conformance/certificatesigningrequests/vault/BUILD.bazel b/test/e2e/suite/conformance/certificatesigningrequests/vault/BUILD.bazel new file mode 100644 index 000000000..614b56f07 --- /dev/null +++ b/test/e2e/suite/conformance/certificatesigningrequests/vault/BUILD.bazel @@ -0,0 +1,40 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "approle.go", + "approle_custom_mount.go", + "kubernetes.go", + ], + importpath = "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/vault", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/certmanager/v1:go_default_library", + "//pkg/apis/meta/v1:go_default_library", + "//pkg/controller/certificatesigningrequests/util:go_default_library", + "//pkg/util:go_default_library", + "//test/e2e/framework:go_default_library", + "//test/e2e/framework/addon:go_default_library", + "//test/e2e/framework/addon/vault:go_default_library", + "//test/e2e/framework/helper/featureset:go_default_library", + "//test/e2e/suite/conformance/certificatesigningrequests:go_default_library", + "@com_github_onsi_ginkgo//:go_default_library", + "@com_github_onsi_gomega//:go_default_library", + "@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/test/e2e/suite/conformance/certificatesigningrequests/vault/kubernetes.go b/test/e2e/suite/conformance/certificatesigningrequests/vault/kubernetes.go new file mode 100644 index 000000000..214d3f0bc --- /dev/null +++ b/test/e2e/suite/conformance/certificatesigningrequests/vault/kubernetes.go @@ -0,0 +1,182 @@ +/* +Copyright 2021 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 vault + +import ( + "context" + "fmt" + "path" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1" + cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1" + csrutil "github.com/jetstack/cert-manager/pkg/controller/certificatesigningrequests/util" + "github.com/jetstack/cert-manager/pkg/util" + "github.com/jetstack/cert-manager/test/e2e/framework" + "github.com/jetstack/cert-manager/test/e2e/framework/addon" + "github.com/jetstack/cert-manager/test/e2e/framework/addon/vault" + "github.com/jetstack/cert-manager/test/e2e/framework/helper/featureset" + "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests" +) + +var _ = framework.ConformanceDescribe("CertificateSigningRequests", func() { + issuer := &kubernetes{ + testWithRootCA: true, + } + (&certificatesigningrequests.Suite{ + Name: "Vault Kubernetes Auth Issuer With Root CA", + CreateIssuerFunc: issuer.createIssuer, + DeleteIssuerFunc: issuer.delete, + UnsupportedFeatures: featureset.NewFeatureSet( + featureset.KeyUsagesFeature, + ), + }).Define() + + clusterIssuer := &kubernetes{ + testWithRootCA: true, + } + (&certificatesigningrequests.Suite{ + Name: "Vault Kubernetes Auth ClusterIssuer With Root CA", + CreateIssuerFunc: clusterIssuer.createClusterIssuer, + DeleteIssuerFunc: clusterIssuer.delete, + UnsupportedFeatures: featureset.NewFeatureSet( + featureset.KeyUsagesFeature, + ), + }).Define() +}) + +type kubernetes struct { + testWithRootCA bool + role string + + addon *vault.Vault + initializer *vault.VaultInitializer +} + +func (k *kubernetes) createIssuer(f *framework.Framework) string { + k.initVault(f, f.Namespace.Name) + + By("Creating a VaultKubernetes Issuer") + issuer, err := f.CertManagerClientSet.CertmanagerV1().Issuers(f.Namespace.Name).Create(context.TODO(), &cmapi.Issuer{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "vault-issuer-", + Namespace: f.Namespace.Name, + }, + Spec: k.issuerSpec(f), + }, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + + return fmt.Sprintf("issuers.cert-manager.io/%s.%s", issuer.Namespace, issuer.Name) +} + +func (k *kubernetes) createClusterIssuer(f *framework.Framework) string { + k.initVault(f, f.Config.Addons.CertManager.ClusterResourceNamespace) + + By("Creating a VaultKubernetes ClusterIssuer") + issuer, err := f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Create(context.TODO(), &cmapi.ClusterIssuer{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "vault-issuer-", + }, + Spec: k.issuerSpec(f), + }, metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + + return fmt.Sprintf("clusterissuers.cert-manager.io/%s", issuer.Name) +} + +func (k *kubernetes) delete(f *framework.Framework, signerName string) { + ref, _ := csrutil.SignerIssuerRefFromSignerName(signerName) + if kind, _ := csrutil.IssuerKindFromType(ref.Type); kind == cmapi.ClusterIssuerKind { + err := f.CertManagerClientSet.CertmanagerV1().ClusterIssuers().Delete(context.TODO(), ref.Name, metav1.DeleteOptions{}) + Expect(err).NotTo(HaveOccurred()) + + k.initializer.CleanKubernetesRole(f.KubeClientSet, f.Config.Addons.CertManager.ClusterResourceNamespace, k.role, k.role) + } + + Expect(k.initializer.Clean()).NotTo(HaveOccurred(), "failed to deprovision vault initializer") + Expect(k.addon.Deprovision()).NotTo(HaveOccurred(), "failed to deprovision vault") + +} + +func (k *kubernetes) initVault(f *framework.Framework, ns string) { + By("Configuring the Vault server") + k.addon = &vault.Vault{ + Base: addon.Base, + Name: "cm-e2e-create-vault-issuer", + Namespace: f.Namespace.Name, + } + + k.role = "vault-issuer-" + util.RandStringRunes(5) + + Expect(k.addon.Setup(f.Config)).NotTo(HaveOccurred(), "failed to setup vault") + Expect(k.addon.Provision()).NotTo(HaveOccurred(), "failed to provision vault") + + By("Configuring the VaultKubernetes server") + + apiHost := "https://kubernetes.default.svc.cluster.local" // since vault is running in-cluster + caCert := string(f.KubeClientConfig.CAData) + Expect(caCert).NotTo(BeEmpty()) + Expect(apiHost).NotTo(BeEmpty()) + k.initializer = &vault.VaultInitializer{ + Details: *k.addon.Details(), + RootMount: rootMount, + IntermediateMount: intermediateMount, + ConfigureWithRoot: k.testWithRootCA, + KubernetesAuthPath: "kubernetes", + Role: k.role, + APIServerURL: apiHost, + APIServerCA: caCert, + } + Expect(k.initializer.Init()).NotTo(HaveOccurred(), "failed to init vault") + Expect(k.initializer.Setup()).NotTo(HaveOccurred(), "failed to setup vault") + + By("Creating a ServiceAccount for Vault authentication") + err := k.initializer.CreateKubernetesRole(f.KubeClientSet, ns, k.role, k.role) + Expect(err).NotTo(HaveOccurred()) + _, err = f.KubeClientSet.CoreV1().Secrets(ns).Create(context.TODO(), vault.NewVaultKubernetesSecret(k.role, k.role), metav1.CreateOptions{}) + Expect(err).NotTo(HaveOccurred()) + _, _, err = k.initializer.CreateAppRole() + Expect(err).NotTo(HaveOccurred()) +} + +func (k *kubernetes) issuerSpec(f *framework.Framework) cmapi.IssuerSpec { + vaultPath := path.Join(intermediateMount, "sign", k.role) + + return cmapi.IssuerSpec{ + IssuerConfig: cmapi.IssuerConfig{ + Vault: &cmapi.VaultIssuer{ + Server: k.addon.Details().Host, + Path: vaultPath, + CABundle: k.addon.Details().VaultCA, + Auth: cmapi.VaultAuth{ + Kubernetes: &cmapi.VaultKubernetesAuth{ + Path: "/v1/auth/kubernetes", + Role: k.role, + SecretRef: cmmeta.SecretKeySelector{ + LocalObjectReference: cmmeta.LocalObjectReference{ + Name: k.role, + }, + }, + }, + }, + }, + }, + } +} diff --git a/test/e2e/suite/conformance/import.go b/test/e2e/suite/conformance/import.go index 0c2c1424d..61b61b9af 100644 --- a/test/e2e/suite/conformance/import.go +++ b/test/e2e/suite/conformance/import.go @@ -26,5 +26,6 @@ import ( _ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificates/venaficloud" _ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/ca" _ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/selfsigned" + _ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/certificatesigningrequests/vault" _ "github.com/jetstack/cert-manager/test/e2e/suite/conformance/rbac" )