diff --git a/pkg/operator/ceph/object/s3-handlers.go b/pkg/operator/ceph/object/s3-handlers.go index 980f94993772..98701f7340fa 100644 --- a/pkg/operator/ceph/object/s3-handlers.go +++ b/pkg/operator/ceph/object/s3-handlers.go @@ -37,6 +37,14 @@ type S3Agent struct { } func NewS3Agent(accessKey, secretKey, endpoint string, debug bool, tlsCert []byte) (*S3Agent, error) { + return newS3Agent(accessKey, secretKey, endpoint, debug, tlsCert, false) +} + +func NewTestOnlyS3Agent(accessKey, secretKey, endpoint string, debug bool) (*S3Agent, error) { + return newS3Agent(accessKey, secretKey, endpoint, debug, nil, true) +} + +func newS3Agent(accessKey, secretKey, endpoint string, debug bool, tlsCert []byte, insecure bool) (*S3Agent, error) { const cephRegion = "us-east-1" logLevel := aws.LogOff @@ -47,9 +55,16 @@ func NewS3Agent(accessKey, secretKey, endpoint string, debug bool, tlsCert []byt Timeout: HttpTimeOut, } tlsEnabled := false - if len(tlsCert) > 0 { - client.Transport = BuildTransportTLS(tlsCert) + if len(tlsCert) > 0 || insecure { tlsEnabled = true + if len(tlsCert) > 0 { + client.Transport = BuildTransportTLS(tlsCert) + } else if insecure { + client.Transport = &http.Transport{ + // #nosec G402 is enabled only for testing + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + } } sess, err := session.NewSession( aws.NewConfig(). diff --git a/tests/framework/clients/object.go b/tests/framework/clients/object.go index 6fdbc74177fb..587d43cc4657 100644 --- a/tests/framework/clients/object.go +++ b/tests/framework/clients/object.go @@ -40,10 +40,10 @@ func CreateObjectOperation(k8sh *utils.K8sHelper, manifests installer.CephManife } // ObjectCreate Function to create a object store in rook -func (o *ObjectOperation) Create(namespace, storeName string, replicaCount int32) error { +func (o *ObjectOperation) Create(namespace, storeName string, replicaCount int32, tlsEnable bool) error { - logger.Infof("creating the object store via CRD") - if err := o.k8sh.ResourceOperation("apply", o.manifests.GetObjectStore(storeName, int(replicaCount), rgwPort)); err != nil { + logger.Info("creating the object store via CRD") + if err := o.k8sh.ResourceOperation("apply", o.manifests.GetObjectStore(storeName, int(replicaCount), rgwPort, tlsEnable)); err != nil { return err } diff --git a/tests/framework/clients/object_user.go b/tests/framework/clients/object_user.go index aee822228e64..6849624efc16 100644 --- a/tests/framework/clients/object_user.go +++ b/tests/framework/clients/object_user.go @@ -17,6 +17,7 @@ limitations under the License. package clients import ( + "context" "fmt" "strings" @@ -24,6 +25,7 @@ import ( rgw "github.com/rook/rook/pkg/operator/ceph/object" "github.com/rook/rook/tests/framework/installer" "github.com/rook/rook/tests/framework/utils" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // ObjectUserOperation is wrapper for k8s rook object user operations @@ -39,9 +41,16 @@ func CreateObjectUserOperation(k8sh *utils.K8sHelper, manifests installer.CephMa // ObjectUserGet Function to get the details of an object user from radosgw func (o *ObjectUserOperation) GetUser(namespace string, store string, userid string) (*rgw.ObjectUser, error) { - context := o.k8sh.MakeContext() + ctx := o.k8sh.MakeContext() clusterInfo := client.AdminClusterInfo(namespace) - rgwcontext := rgw.NewContext(context, clusterInfo, store) + objectStore, err := o.k8sh.RookClientset.CephV1().CephObjectStores(namespace).Get(context.TODO(), store, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get objectstore info: %+v", err) + } + rgwcontext, err := rgw.NewMultisiteContext(ctx, clusterInfo, objectStore) + if err != nil { + return nil, fmt.Errorf("failed to get RGW context: %+v", err) + } userinfo, _, err := rgw.GetUser(rgwcontext, userid) if err != nil { return nil, fmt.Errorf("failed to get user info: %+v", err) diff --git a/tests/framework/installer/ceph_manifests.go b/tests/framework/installer/ceph_manifests.go index ef91617667b9..d7e871f9e8fd 100644 --- a/tests/framework/installer/ceph_manifests.go +++ b/tests/framework/installer/ceph_manifests.go @@ -42,7 +42,7 @@ type CephManifests interface { GetFilesystem(name string, activeCount int) string GetNFS(name, pool string, daemonCount int) string GetRBDMirror(name string, daemonCount int) string - GetObjectStore(name string, replicaCount, port int) string + GetObjectStore(name string, replicaCount, port int, tlsEnable bool) string GetObjectStoreUser(name, displayName, store string) string GetBucketStorageClass(storeName, storageClassName, reclaimPolicy, region string) string GetOBC(obcName, storageClassName, bucketName string, maxObject string, createBucket bool) string @@ -385,7 +385,34 @@ spec: active: ` + strconv.Itoa(count) } -func (m *CephManifestsMaster) GetObjectStore(name string, replicaCount, port int) string { +func (m *CephManifestsMaster) GetObjectStore(name string, replicaCount, port int, tlsEnable bool) string { + if tlsEnable { + return `apiVersion: ceph.rook.io/v1 +kind: CephObjectStore +metadata: + name: ` + name + ` + namespace: ` + m.settings.Namespace + ` +spec: + metadataPool: + replicated: + size: 1 + requireSafeReplicaSize: false + compressionMode: passive + dataPool: + replicated: + size: 1 + requireSafeReplicaSize: false + gateway: + type: s3 + securePort: ` + strconv.Itoa(port) + ` + instances: ` + strconv.Itoa(replicaCount) + ` + sslCertificateRef: ` + name + ` + healthCheck: + bucket: + disabled: false + interval: 10s +` + } return `apiVersion: ceph.rook.io/v1 kind: CephObjectStore metadata: diff --git a/tests/framework/installer/ceph_manifests_v1.5.go b/tests/framework/installer/ceph_manifests_v1.5.go index ed4d68f076b0..7b60134bc3c8 100644 --- a/tests/framework/installer/ceph_manifests_v1.5.go +++ b/tests/framework/installer/ceph_manifests_v1.5.go @@ -336,7 +336,7 @@ spec: active: ` + strconv.Itoa(count) } -func (m *CephManifestsV1_5) GetObjectStore(name string, replicaCount, port int) string { +func (m *CephManifestsV1_5) GetObjectStore(name string, replicaCount, port int, tlsEnable bool) string { return `apiVersion: ceph.rook.io/v1 kind: CephObjectStore metadata: diff --git a/tests/integration/ceph_base_object_test.go b/tests/integration/ceph_base_object_test.go index 8f85f527b23a..99adf7deca59 100644 --- a/tests/integration/ceph_base_object_test.go +++ b/tests/integration/ceph_base_object_test.go @@ -19,6 +19,10 @@ package integration import ( "context" "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" "testing" "time" @@ -30,6 +34,7 @@ import ( "github.com/rook/rook/tests/framework/installer" "github.com/rook/rook/tests/framework/utils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -53,19 +58,106 @@ var ( // Smoke Test for ObjectStore - Test check the following operations on ObjectStore in order // Create object store, Create User, Connect to Object Store, Create Bucket, Read/Write/Delete to bucket, // Check issues in MGRs, Delete Bucket and Delete user +// Test for ObjectStore with and without TLS enabled func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite.Suite, namespace string) { - ctx := context.TODO() storeName := "teststore" - defer objectStoreCleanUp(s, helper, k8sh, namespace, storeName) - t := s.T() + logger.Info("Object Storage End To End Integration Test without TLS - Create Object Store, User,Bucket and read/write to bucket") + logger.Info("Running on Rook Cluster %s", namespace) + createCephObjectStore(s, helper, k8sh, namespace, storeName, 3, false) + testObjectStoreOperations(s, helper, k8sh, namespace, storeName) + + storeName = "tlsteststore" + logger.Info("Object Storage End To End Integration Test with TLS enabled - Create Object Store, User,Bucket and read/write to bucket") + createCephObjectStore(s, helper, k8sh, namespace, storeName, 3, true) + testObjectStoreOperations(s, helper, k8sh, namespace, storeName) +} - logger.Infof("Object Storage End To End Integration Test - Create Object Store, User,Bucket and read/write to bucket") - logger.Infof("Running on Rook Cluster %s", namespace) - clusterInfo := client.AdminClusterInfo(namespace) +// Test Object StoreCreation on Rook that was installed via helm +func runObjectE2ETestLite(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite.Suite, settings *installer.TestCephSettings, name string, replicaSize int, deleteStore bool) { + logger.Infof("Object Storage End To End Integration Test - Create Object Store and check if rgw service is Running") + logger.Infof("Running on Rook Cluster %s", settings.Namespace) + + logger.Infof("Step 1 : Create Object Store") + err := helper.ObjectClient.Create(settings.Namespace, name, int32(replicaSize), false) + assert.Nil(s.T(), err) + + logger.Infof("Step 2 : check rook-ceph-rgw service status and count") + assert.True(s.T(), k8sh.IsPodInExpectedState("rook-ceph-rgw", settings.Namespace, "Running"), + "Make sure rook-ceph-rgw is in running state") + + assert.True(s.T(), k8sh.CheckPodCountAndState("rook-ceph-rgw", settings.Namespace, replicaSize, "Running"), + "Make sure all rook-ceph-rgw pods are in Running state") + + assert.True(s.T(), k8sh.IsServiceUp("rook-ceph-rgw-"+name, settings.Namespace)) + + if deleteStore { + logger.Infof("Delete Object Store") + err = helper.ObjectClient.Delete(settings.Namespace, name) + assert.Nil(s.T(), err) + logger.Infof("Done deleting object store") + } +} + +func objectStoreCleanUp(s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, namespace, storeName string) { + logger.Infof("Delete Object Store (will fail if users and buckets still exist)") + err := helper.ObjectClient.Delete(namespace, storeName) + assert.Nil(s.T(), err) + logger.Infof("Done deleting object store") +} + +func createCephObjectUser( + s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, + namespace, storeName, userID string, + checkPhase bool, +) { + s.T().Helper() + + cosuErr := helper.ObjectUserClient.Create(namespace, userID, userdisplayname, storeName) + assert.Nil(s.T(), cosuErr) + logger.Infof("Waiting 5 seconds for the object user to be created") + time.Sleep(5 * time.Second) + logger.Infof("Checking to see if the user secret has been created") + for i := 0; i < 6 && helper.ObjectUserClient.UserSecretExists(namespace, storeName, userID) == false; i++ { + logger.Infof("(%d) secret check sleeping for 5 seconds ...", i) + time.Sleep(5 * time.Second) + } + + checkCephObjectUser(s, helper, k8sh, namespace, storeName, userID, checkPhase) +} + +func checkCephObjectUser( + s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, + namespace, storeName, userID string, + checkPhase bool, +) { + s.T().Helper() + logger.Infof("checking object store \"%s/%s\" user %q", namespace, storeName, userID) + assert.True(s.T(), helper.ObjectUserClient.UserSecretExists(namespace, storeName, userID)) + + userInfo, err := helper.ObjectUserClient.GetUser(namespace, storeName, userID) + assert.NoError(s.T(), err) + assert.Equal(s.T(), userID, userInfo.UserID) + assert.Equal(s.T(), userdisplayname, *userInfo.DisplayName) + + if checkPhase { + // status.phase doesn't exist before Rook v1.6 + phase, err := k8sh.GetResource("--namespace", namespace, "cephobjectstoreuser", userID, "--output", "jsonpath={.status.phase}") + assert.NoError(s.T(), err) + assert.Equal(s.T(), k8sutil.ReadyStatus, phase) + } +} + +func createCephObjectStore(s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, namespace, storeName string, replicaSize int, tlsEnable bool) { + logger.Infof("Create Object Store %q with replica count %d", storeName, replicaSize) + rgwServiceName := "rook-ceph-rgw-" + storeName + if tlsEnable { + generateRgwTlsCertSecret(s, helper, k8sh, namespace, storeName, rgwServiceName) + } + t := s.T() t.Run("create CephObjectStore", func(t *testing.T) { - cobsErr := helper.ObjectClient.Create(namespace, storeName, 3) - assert.Nil(s.T(), cobsErr) + err := helper.ObjectClient.Create(namespace, storeName, 3, tlsEnable) + assert.Nil(s.T(), err) // check that ObjectStore is created logger.Infof("Check that RGW pods are Running") @@ -74,10 +166,15 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite time.Sleep(5 * time.Second) } assert.True(s.T(), k8sh.CheckPodCountAndState("rook-ceph-rgw", namespace, 1, "Running")) - logger.Infof("RGW pods are running") - logger.Infof("Object store created successfully") + logger.Info("RGW pods are running") + logger.Infof("Object store %q created successfully", storeName) }) +} +func testObjectStoreOperations(s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, namespace, storeName string) { + ctx := context.TODO() + clusterInfo := client.AdminClusterInfo(namespace) + t := s.T() t.Run("create CephObjectStoreUser", func(t *testing.T) { createCephObjectUser(s, helper, k8sh, namespace, storeName, userid, true) i := 0 @@ -85,7 +182,7 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite if helper.ObjectUserClient.UserSecretExists(namespace, storeName, userid) { break } - logger.Infof("waiting 5 more seconds for user secret to exist") + logger.Info("waiting 5 more seconds for user secret to exist") time.Sleep(5 * time.Second) } assert.NotEqual(t, 4, i) @@ -112,8 +209,10 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite }) context := k8sh.MakeContext() - rgwcontext := rgw.NewContext(context, clusterInfo, storeName) - + objectStore, err := k8sh.RookClientset.CephV1().CephObjectStores(namespace).Get(ctx, storeName, metav1.GetOptions{}) + assert.Nil(s.T(), err) + rgwcontext, err := rgw.NewMultisiteContext(context, clusterInfo, objectStore) + assert.Nil(s.T(), err) t.Run("create ObjectBucketClaim with reclaim policy delete", func(t *testing.T) { cobErr := helper.BucketClient.CreateBucketStorageClass(namespace, storeName, bucketStorageClassName, "Delete", region) assert.Nil(s.T(), cobErr) @@ -144,10 +243,16 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite }) t.Run("use S3 client to put and get objects on OBC bucket", func(t *testing.T) { + var s3client *rgw.S3Agent s3endpoint, _ := helper.ObjectClient.GetEndPointUrl(namespace, storeName) s3AccessKey, _ := helper.BucketClient.GetAccessKey(obcName) s3SecretKey, _ := helper.BucketClient.GetSecretKey(obcName) - s3client, err := rgw.NewS3Agent(s3AccessKey, s3SecretKey, s3endpoint, true, nil) + if objectStore.Spec.IsTLSEnabled() { + s3client, err = rgw.NewTestOnlyS3Agent(s3AccessKey, s3SecretKey, s3endpoint, true) + } else { + s3client, err = rgw.NewS3Agent(s3AccessKey, s3SecretKey, s3endpoint, true, nil) + } + assert.Nil(s.T(), err) logger.Infof("endpoint (%s) Accesskey (%s) secret (%s)", s3endpoint, s3AccessKey, s3SecretKey) @@ -175,7 +280,7 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite assert.Nil(s.T(), delobjErr) _, delobjErr = s3client.DeleteObjectInBucket(bucketname, ObjectKey2) assert.Nil(s.T(), delobjErr) - logger.Infof("Objects deleted on bucket successfully") + logger.Info("Objects deleted on bucket successfully") }) }) @@ -209,7 +314,7 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite if cond != nil { break } - logger.Infof("waiting 2 more seconds for CephObjectStore to reach Deleting state") + logger.Info("waiting 2 more seconds for CephObjectStore to reach Deleting state") time.Sleep(2 * time.Second) } assert.NotEqual(t, 4, i) @@ -234,14 +339,14 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite i := 0 dobcErr := helper.BucketClient.DeleteObc(obcName, bucketStorageClassName, bucketname, maxObject, true) assert.Nil(s.T(), dobcErr) - logger.Infof("Checking to see if the obc, secret and cm have all been deleted") + logger.Info("Checking to see if the obc, secret and cm have all been deleted") for i = 0; i < 4 && !helper.BucketClient.CheckOBC(obcName, "deleted"); i++ { logger.Infof("(%d) obc deleted check, sleeping for 5 seconds ...", i) time.Sleep(5 * time.Second) } assert.NotEqual(s.T(), 4, i) - logger.Infof("ensure OBC bucket was deleted") + logger.Info("ensure OBC bucket was deleted") var rgwErr int for i = 0; i < 4; i++ { _, rgwErr, _ = rgw.GetBucket(rgwcontext, bucketname) @@ -261,8 +366,8 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite t.Run("delete CephObjectStoreUser", func(t *testing.T) { dosuErr := helper.ObjectUserClient.Delete(namespace, userid) assert.Nil(s.T(), dosuErr) - logger.Infof("Object store user deleted successfully") - logger.Infof("Checking to see if the user secret has been deleted") + logger.Info("Object store user deleted successfully") + logger.Info("Checking to see if the user secret has been deleted") i := 0 for i = 0; i < 4 && helper.ObjectUserClient.UserSecretExists(namespace, storeName, userid) == true; i++ { logger.Infof("(%d) secret check sleeping for 5 seconds ...", i) @@ -293,7 +398,7 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite if cond.Status == v1.ConditionFalse { break } - logger.Infof("waiting 3 more seconds for CephObjectStore to be unblocked by dependents") + logger.Info("waiting 3 more seconds for CephObjectStore to be unblocked by dependents") time.Sleep(3 * time.Second) } assert.NotEqual(t, 4, i) @@ -310,79 +415,33 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite // TODO : Add case for brownfield/cleanup s3 client} } - -// Test Object StoreCreation on Rook that was installed via helm -func runObjectE2ETestLite(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite.Suite, settings *installer.TestCephSettings, name string, replicaSize int, deleteStore bool) { - logger.Infof("Object Storage End To End Integration Test - Create Object Store and check if rgw service is Running") - logger.Infof("Running on Rook Cluster %s", settings.Namespace) - - logger.Infof("Step 1 : Create Object Store") - err := helper.ObjectClient.Create(settings.Namespace, name, int32(replicaSize)) - assert.Nil(s.T(), err) - - logger.Infof("Step 2 : check rook-ceph-rgw service status and count") - assert.True(s.T(), k8sh.IsPodInExpectedState("rook-ceph-rgw", settings.Namespace, "Running"), - "Make sure rook-ceph-rgw is in running state") - - assert.True(s.T(), k8sh.CheckPodCountAndState("rook-ceph-rgw", settings.Namespace, replicaSize, "Running"), - "Make sure all rook-ceph-rgw pods are in Running state") - - assert.True(s.T(), k8sh.IsServiceUp("rook-ceph-rgw-"+name, settings.Namespace)) - - if deleteStore { - logger.Infof("Delete Object Store") - err = helper.ObjectClient.Delete(settings.Namespace, name) - assert.Nil(s.T(), err) - logger.Infof("Done deleting object store") - } -} - -func objectStoreCleanUp(s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, namespace, storeName string) { - logger.Infof("Delete Object Store (will fail if users and buckets still exist)") - err := helper.ObjectClient.Delete(namespace, storeName) - assert.Nil(s.T(), err) - logger.Infof("Done deleting object store") -} - -func createCephObjectUser( - s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, - namespace, storeName, userID string, - checkPhase bool, -) { - s.T().Helper() - - cosuErr := helper.ObjectUserClient.Create(namespace, userID, userdisplayname, storeName) - assert.Nil(s.T(), cosuErr) - logger.Infof("Waiting 5 seconds for the object user to be created") - time.Sleep(5 * time.Second) - logger.Infof("Checking to see if the user secret has been created") - for i := 0; i < 6 && helper.ObjectUserClient.UserSecretExists(namespace, storeName, userID) == false; i++ { - logger.Infof("(%d) secret check sleeping for 5 seconds ...", i) - time.Sleep(5 * time.Second) - } - - checkCephObjectUser(s, helper, k8sh, namespace, storeName, userID, checkPhase) -} - -func checkCephObjectUser( - s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, - namespace, storeName, userID string, - checkPhase bool, -) { - s.T().Helper() - - logger.Infof("checking object store \"%s/%s\" user %q", namespace, storeName, userID) - assert.True(s.T(), helper.ObjectUserClient.UserSecretExists(namespace, storeName, userID)) - - userInfo, err := helper.ObjectUserClient.GetUser(namespace, storeName, userID) - assert.NoError(s.T(), err) - assert.Equal(s.T(), userID, userInfo.UserID) - assert.Equal(s.T(), userdisplayname, *userInfo.DisplayName) - - if checkPhase { - // status.phase doesn't exist before Rook v1.6 - phase, err := k8sh.GetResource("--namespace", namespace, "cephobjectstoreuser", userID, "--output", "jsonpath={.status.phase}") - assert.NoError(s.T(), err) - assert.Equal(s.T(), k8sutil.ReadyStatus, phase) +func generateRgwTlsCertSecret(s suite.Suite, helper *clients.TestClient, k8sh *utils.K8sHelper, namespace, storeName, rgwServiceName string) { + ctx := context.TODO() + root, err := utils.FindRookRoot() + require.NoError(s.T(), err, "failed to get rook root") + tlscertdir, err := ioutil.TempDir(root, "tlscertdir") + require.NoError(s.T(), err, "failed to create directory for TLS certs") + defer os.RemoveAll(tlscertdir) + cmdArgs := utils.CommandArgs{Command: filepath.Join(root, "tests/scripts/github-action-helper.sh"), + CmdArgs: []string{"generate_tls_config", tlscertdir, rgwServiceName, namespace}} + cmdOut := utils.ExecuteCommand(cmdArgs) + require.NoError(s.T(), cmdOut.Err) + tlsKeyIn, err := ioutil.ReadFile(filepath.Join(tlscertdir, rgwServiceName+".key")) + require.NoError(s.T(), err) + tlsCertIn, err := ioutil.ReadFile(filepath.Join(tlscertdir, rgwServiceName+".crt")) + require.NoError(s.T(), err) + tlsCaCertIn, err := ioutil.ReadFile(filepath.Join(tlscertdir, rgwServiceName+".ca")) + require.NoError(s.T(), err) + secretCertOut := fmt.Sprintf("%s%s%s", tlsKeyIn, tlsCertIn, tlsCaCertIn) + tlsK8sSecret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: storeName, + Namespace: namespace, + }, + Data: map[string][]byte{ + "cert": []byte(secretCertOut), + }, } + _, err = k8sh.Clientset.CoreV1().Secrets(namespace).Create(ctx, tlsK8sSecret, metav1.CreateOptions{}) + require.Nil(s.T(), err) } diff --git a/tests/scripts/github-action-helper.sh b/tests/scripts/github-action-helper.sh index 184d6d7e10e5..f5856163e0a1 100755 --- a/tests/scripts/github-action-helper.sh +++ b/tests/scripts/github-action-helper.sh @@ -178,9 +178,68 @@ function create_LV_on_disk() { kubectl create -f cluster/examples/kubernetes/ceph/common.yaml } +function generate_tls_config { +DIR=$1 +SERVICE=$2 +NAMESPACE=$3 +IP=$4 +if [ -z "${IP}" ]; then + IP=127.0.0.1 +fi + + openssl genrsa -out "${DIR}"/"${SERVICE}".key 2048 + + cat <"${DIR}"/csr.conf +[req] +req_extensions = v3_req +distinguished_name = req_distinguished_name +[req_distinguished_name] +[ v3_req ] +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names +[alt_names] +DNS.1 = ${SERVICE} +DNS.2 = ${SERVICE}.${NAMESPACE} +DNS.3 = ${SERVICE}.${NAMESPACE}.svc +DNS.4 = ${SERVICE}.${NAMESPACE}.svc.cluster.local +IP.1 = ${IP} +EOF + + openssl req -new -key "${DIR}"/"${SERVICE}".key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out "${DIR}"/server.csr -config "${DIR}"/csr.conf + + export CSR_NAME=${SERVICE}-csr + + cat <"${DIR}"/csr.yaml +apiVersion: certificates.k8s.io/v1beta1 +kind: CertificateSigningRequest +metadata: + name: ${CSR_NAME} +spec: + groups: + - system:authenticated + request: $(cat ${DIR}/server.csr | base64 | tr -d '\n') + usages: + - digital signature + - key encipherment + - server auth +EOF + + kubectl create -f "${DIR}/"csr.yaml + + kubectl certificate approve ${CSR_NAME} + + serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}') + echo "${serverCert}" | openssl base64 -d -A -out "${DIR}"/"${SERVICE}".crt + kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > "${DIR}"/"${SERVICE}".ca +} + selected_function="$1" -if [ "$selected_function" = "wait_for_ceph_to_be_ready" ]; then - $selected_function $2 $3 +if [ "$selected_function" = "generate_tls_config" ]; then + $selected_function $2 $3 $4 $5 +elif [ "$selected_function" = "wait_for_ceph_to_be_ready" ]; then + $selected_function $2 $3 else $selected_function fi