1
0
mirror of https://github.com/ceph/ceph-csi.git synced 2024-12-22 04:50:23 +00:00
ceph-csi/e2e/deploy-vault.go
Niels de Vos 4a6c27274f build: address ginkgolinter warnings
Signed-off-by: Niels de Vos <ndevos@ibm.com>
2023-06-05 04:49:46 +00:00

157 lines
5.3 KiB
Go

/*
Copyright 2021 The Ceph-CSI 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 e2e
import (
"context"
"fmt"
"strings"
. "github.com/onsi/gomega" //nolint:golint // e2e uses Expect() and other Gomega functions
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/test/e2e/framework"
)
var (
vaultExamplePath = "../examples/kms/vault/"
vaultServicePath = "vault.yaml"
vaultRBACPath = "csi-vaulttokenreview-rbac.yaml"
vaultConfigPath = "kms-config.yaml"
vaultTenantPath = "tenant-sa.yaml"
vaultTenantAdminPath = "tenant-sa-admin.yaml"
vaultUserSecret = "user-secret.yaml"
)
func deployVault(c kubernetes.Interface, deployTimeout int) {
// hack to make helm E2E pass as helm charts creates this configmap as part
// of cephcsi deployment
err := retryKubectlArgs(
cephCSINamespace,
kubectlDelete,
deployTimeout,
"cm",
"ceph-csi-encryption-kms-config",
"--ignore-not-found=true")
Expect(err).ShouldNot(HaveOccurred())
createORDeleteVault(kubectlCreate)
opt := metav1.ListOptions{
LabelSelector: "app=vault",
}
pods, err := c.CoreV1().Pods(cephCSINamespace).List(context.TODO(), opt)
Expect(err).ShouldNot(HaveOccurred())
Expect(pods.Items).Should(HaveLen(1))
name := pods.Items[0].Name
err = waitForPodInRunningState(name, cephCSINamespace, c, deployTimeout, noError)
Expect(err).ShouldNot(HaveOccurred())
}
func deleteVault() {
createORDeleteVault(kubectlDelete)
}
func createORDeleteVault(action kubectlAction) {
data, err := replaceNamespaceInTemplate(vaultExamplePath + vaultServicePath)
if err != nil {
framework.Failf("failed to read content from %s %v", vaultExamplePath+vaultServicePath, err)
}
data = strings.ReplaceAll(data, "vault.default", "vault."+cephCSINamespace)
data = strings.ReplaceAll(data, "value: default", "value: "+cephCSINamespace)
err = retryKubectlInput(cephCSINamespace, action, data, deployTimeout)
if err != nil {
framework.Failf("failed to %s vault statefulset %v", action, err)
}
data, err = replaceNamespaceInTemplate(vaultExamplePath + vaultRBACPath)
if err != nil {
framework.Failf("failed to read content from %s %v", vaultExamplePath+vaultRBACPath, err)
}
err = retryKubectlInput(cephCSINamespace, action, data, deployTimeout)
if err != nil {
framework.Failf("failed to %s vault statefulset %v", action, err)
}
data, err = replaceNamespaceInTemplate(vaultExamplePath + vaultConfigPath)
if err != nil {
framework.Failf("failed to read content from %s %v", vaultExamplePath+vaultConfigPath, err)
}
data = strings.ReplaceAll(data, "default", cephCSINamespace)
err = retryKubectlInput(cephCSINamespace, action, data, deployTimeout)
if err != nil {
framework.Failf("failed to %s vault configmap %v", action, err)
}
}
// createTenantServiceAccount uses the tenant-sa.yaml example file to create
// the ServiceAccount for the tenant and configured Hashicorp Vault with a
// kv-store that the ServiceAccount has access to.
func createTenantServiceAccount(c kubernetes.Interface, ns string) error {
err := createORDeleteTenantServiceAccount(kubectlCreate, ns)
if err != nil {
return fmt.Errorf("failed to create ServiceAccount: %w", err)
}
// wait for the Job to finish
const jobName = "vault-tenant-sa"
err = waitForJobCompletion(c, cephCSINamespace, jobName, deployTimeout)
if err != nil {
return fmt.Errorf("job %s/%s did not succeed: %w", cephCSINamespace, jobName, err)
}
return nil
}
// deleteTenantServiceAccount removed the ServiceAccount and other objects that
// were created with createTenantServiceAccount.
func deleteTenantServiceAccount(ns string) {
err := createORDeleteTenantServiceAccount(kubectlDelete, ns)
Expect(err).ShouldNot(HaveOccurred())
}
// createORDeleteTenantServiceAccount is a helper that reads the tenant-sa.yaml
// example file and replaces the default namespaces with the current deployment
// configuration.
func createORDeleteTenantServiceAccount(action kubectlAction, ns string) error {
err := retryKubectlFile(ns, action, vaultExamplePath+vaultTenantPath, deployTimeout)
if err != nil {
return fmt.Errorf("failed to %s tenant ServiceAccount: %w", action, err)
}
// the ServiceAccount needs permissions in Vault, the admin job sets that up
data, err := replaceNamespaceInTemplate(vaultExamplePath + vaultTenantAdminPath)
if err != nil {
return fmt.Errorf("failed to read content from %q: %w", vaultExamplePath+vaultTenantAdminPath, err)
}
// replace the value for TENANT_NAMESPACE
data = strings.ReplaceAll(data, "value: tenant", "value: "+ns)
// replace "default" in the URL to the Vault service
data = strings.ReplaceAll(data, "vault.default", "vault."+cephCSINamespace)
err = retryKubectlInput(cephCSINamespace, action, data, deployTimeout)
if err != nil {
return fmt.Errorf("failed to %s ServiceAccount: %w", action, err)
}
return nil
}