summaryrefslogtreecommitdiffstats
path: root/src/pybind
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind')
-rwxr-xr-xsrc/pybind/mgr/dashboard/controllers/rgw.py61
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html8
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts14
-rw-r--r--src/pybind/mgr/dashboard/openapi.yaml1
-rw-r--r--src/pybind/mgr/dashboard/services/rgw_iam.py24
-rw-r--r--src/pybind/mgr/dashboard/services/service.py7
6 files changed, 87 insertions, 28 deletions
diff --git a/src/pybind/mgr/dashboard/controllers/rgw.py b/src/pybind/mgr/dashboard/controllers/rgw.py
index 2e6e466f97b..9d257674794 100755
--- a/src/pybind/mgr/dashboard/controllers/rgw.py
+++ b/src/pybind/mgr/dashboard/controllers/rgw.py
@@ -16,6 +16,7 @@ from ..services.auth import AuthManager, JwtManager
from ..services.ceph_service import CephService
from ..services.rgw_client import _SYNC_GROUP_ID, NoRgwDaemonsException, \
RgwClient, RgwMultisite, RgwMultisiteAutomation
+from ..services.rgw_iam import RgwAccounts
from ..services.service import RgwServiceManager, wait_for_daemon_to_start
from ..tools import json_str_to_object, str_to_bool
from . import APIDoc, APIRouter, BaseController, CreatePermission, \
@@ -399,6 +400,15 @@ class RgwBucket(RgwRESTController):
if bucket['tenant'] else bucket['bucket']
return bucket
+ def _get_owner(self, owner):
+ accounts = RgwAccounts().get_accounts()
+
+ # if the owner is present in the accounts list,
+ # then the bucket is owned by an account.
+ # hence we will use dashboard user to fetch the
+ # bucket info
+ return owner if owner not in accounts else RgwServiceManager.user
+
def _get_versioning(self, owner, daemon_name, bucket_name):
rgw_client = RgwClient.instance(owner, daemon_name)
return rgw_client.get_bucket_versioning(bucket_name)
@@ -542,19 +552,20 @@ class RgwBucket(RgwRESTController):
bucket_name = RgwBucket.get_s3_bucket_name(result['bucket'],
result['tenant'])
+ owner = self._get_owner(result['owner'])
# Append the versioning configuration.
- versioning = self._get_versioning(result['owner'], daemon_name, bucket_name)
- encryption = self._get_encryption(bucket_name, daemon_name, result['owner'])
+ versioning = self._get_versioning(owner, daemon_name, bucket_name)
+ encryption = self._get_encryption(bucket_name, daemon_name, owner)
result['encryption'] = encryption['Status']
result['versioning'] = versioning['Status']
result['mfa_delete'] = versioning['MfaDelete']
- result['bucket_policy'] = self._get_policy(bucket_name, daemon_name, result['owner'])
- result['acl'] = self._get_acl(bucket_name, daemon_name, result['owner'])
- result['replication'] = self._get_replication(bucket_name, result['owner'], daemon_name)
- result['lifecycle'] = self._get_lifecycle(bucket_name, daemon_name, result['owner'])
+ result['bucket_policy'] = self._get_policy(bucket_name, daemon_name, owner)
+ result['acl'] = self._get_acl(bucket_name, daemon_name, owner)
+ result['replication'] = self._get_replication(bucket_name, owner, daemon_name)
+ result['lifecycle'] = self._get_lifecycle(bucket_name, daemon_name, owner)
# Append the locking configuration.
- locking = self._get_locking(result['owner'], daemon_name, bucket_name)
+ locking = self._get_locking(owner, daemon_name, bucket_name)
result.update(locking)
return self._append_bid(result)
@@ -599,7 +610,7 @@ class RgwBucket(RgwRESTController):
raise DashboardException(e, http_status_code=500, component='rgw')
@allow_empty_body
- def set(self, bucket, bucket_id, uid, versioning_state=None,
+ def set(self, bucket, bucket_id, uid=None, 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,
@@ -609,23 +620,27 @@ class RgwBucket(RgwRESTController):
encryption_state = str_to_bool(encryption_state)
if replication is not None:
replication = str_to_bool(replication)
- # 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:
- bucket = '/{}'.format(bucket)
-
- # Link bucket to new user:
- result = self.proxy(daemon_name,
- 'PUT',
- 'bucket', {
- 'bucket': bucket,
- 'bucket-id': bucket_id,
- 'uid': uid
- },
- json_response=False)
+
+ result = None
+ if uid:
+ # 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:
+ bucket = '/{}'.format(bucket)
+
+ # Link bucket to new user:
+ result = self.proxy(daemon_name,
+ 'PUT',
+ 'bucket', {
+ 'bucket': bucket,
+ 'bucket-id': bucket_id,
+ 'uid': uid
+ },
+ json_response=False)
uid_tenant = uid[:uid.find('$')] if uid.find('$') >= 0 else None
bucket_name = RgwBucket.get_s3_bucket_name(bucket, uid_tenant)
+ uid = self._get_owner(uid)
locking = self._get_locking(uid, daemon_name, bucket_name)
if versioning_state:
@@ -659,7 +674,7 @@ class RgwBucket(RgwRESTController):
self._set_lifecycle(bucket_name, lifecycle, daemon_name, uid)
else:
self._delete_lifecycle(bucket_name, daemon_name, uid)
- return self._append_bid(result)
+ return self._append_bid(result) if result else None
def delete(self, bucket, purge_objects='true', daemon_name=None):
return self.proxy(daemon_name, 'DELETE', 'bucket', {
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 f77526be779..9c07182a0e5 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
@@ -91,6 +91,14 @@
<span class="invalid-feedback"
*ngIf="bucketForm.showError('owner', frm, 'required')"
i18n>This field is required.</span>
+ <cd-alert-panel
+ type="info"
+ *ngIf="bucketForm.get('owner').disabled"
+ spacingClass="me-1 mt-1"
+ i18n>
+ The bucket is owned by an account. UI does not support changing
+ the ownership of bucket owned by an account.
+ </cd-alert-panel>
</div>
</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
index d82c71e3cf7..53a1ac442c5 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
@@ -269,6 +269,14 @@ export class RgwBucketFormComponent extends CdForm implements OnInit, AfterViewC
}
this.bucketForm.setValue(value);
if (this.editing) {
+ // temporary fix until the s3 account management is implemented in
+ // the frontend. Disable changing the owner of the bucket in case
+ // its owned by the account.
+ // @TODO: Introduce account selection for a bucket.
+ if (!this.owners.includes(value['owner'])) {
+ this.owners.push(value['owner']);
+ this.bucketForm.get('owner').disable();
+ }
this.isVersioningAlreadyEnabled = this.isVersioningEnabled;
this.isMfaDeleteAlreadyEnabled = this.isMfaDeleteEnabled;
this.setMfaDeleteValidators();
@@ -327,11 +335,15 @@ export class RgwBucketFormComponent extends CdForm implements OnInit, AfterViewC
// Edit
const versioning = this.getVersioningStatus();
const mfaDelete = this.getMfaDeleteStatus();
+ // make the owner empty if the field is disabled.
+ // this ensures the bucket doesn't gets updated with owner when
+ // the bucket is owned by the account.
+ const owner = this.bucketForm.get('owner').disabled === true ? '' : values['owner'];
this.rgwBucketService
.update(
values['bid'],
values['id'],
- values['owner'],
+ owner,
versioning,
values['encryption_enabled'],
values['encryption_type'],
diff --git a/src/pybind/mgr/dashboard/openapi.yaml b/src/pybind/mgr/dashboard/openapi.yaml
index aedee7e493d..b464344e27a 100644
--- a/src/pybind/mgr/dashboard/openapi.yaml
+++ b/src/pybind/mgr/dashboard/openapi.yaml
@@ -11193,7 +11193,6 @@ paths:
type: string
required:
- bucket_id
- - uid
type: object
responses:
'200':
diff --git a/src/pybind/mgr/dashboard/services/rgw_iam.py b/src/pybind/mgr/dashboard/services/rgw_iam.py
new file mode 100644
index 00000000000..dbf00df25e0
--- /dev/null
+++ b/src/pybind/mgr/dashboard/services/rgw_iam.py
@@ -0,0 +1,24 @@
+from subprocess import SubprocessError
+from typing import List
+
+from .. import mgr
+from ..exceptions import DashboardException
+
+
+class RgwAccounts:
+ def send_rgw_cmd(self, command: List[str]):
+ try:
+ exit_code, out, err = mgr.send_rgwadmin_command(command)
+
+ if exit_code != 0:
+ raise DashboardException(msg=err,
+ http_status_code=500,
+ component='rgw')
+ return out
+
+ except SubprocessError as e:
+ raise DashboardException(e, component='rgw')
+
+ def get_accounts(self):
+ get_accounts_cmd = ['account', 'list']
+ return self.send_rgw_cmd(get_accounts_cmd)
diff --git a/src/pybind/mgr/dashboard/services/service.py b/src/pybind/mgr/dashboard/services/service.py
index 41fcc4c4446..9b789c0c859 100644
--- a/src/pybind/mgr/dashboard/services/service.py
+++ b/src/pybind/mgr/dashboard/services/service.py
@@ -101,6 +101,8 @@ def wait_for_daemon_to_start(service_name, timeout=30):
class RgwServiceManager:
+ user = 'dashboard'
+
def find_available_port(self, starting_port=80):
orch = OrchClient.instance()
daemons = [d.to_dict() for d in orch.services.list_daemons(daemon_type='rgw')]
@@ -172,7 +174,6 @@ class RgwServiceManager:
def configure_rgw_credentials(self):
logger.info('Configuring dashboard RGW credentials')
- user = 'dashboard'
realms = []
access_key = ''
secret_key = ''
@@ -186,7 +187,7 @@ class RgwServiceManager:
realm_access_keys = {}
realm_secret_keys = {}
for realm in realms:
- realm_access_key, realm_secret_key = self._get_user_keys(user, realm)
+ realm_access_key, realm_secret_key = self._get_user_keys(self.user, realm)
if realm_access_key:
realm_access_keys[realm] = realm_access_key
realm_secret_keys[realm] = realm_secret_key
@@ -194,7 +195,7 @@ class RgwServiceManager:
access_key = json.dumps(realm_access_keys)
secret_key = json.dumps(realm_secret_keys)
else:
- access_key, secret_key = self._get_user_keys(user)
+ access_key, secret_key = self._get_user_keys(self.user)
assert access_key and secret_key
Settings.RGW_API_ACCESS_KEY = access_key