diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-23 16:45:17 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-23 16:45:44 +0000 |
commit | 17d6a993fc17d533460c5f40f3908c708e057c18 (patch) | |
tree | 1a3bd93e0ecd74fa02f93a528fe2f87e5314c4b5 /src/pybind/mgr/dashboard/controllers/rgw.py | |
parent | Releasing progress-linux version 18.2.2-0progress7.99u1. (diff) | |
download | ceph-17d6a993fc17d533460c5f40f3908c708e057c18.tar.xz ceph-17d6a993fc17d533460c5f40f3908c708e057c18.zip |
Merging upstream version 18.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/pybind/mgr/dashboard/controllers/rgw.py')
-rw-r--r-- | src/pybind/mgr/dashboard/controllers/rgw.py | 143 |
1 files changed, 131 insertions, 12 deletions
diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py index 9ccf4b36b..240d22f21 100644 --- a/src/pybind/mgr/dashboard/controllers/rgw.py +++ b/src/pybind/mgr/dashboard/controllers/rgw.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- +# pylint: disable=C0302 import json import logging import re @@ -134,6 +135,16 @@ class RgwDaemon(RESTController): for service in server['services']: metadata = service['metadata'] + frontend_config = metadata['frontend_config#0'] + port_match = re.search(r"port=(\d+)", frontend_config) + port = None + if port_match: + port = port_match.group(1) + else: + match_from_endpoint = re.search(r"endpoint=\S+:(\d+)", frontend_config) + if match_from_endpoint: + port = match_from_endpoint.group(1) + # extract per-daemon service data and health daemon = { 'id': metadata['id'], @@ -144,7 +155,7 @@ class RgwDaemon(RESTController): 'zonegroup_name': metadata['zonegroup_name'], 'zone_name': metadata['zone_name'], 'default': instance.daemon.name == metadata['id'], - 'port': int(re.findall(r'port=(\d+)', metadata['frontend_config#0'])[0]) + 'port': int(port) if port else None } daemons.append(daemon) @@ -276,6 +287,26 @@ class RgwBucket(RgwRESTController): retention_period_days, retention_period_years) + def _get_policy(self, bucket: str): + rgw_client = RgwClient.admin_instance() + return rgw_client.get_bucket_policy(bucket) + + def _set_policy(self, bucket_name: str, policy: str, daemon_name, owner): + rgw_client = RgwClient.instance(owner, daemon_name) + return rgw_client.set_bucket_policy(bucket_name, policy) + + def _set_tags(self, bucket_name, tags, daemon_name, owner): + rgw_client = RgwClient.instance(owner, daemon_name) + return rgw_client.set_tags(bucket_name, tags) + + def _get_acl(self, bucket_name, daemon_name, owner): + rgw_client = RgwClient.instance(owner, daemon_name) + return str(rgw_client.get_acl(bucket_name)) + + def _set_acl(self, bucket_name: str, acl: str, owner, daemon_name): + rgw_client = RgwClient.instance(owner, daemon_name) + return rgw_client.set_acl(bucket_name, acl) + @staticmethod def strip_tenant_from_bucket_name(bucket_name): # type (str) -> str @@ -328,6 +359,8 @@ class RgwBucket(RgwRESTController): result['encryption'] = encryption['Status'] result['versioning'] = versioning['Status'] result['mfa_delete'] = versioning['MfaDelete'] + result['bucket_policy'] = self._get_policy(bucket_name) + result['acl'] = self._get_acl(bucket_name, daemon_name, result['owner']) # Append the locking configuration. locking = self._get_locking(result['owner'], daemon_name, bucket_name) @@ -340,7 +373,8 @@ class RgwBucket(RgwRESTController): lock_enabled='false', lock_mode=None, lock_retention_period_days=None, lock_retention_period_years=None, encryption_state='false', - encryption_type=None, key_id=None, daemon_name=None): + encryption_type=None, key_id=None, tags=None, + bucket_policy=None, canned_acl=None, daemon_name=None): lock_enabled = str_to_bool(lock_enabled) encryption_state = str_to_bool(encryption_state) try: @@ -356,6 +390,15 @@ class RgwBucket(RgwRESTController): if encryption_state: self._set_encryption(bucket, encryption_type, key_id, daemon_name, uid) + if tags: + self._set_tags(bucket, tags, daemon_name, uid) + + if bucket_policy: + self._set_policy(bucket, bucket_policy, daemon_name, uid) + + if canned_acl: + self._set_acl(bucket, canned_acl, uid, daemon_name) + return result except RequestException as e: # pragma: no cover - handling is too obvious raise DashboardException(e, http_status_code=500, component='rgw') @@ -365,7 +408,8 @@ class RgwBucket(RgwRESTController): 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): + lock_retention_period_years=None, tags=None, bucket_policy=None, + canned_acl=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 @@ -405,6 +449,12 @@ class RgwBucket(RgwRESTController): 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) + if tags: + self._set_tags(bucket_name, tags, daemon_name, uid) + if bucket_policy: + self._set_policy(bucket_name, bucket_policy, daemon_name, uid) + if canned_acl: + self._set_acl(bucket_name, canned_acl, uid, daemon_name) return self._append_bid(result) def delete(self, bucket, purge_objects='true', daemon_name=None): @@ -540,7 +590,7 @@ class RgwUser(RgwRESTController): @allow_empty_body def create(self, uid, display_name, email=None, max_buckets=None, - suspended=None, generate_key=None, access_key=None, + system=None, suspended=None, generate_key=None, access_key=None, secret_key=None, daemon_name=None): params = {'uid': uid} if display_name is not None: @@ -549,6 +599,8 @@ class RgwUser(RgwRESTController): params['email'] = email if max_buckets is not None: params['max-buckets'] = max_buckets + if system is not None: + params['system'] = system if suspended is not None: params['suspended'] = suspended if generate_key is not None: @@ -562,7 +614,7 @@ class RgwUser(RgwRESTController): @allow_empty_body def set(self, uid, display_name=None, email=None, max_buckets=None, - suspended=None, daemon_name=None): + system=None, suspended=None, daemon_name=None): params = {'uid': uid} if display_name is not None: params['display-name'] = display_name @@ -570,6 +622,8 @@ class RgwUser(RgwRESTController): params['email'] = email if max_buckets is not None: params['max-buckets'] = max_buckets + if system is not None: + params['system'] = system if suspended is not None: params['suspended'] = suspended result = self.proxy(daemon_name, 'POST', 'user', params) @@ -702,6 +756,36 @@ class RGWRoleEndpoints: rgw_client.create_role(role_name, role_path, role_assume_policy_doc) return f'Role {role_name} created successfully' + @staticmethod + def role_update(_, role_name: str, max_session_duration: str): + assert role_name + assert max_session_duration + # convert max_session_duration which is in hours to seconds + max_session_duration = int(float(max_session_duration) * 3600) + rgw_client = RgwClient.admin_instance() + rgw_client.update_role(role_name, str(max_session_duration)) + return f'Role {role_name} updated successfully' + + @staticmethod + def role_delete(_, role_name: str): + assert role_name + rgw_client = RgwClient.admin_instance() + rgw_client.delete_role(role_name) + return f'Role {role_name} deleted successfully' + + @staticmethod + def model(role_name: str): + assert role_name + rgw_client = RgwClient.admin_instance() + role = rgw_client.get_role(role_name) + model = {'role_name': '', 'max_session_duration': ''} + model['role_name'] = role['RoleName'] + + # convert maxsessionduration which is in seconds to hours + if role['MaxSessionDuration']: + model['max_session_duration'] = role['MaxSessionDuration'] / 3600 + return model + # pylint: disable=C0301 assume_role_policy_help = ( @@ -710,6 +794,10 @@ assume_role_policy_help = ( 'target="_blank">click here.</a>' ) +max_session_duration_help = ( + 'The maximum session duration (in hours) that you want to set for the specified role.This setting can have a value from 1 hour to 12 hours.' # noqa: E501 +) + create_container = VerticalContainer('Create Role', 'create_role', fields=[ FormField('Role name', 'role_name', validators=[Validator.RGW_ROLE_NAME]), FormField('Path', 'role_path', validators=[Validator.RGW_ROLE_PATH]), @@ -719,37 +807,67 @@ create_container = VerticalContainer('Create Role', 'create_role', fields=[ field_type='textarea', validators=[Validator.JSON]), ]) -create_role_form = Form(path='/rgw/roles/create', + +edit_container = VerticalContainer('Edit Role', 'edit_role', fields=[ + FormField('Role name', 'role_name', readonly=True), + FormField('Max Session Duration', 'max_session_duration', + help=max_session_duration_help, + validators=[Validator.RGW_ROLE_SESSION_DURATION]) +]) + +create_role_form = Form(path='/create', root_container=create_container, task_info=FormTaskInfo("IAM RGW Role '{role_name}' created successfully", ['role_name']), method_type=MethodType.POST.value) +edit_role_form = Form(path='/edit', + root_container=edit_container, + task_info=FormTaskInfo("IAM RGW Role '{role_name}' edited successfully", + ['role_name']), + method_type=MethodType.PUT.value, + model_callback=RGWRoleEndpoints.model) + @CRUDEndpoint( router=APIRouter('/rgw/roles', Scope.RGW), doc=APIDoc("List of RGW roles", "RGW"), actions=[ TableAction(name='Create', permission='create', icon=Icon.ADD.value, - routerLink='/rgw/roles/create') + routerLink='/rgw/roles/create'), + TableAction(name='Edit', permission='update', icon=Icon.EDIT.value, + click='edit', routerLink='/rgw/roles/edit'), + TableAction(name='Delete', permission='delete', icon=Icon.DESTROY.value, + click='delete', disable=True), ], - forms=[create_role_form], - permissions=[Scope.CONFIG_OPT], + forms=[create_role_form, edit_role_form], + column_key='RoleName', + resource='Role', + permissions=[Scope.RGW], get_all=CRUDCollectionMethod( func=RGWRoleEndpoints.role_list, doc=EndpointDoc("List RGW roles") ), create=CRUDCollectionMethod( func=RGWRoleEndpoints.role_create, - doc=EndpointDoc("Create Ceph User") + doc=EndpointDoc("Create RGW role") + ), + edit=CRUDCollectionMethod( + func=RGWRoleEndpoints.role_update, + doc=EndpointDoc("Edit RGW role") + ), + delete=CRUDCollectionMethod( + func=RGWRoleEndpoints.role_delete, + doc=EndpointDoc("Delete RGW role") ), set_column={ "CreateDate": {'cellTemplate': 'date'}, "MaxSessionDuration": {'cellTemplate': 'duration'}, "RoleId": {'isHidden': True}, - "AssumeRolePolicyDocument": {'isHidden': True} + "AssumeRolePolicyDocument": {'isHidden': True}, + "PermissionPolicies": {'isHidden': True} }, - detail_columns=['RoleId', 'AssumeRolePolicyDocument'], + detail_columns=['RoleId', 'AssumeRolePolicyDocument', 'PermissionPolicies'], meta=CRUDMeta() ) class RgwUserRole(NamedTuple): @@ -760,6 +878,7 @@ class RgwUserRole(NamedTuple): CreateDate: str MaxSessionDuration: int AssumeRolePolicyDocument: str + PermissionPolicies: List @APIRouter('/rgw/realm', Scope.RGW) |