From 98809bccd13f6374303e00ce9663ec679b20a791 Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Mon, 8 Aug 2022 18:05:02 +0530 Subject: [PATCH] mgr/dashboard: add server side encryption to rgw/s3 Fixes:https://tracker.ceph.com/issues/57826 Signed-off-by: Aashish Sharma (cherry picked from commit 42aa2283c2aea6059586cf3bb213a127d8879a45) --- src/pybind/mgr/dashboard/controllers/rgw.py | 65 ++++- .../ceph/rgw/models/rgw-bucket-encryption.ts | 7 + .../rgw-bucket-details.component.html | 5 + .../rgw-bucket-form.component.html | 105 ++++++++ .../rgw-bucket-form.component.ts | 94 ++++++- .../rgw-config-modal.component.html | 251 ++++++++++++++++++ .../rgw-config-modal.component.scss | 0 .../rgw-config-modal.component.spec.ts | 38 +++ .../rgw-config-modal.component.ts | 144 ++++++++++ .../frontend/src/app/ceph/rgw/rgw.module.ts | 4 +- .../app/shared/api/rgw-bucket.service.spec.ts | 32 ++- .../src/app/shared/api/rgw-bucket.service.ts | 83 +++++- src/pybind/mgr/dashboard/openapi.yaml | 176 ++++++++++++ .../mgr/dashboard/services/ceph_service.py | 109 +++++++- .../mgr/dashboard/services/rgw_client.py | 45 ++++ src/pybind/mgr/mgr_util.py | 16 +- 16 files changed, 1148 insertions(+), 26 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-bucket-encryption.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-config-modal/rgw-config-modal.component.html create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-config-modal/rgw-config-modal.component.scss create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-config-modal/rgw-config-modal.component.spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-config-modal/rgw-config-modal.component.ts diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index f42b91a0e940e..104a5a40d35fe 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -197,6 +197,28 @@ class RgwBucket(RgwRESTController): rgw_client.set_bucket_versioning(bucket_name, versioning_state, mfa_delete, mfa_token_serial, mfa_token_pin) + def _set_encryption(self, bid, encryption_type, key_id, daemon_name, owner): + + rgw_client = RgwClient.instance(owner, daemon_name) + rgw_client.set_bucket_encryption(bid, key_id, encryption_type) + + # pylint: disable=W0613 + def _set_encryption_config(self, encryption_type, kms_provider, auth_method, secret_engine, + secret_path, namespace, address, token, daemon_name, owner, + ssl_cert, client_cert, client_key): + + CephService.set_encryption_config(encryption_type, kms_provider, auth_method, + secret_engine, secret_path, namespace, address, + token, ssl_cert, client_cert, client_key) + + def _get_encryption(self, bucket_name, daemon_name, owner): + rgw_client = RgwClient.instance(owner, daemon_name) + return rgw_client.get_bucket_encryption(bucket_name) + + def _delete_encryption(self, bucket_name, daemon_name, owner): + rgw_client = RgwClient.instance(owner, daemon_name) + return rgw_client.delete_bucket_encryption(bucket_name) + def _get_locking(self, owner, daemon_name, bucket_name): rgw_client = RgwClient.instance(owner, daemon_name) return rgw_client.get_bucket_locking(bucket_name) @@ -256,6 +278,8 @@ class RgwBucket(RgwRESTController): # Append the versioning configuration. versioning = self._get_versioning(result['owner'], daemon_name, bucket_name) + encryption = self._get_encryption(bucket_name, daemon_name, result['owner']) + result['encryption'] = encryption['Status'] result['versioning'] = versioning['Status'] result['mfa_delete'] = versioning['MfaDelete'] @@ -269,8 +293,10 @@ class RgwBucket(RgwRESTController): def create(self, bucket, uid, zonegroup=None, placement_target=None, lock_enabled='false', lock_mode=None, lock_retention_period_days=None, - lock_retention_period_years=None, daemon_name=None): + lock_retention_period_years=None, encryption_state='false', + encryption_type=None, key_id=None, daemon_name=None): lock_enabled = str_to_bool(lock_enabled) + encryption_state = str_to_bool(encryption_state) try: rgw_client = RgwClient.instance(uid, daemon_name) result = rgw_client.create_bucket(bucket, zonegroup, @@ -280,15 +306,21 @@ class RgwBucket(RgwRESTController): self._set_locking(uid, daemon_name, bucket, lock_mode, lock_retention_period_days, lock_retention_period_years) + + if encryption_state: + self._set_encryption(bucket, encryption_type, key_id, daemon_name, uid) + return result except RequestException as e: # pragma: no cover - handling is too obvious raise DashboardException(e, http_status_code=500, component='rgw') @allow_empty_body def set(self, bucket, bucket_id, uid, versioning_state=None, + encryption_state='false', encryption_type=None, key_id=None, mfa_delete=None, mfa_token_serial=None, mfa_token_pin=None, lock_mode=None, lock_retention_period_days=None, lock_retention_period_years=None, daemon_name=None): + encryption_state = str_to_bool(encryption_state) # When linking a non-tenant-user owned bucket to a tenanted user, we # need to prefix bucket name with '/'. e.g. photos -> /photos if '$' in uid and '/' not in bucket: @@ -322,6 +354,11 @@ class RgwBucket(RgwRESTController): lock_retention_period_days, lock_retention_period_years) + encryption_status = self._get_encryption(bucket_name, daemon_name, uid) + if encryption_state and encryption_status['Status'] != 'Enabled': + self._set_encryption(bucket_name, encryption_type, key_id, daemon_name, uid) + if encryption_status['Status'] == 'Enabled' and (not encryption_state): + self._delete_encryption(bucket_name, daemon_name, uid) return self._append_bid(result) def delete(self, bucket, purge_objects='true', daemon_name=None): @@ -330,6 +367,32 @@ class RgwBucket(RgwRESTController): 'purge-objects': purge_objects }, json_response=False) + @RESTController.Collection(method='PUT', path='/setEncryptionConfig') + @allow_empty_body + def set_encryption_config(self, encryption_type=None, kms_provider=None, auth_method=None, + secret_engine=None, secret_path='', namespace='', address=None, + token=None, daemon_name=None, owner=None, ssl_cert=None, + client_cert=None, client_key=None): + return self._set_encryption_config(encryption_type, kms_provider, auth_method, + secret_engine, secret_path, namespace, + address, token, daemon_name, owner, ssl_cert, + client_cert, client_key) + + @RESTController.Collection(method='GET', path='/getEncryption') + @allow_empty_body + def get_encryption(self, bucket_name, daemon_name=None, owner=None): + return self._get_encryption(bucket_name, daemon_name, owner) + + @RESTController.Collection(method='DELETE', path='/deleteEncryption') + @allow_empty_body + def delete_encryption(self, bucket_name, daemon_name=None, owner=None): + return self._delete_encryption(bucket_name, daemon_name, owner) + + @RESTController.Collection(method='GET', path='/getEncryptionConfig') + @allow_empty_body + def get_encryption_config(self): + return CephService.get_encryption_config() + @APIRouter('/rgw/user', Scope.RGW) @APIDoc("RGW User Management API", "RgwUser") diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-bucket-encryption.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-bucket-encryption.ts new file mode 100644 index 0000000000000..e4f81f643c445 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-bucket-encryption.ts @@ -0,0 +1,7 @@ +export class RgwBucketEncryptionModel { + kmsProviders = ['vault']; + authMethods = ['token', 'agent']; + secretEngines = ['kv', 'transit']; + sse_s3 = 'AES256'; + sse_kms = 'aws:kms'; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html index bf4bdcb08d959..15b33e141229d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html @@ -61,6 +61,11 @@ class="bold">Versioning {{ selection.versioning }} + + Encryption + {{ selection.encryption }} + MFA Delete diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html index bad80a7f35887..4d2bc5ff2e12d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html @@ -279,6 +279,111 @@ +
+ Security +
+
+
+ + + + Enables encryption for the objects in the bucket. + To enable encryption on a bucket you need to set the configuration values for SSE-S3 or SSE-KMS. + To set the configuration values Click here + +
+
+
+ +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+ + This field is required. +
+
+
+ +
+
+ +
+ + This field is required. +
+
+
+
+
+