From 05b21e0a7bb84681081583d6432581cdd06ae47c Mon Sep 17 00:00:00 2001 From: pulkitM1 Date: Wed, 29 Jan 2025 22:22:33 +0530 Subject: [PATCH] CBQE-8314: Adding methods to enable log and config encryption for onPremBase Change-Id: Ibd421d71b441acbad12535c2a07e7a584126b384 Reviewed-on: https://review.couchbase.org/c/TAF/+/222608 Reviewed-by: Ashwin Tested-by: Build Bot --- .../cluster_utils/cluster_ready_functions.py | 43 +++++++++ .../bucket_collections/collections_base.py | 14 +-- pytests/onPrem_basetestcase.py | 87 +++++++++++++++++++ 3 files changed, 131 insertions(+), 13 deletions(-) diff --git a/couchbase_utils/cluster_utils/cluster_ready_functions.py b/couchbase_utils/cluster_utils/cluster_ready_functions.py index 3b270268e..ad8bb6f40 100644 --- a/couchbase_utils/cluster_utils/cluster_ready_functions.py +++ b/couchbase_utils/cluster_utils/cluster_ready_functions.py @@ -170,6 +170,49 @@ def __init__(self, task_manager): self.task_manager = task_manager self.log = logger.get("test") + @staticmethod + def create_secret_params(secret_type="auto-generated-aes-key-256", + name="Default secret", usage=None, + autoRotation=True, rotationIntervalInDays=60, + rotationIntervalInSeconds=None, keyARN=None, + region=None, useIMDS=None, credentialsFile=None, + configFile=None, profile=None): + if usage is None: + usage = ["bucket-encryption-*"] + + data = { + "autoRotation": autoRotation, + "rotationIntervalInDays": rotationIntervalInDays + } + + if rotationIntervalInSeconds is not None: + data["nextRotationTime"] = (datetime.utcnow() + timedelta( + seconds=rotationIntervalInSeconds)).isoformat() + "Z" + else: + data["nextRotationTime"] = (datetime.utcnow() + timedelta( + days=rotationIntervalInDays)).isoformat() + "Z" + + if keyARN is not None: + data["keyARN"] = keyARN + if region is not None: + data["region"] = region + if useIMDS is not None: + data["useIMDS"] = useIMDS + if credentialsFile is not None: + data["credentialsFile"] = credentialsFile + if configFile is not None: + data["configFile"] = configFile + if profile is not None: + data["profile"] = profile + + params = { + "type": secret_type, + "name": name, + "usage": usage, + "data": data + } + return params + @staticmethod def flush_network_rules(node): shell = RemoteMachineShellConnection(node) diff --git a/pytests/bucket_collections/collections_base.py b/pytests/bucket_collections/collections_base.py index 0ffa1df03..bf6fc238e 100644 --- a/pytests/bucket_collections/collections_base.py +++ b/pytests/bucket_collections/collections_base.py @@ -581,18 +581,6 @@ def deploy_buckets_from_spec_file(test_obj): # If True, creates bucket/scope/collections with simpler names use_simple_names = test_obj.input.param("use_simple_names", True) - # enable encryption at rest - if test_obj.enable_encryption_at_rest: - params = BucketHelper(test_obj.cluster.master).create_secret_params( - usage=["bucket-encryption-*"], - rotationIntervalInSeconds=test_obj.rotationIntervalInSeconds, - ) - status, response = RestConnection( - test_obj.cluster.master).create_secret(params) - test_obj.assertTrue(status, "failed to create encryption at rest secret key") - response_dict = json.loads(response) - test_obj.secret_id = response_dict.get('id') - # Create bucket(s) and add rbac user buckets_spec = \ test_obj.bucket_util.get_bucket_template_from_package( @@ -608,7 +596,7 @@ def deploy_buckets_from_spec_file(test_obj): CollectionBase.over_ride_bucket_template_params( test_obj, test_obj.bucket_storage, buckets_spec) if test_obj.enable_encryption_at_rest: - buckets_spec[Bucket.encryptionAtRestSecretId] = test_obj.secret_id + buckets_spec[Bucket.encryptionAtRestSecretId] = test_obj.encryption_at_rest_id buckets_spec[Bucket.encryptionAtRestDekRotationInterval] = \ test_obj.encryptionAtRestDekRotationInterval test_obj.log.info("Encryption at rest enabled") diff --git a/pytests/onPrem_basetestcase.py b/pytests/onPrem_basetestcase.py index 20c73e1fb..0065b2b85 100644 --- a/pytests/onPrem_basetestcase.py +++ b/pytests/onPrem_basetestcase.py @@ -1,3 +1,4 @@ +import json import time from datetime import datetime import os @@ -97,6 +98,26 @@ def setUp(self): self.encryption_level = self.input.param("encryption_level", "all") self.enable_encryption_at_rest = self.input.param( "enable_encryption_at_rest", False) + self.encryption_at_rest_id = self.input.param( + "encryption_at_rest_id", None) + self.enable_config_encryption_at_rest = self.input.param( + "enable_config_encryption_at_rest", False) + self.config_encryption_at_rest_id = self.input.param( + "config_encryption_at_rest_id", None) + self.enable_log_encryption_at_rest = self.input.param( + "enable_log_encryption_at_rest", False) + self.log_encryption_at_rest_id = self.input.param( + "log_encryption_at_rest_id", False) + self.secret_rotation_interval = self.input.param( + "secret_rotation_interval", 60) + self.config_dekLifetime = self.input.param( + "config_dekLifetime", CbServer.secret_rotation_interval_in_seconds) + self.log_dekLifetime = self.input.param( + "log_dekLifetime", CbServer.secret_rotation_interval_in_seconds) + self.config_dekRotationInterval = self.input.param( + "config_dekRotationInterval", CbServer.encryption_at_rest_dek_rotation_interval) + self.log_dekRotationInterval = self.input.param( + "log_dekRotationInterval", CbServer.encryption_at_rest_dek_rotation_interval) self.secret_id = self.input.param("secret_id", None) self.encryptionAtRestDekRotationInterval = self.input.param( "encryptionAtRestDekRotationInterval", CbServer.encryption_at_rest_dek_rotation_interval) @@ -365,6 +386,72 @@ def setUp(self): # Enforce tls on nodes of all clusters self.enable_tls_on_nodes() + # Creating encryption keys + if self.enable_encryption_at_rest: + self.log.info("Initializing encryption at rest") + log_params = ClusterUtils.create_secret_params( + name="EncryptionSecret", + rotationIntervalInSeconds=self.secret_rotation_interval + ) + rest = RestConnection(self.cluster.master) + status, response = rest.create_secret(log_params) + response_dict = json.loads(response) + self.encryption_at_rest_id = response_dict.get('id') + self.log.info("Encryption at rest ID: {0}".format( + self.encryption_at_rest_id)) + + if self.enable_config_encryption_at_rest: + self.log.info("Initializing config encryption at rest") + log_params = ClusterUtils.create_secret_params( + name="LogEncryptionSecret", + usage=["config-encryption"], + rotationIntervalInSeconds=self.secret_rotation_interval + ) + rest = RestConnection(self.cluster.master) + status, response = rest.create_secret(log_params) + response_dict = json.loads(response) + self.config_encryption_at_rest_id = response_dict.get('id') + self.log.info("Config encryption at rest ID: {0}".format( + self.config_encryption_at_rest_id)) + valid_params = { + "config.encryptionMethod": "encryptionKey", + "config.encryptionKeyId": self.config_encryption_at_rest_id, + "config.dekLifetime": self.config_dekLifetime, + "config.dekRotationInterval": self.config_dekRotationInterval + } + status, response = rest.configure_encryption_at_rest( + valid_params) + self.log.info( + "Config encryption at rest status: {0}".format(status)) + self.assertTrue(status, + "Failed to enable config encryption values") + + if self.enable_log_encryption_at_rest: + self.log.info("Initializing log encryption at rest") + log_params = ClusterUtils.create_secret_params( + name="ConfigEncryptionSecret", + usage=["log-encryption"], + rotationIntervalInSeconds=self.secret_rotation_interval + ) + rest = RestConnection(self.cluster.master) + status, response = rest.create_secret(log_params) + response_dict = json.loads(response) + self.log_encryption_at_rest_id = response_dict.get('id') + self.log.info("Log encryption at rest ID: {0}".format( + self.log_encryption_at_rest_id)) + valid_params = { + "log.encryptionMethod": "encryptionKey", + "log.encryptionKeyId": self.log_encryption_at_rest_id, + "log.dekLifetime": self.log_dekLifetime, + "log.dekRotationInterval": self.log_dekRotationInterval + } + status, response = rest.configure_encryption_at_rest( + valid_params) + self.log.info( + "Log encryption at rest status: {0}".format(status)) + self.assertTrue(status, + "Failed to set valid log encryption values") + if self.use_https: if ClusterRun.is_enabled: for index, server in enumerate(self.input.servers):