]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/rest: wrap iam/sns/sts Error responses with ErrorResponse
authorCasey Bodley <cbodley@redhat.com>
Thu, 11 Jan 2024 22:10:06 +0000 (17:10 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:27 +0000 (15:34 -0400)
all iam/sns/sts requests wrap the s3 <Error> xml response in another
<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">

without this, boto3 fails to fully parse error responses, leading to
generic Unknown ClientError exceptions of the form:
    botocore.exceptions.ClientError: An error occurred (Unknown) when calling the PutUserPolicy operation: Unknown

with the ErrorResponse part, boto3 throws more specific exceptions that
include the error Code and Message:
    botocore.errorfactory.NoSuchEntityException: An error occurred (NoSuchEntity) when calling the PutUserPolicy operation: No such UserName in the account

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 195ecb3732e0d7f78dc74cc9b7f2ac3d7ed919a0)

src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_rest_iam.h
src/rgw/rgw_rest_pubsub.cc
src/rgw/rgw_rest_sts.cc

index 752bdb1bb96d455dfde90d225e2cad55fa159aed..ff0074c84e4eecb4cc65d4062144f295ebc820c6 100644 (file)
@@ -374,6 +374,15 @@ void set_req_state_err(req_state* s, int err_no)
 
 void dump(req_state* s)
 {
+  std::optional<Formatter::ObjectSection> error_response;
+  if (s->prot_flags & RGW_REST_IAM) {
+    error_response.emplace(*s->formatter, "ErrorResponse", RGW_REST_IAM_XMLNS);
+  } else if (s->prot_flags & RGW_REST_SNS) {
+    error_response.emplace(*s->formatter, "ErrorResponse", RGW_REST_SNS_XMLNS);
+  } else if (s->prot_flags & RGW_REST_STS) {
+    error_response.emplace(*s->formatter, "ErrorResponse", RGW_REST_STS_XMLNS);
+  }
+
   if (s->format != RGWFormat::HTML)
     s->formatter->open_object_section("Error");
   if (!s->err.err_code.empty())
@@ -385,7 +394,7 @@ void dump(req_state* s)
     s->formatter->dump_string("RequestId", s->trans_id);
   s->formatter->dump_string("HostId", s->host_id);
   if (s->format != RGWFormat::HTML)
-    s->formatter->close_section();
+    s->formatter->close_section(); // Error
 }
 
 struct str_len {
index 35d097ef1c0d9ccca24c1d8e4c0e610fd67ce809..0794c0e4d059467d54c89e66c07bb48c82cc4fbf 100644 (file)
@@ -213,7 +213,16 @@ static inline const char* to_mime_type(const RGWFormat f)
 #define RGW_REST_WEBSITE     0x8
 #define RGW_REST_STS            0x10
 #define RGW_REST_IAM            0x20
-#define RGW_REST_SNS            0x30
+#define RGW_REST_SNS            0x40
+
+inline constexpr const char* RGW_REST_IAM_XMLNS =
+    "https://iam.amazonaws.com/doc/2010-05-08/";
+
+inline constexpr const char* RGW_REST_SNS_XMLNS =
+    "https://sns.amazonaws.com/doc/2010-03-31/";
+
+inline constexpr const char* RGW_REST_STS_XMLNS =
+    "https://sts.amazonaws.com/doc/2011-06-15/";
 
 #define RGW_SUSPENDED_USER_AUID (uint64_t)-2
 
index 3e579ab35ce767521e61f533d1fd66479ef3066f..c1edd201e37035359ce95cb79fa2dbb656034e03 100644 (file)
@@ -7,6 +7,7 @@
 #include "rgw_auth_filters.h"
 #include "rgw_rest.h"
 
+
 class RGWHandler_REST_IAM : public RGWHandler_REST {
   const rgw::auth::StrategyRegistry& auth_registry;
   bufferlist bl_post_body;
index 4fb1051ebf6bc3794ffb421944cd6b9be4a24207..ec0b2ff6e86562a0d037cfb2a05b9ba47e575295 100644 (file)
@@ -23,8 +23,6 @@
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_rgw
 
-static const char* AWS_SNS_NS("https://sns.amazonaws.com/doc/2010-03-31/");
-
 bool verify_transport_security(CephContext *cct, const RGWEnv& env) {
   const auto is_secure = rgw_transport_is_secure(cct, env);
   if (!is_secure && g_conf().get_val<bool>("rgw_allow_notification_secrets_in_cleartext")) {
@@ -264,7 +262,7 @@ class RGWPSCreateTopicOp : public RGWOp {
     }
 
     const auto f = s->formatter;
-    f->open_object_section_in_ns("CreateTopicResponse", AWS_SNS_NS);
+    f->open_object_section_in_ns("CreateTopicResponse", RGW_REST_SNS_XMLNS);
     f->open_object_section("CreateTopicResult");
     encode_xml("TopicArn", topic_arn, f); 
     f->close_section(); // CreateTopicResult
@@ -340,7 +338,7 @@ public:
     }
 
     const auto f = s->formatter;
-    f->open_object_section_in_ns("ListTopicsResponse", AWS_SNS_NS);
+    f->open_object_section_in_ns("ListTopicsResponse", RGW_REST_SNS_XMLNS);
     f->open_object_section("ListTopicsResult");
     encode_xml("Topics", result, f); 
     f->close_section(); // ListTopicsResult
@@ -513,7 +511,7 @@ class RGWPSGetTopicAttributesOp : public RGWOp {
     }
 
     const auto f = s->formatter;
-    f->open_object_section_in_ns("GetTopicAttributesResponse", AWS_SNS_NS);
+    f->open_object_section_in_ns("GetTopicAttributesResponse", RGW_REST_SNS_XMLNS);
     f->open_object_section("GetTopicAttributesResult");
     result.dump_xml_as_attributes(f);
     f->close_section(); // GetTopicAttributesResult
@@ -701,7 +699,7 @@ class RGWPSSetTopicAttributesOp : public RGWOp {
     }
 
     const auto f = s->formatter;
-    f->open_object_section_in_ns("SetTopicAttributesResponse", AWS_SNS_NS);
+    f->open_object_section_in_ns("SetTopicAttributesResponse", RGW_REST_SNS_XMLNS);
     f->open_object_section("ResponseMetadata");
     encode_xml("RequestId", s->req_id, f);
     f->close_section();  // ResponseMetadata
@@ -799,7 +797,7 @@ class RGWPSDeleteTopicOp : public RGWOp {
     }
 
     const auto f = s->formatter;
-    f->open_object_section_in_ns("DeleteTopicResponse", AWS_SNS_NS);
+    f->open_object_section_in_ns("DeleteTopicResponse", RGW_REST_SNS_XMLNS);
     f->open_object_section("ResponseMetadata");
     encode_xml("RequestId", s->req_id, f); 
     f->close_section(); // ResponseMetadata
index d94181f4e6342f35836940c99a054618872f9ead..210d310313fd583e5da9ec51e09af259b1527914 100644 (file)
@@ -621,7 +621,7 @@ void RGWSTSGetSessionToken::execute(optional_yield y)
   op_ret = std::move(ret);
   //Dump the output
   if (op_ret == 0) {
-    s->formatter->open_object_section("GetSessionTokenResponse");
+    s->formatter->open_object_section_in_ns("GetSessionTokenResponse", RGW_REST_STS_XMLNS);
     s->formatter->open_object_section("GetSessionTokenResult");
     s->formatter->open_object_section("Credentials");
     creds.dump(s->formatter);
@@ -677,7 +677,7 @@ void RGWSTSAssumeRoleWithWebIdentity::execute(optional_yield y)
 
   //Dump the output
   if (op_ret == 0) {
-    s->formatter->open_object_section("AssumeRoleWithWebIdentityResponse");
+    s->formatter->open_object_section_in_ns("AssumeRoleWithWebIdentityResponse", RGW_REST_STS_XMLNS);
     s->formatter->open_object_section("AssumeRoleWithWebIdentityResult");
     encode_json("SubjectFromWebIdentityToken", response.sub , s->formatter);
     encode_json("Audience", response.aud , s->formatter);
@@ -738,7 +738,7 @@ void RGWSTSAssumeRole::execute(optional_yield y)
   op_ret = std::move(response.retCode);
   //Dump the output
   if (op_ret == 0) {
-    s->formatter->open_object_section("AssumeRoleResponse");
+    s->formatter->open_object_section_in_ns("AssumeRoleResponse", RGW_REST_STS_XMLNS);
     s->formatter->open_object_section("AssumeRoleResult");
     s->formatter->open_object_section("Credentials");
     response.creds.dump(s->formatter);