From 51d36c3f60f77f9c2c32d4764ad66c90df67bacd Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Sat, 17 Feb 2024 17:53:21 -0500 Subject: [PATCH] rgw/iam: only RGWDeleteRole returns ERR_DELETE_CONFLICT metadata sync calls RadosRole::delete_obj() after the role is deleted on the metadata master zone. the role was verified to be empty there, so metadata sync needs to delete the role anyway only the iam DeleteRole api should require policies to be removed first Signed-off-by: Casey Bodley --- src/rgw/driver/rados/rgw_sal_rados.cc | 5 ---- src/rgw/rgw_rest_role.cc | 34 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index 92244196295c4..8171e25689fb6 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -4430,11 +4430,6 @@ int RadosRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y) return ret; } - if (!info.perm_policy_map.empty() || - !info.managed_policies.arns.empty()) { - return -ERR_DELETE_CONFLICT; - } - // Delete id & insert MD Log RGWSI_MBSObj_RemoveParams params; std::unique_ptr ctx(store->svc()->role->svc.meta_be->alloc_ctx()); diff --git a/src/rgw/rgw_rest_role.cc b/src/rgw/rgw_rest_role.cc index 79c5c4bbac000..893608d7acb30 100644 --- a/src/rgw/rgw_rest_role.cc +++ b/src/rgw/rgw_rest_role.cc @@ -352,11 +352,8 @@ int RGWDeleteRole::init_processing(optional_yield y) void RGWDeleteRole::execute(optional_yield y) { - bool is_master = true; - const rgw::SiteConfig& site = *s->penv.site; if (!site.is_meta_master()) { - is_master = false; RGWXMLDecoder::XMLParser parser; if (!parser.init()) { ldpp_dout(this, 0) << "ERROR: failed to initialize xml parser" << dendl; @@ -376,16 +373,28 @@ void RGWDeleteRole::execute(optional_yield y) } } - op_ret = role->delete_obj(s, y); + op_ret = retry_raced_role_write(this, y, role.get(), + [this, y, &site] { + if (site.is_meta_master()) { + // only check on the master zone. if a forwarded DeleteRole request + // succeeds on the master zone, it needs to succeed here too + const auto& info = role->get_info(); + if (!info.perm_policy_map.empty() || + !info.managed_policies.arns.empty()) { + s->err.message = "The role cannot be deleted until all role policies are removed"; + return -ERR_DELETE_CONFLICT; + } + } + return role->delete_obj(s, y); + }); if (op_ret == -ENOENT) { //Role has been deleted since metadata from master has synced up - if (!is_master) { + if (!site.is_meta_master()) { op_ret = 0; } else { op_ret = -ERR_NO_ROLE_FOUND; } - return; } if (!op_ret) { s->formatter->open_object_section("DeleteRoleResponse"); @@ -725,12 +734,16 @@ void RGWDeleteRolePolicy::execute(optional_yield y) } op_ret = retry_raced_role_write(this, y, role.get(), - [this, y] { + [this, y, &site] { int r = role->delete_policy(this, policy_name); if (r == -ENOENT) { + if (!site.is_meta_master()) { + return 0; // delete succeeded on the master + } s->err.message = "The requested PolicyName was not found"; return -ERR_NO_SUCH_ENTITY; - } else if (r == 0) { + } + if (r == 0) { r = role->update(this, y); } return r; @@ -1157,10 +1170,13 @@ void RGWDetachRolePolicy_IAM::execute(optional_yield y) } op_ret = retry_raced_role_write(this, y, role.get(), - [this, y] { + [this, y, &site] { auto &policies = role->get_info().managed_policies; auto p = policies.arns.find(policy_arn); if (p == policies.arns.end()) { + if (!site.is_meta_master()) { + return 0; // delete succeeded on the master + } s->err.message = "The requested PolicyArn is not attached to the role"; return -ERR_NO_SUCH_ENTITY; } -- 2.39.5