]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: rest_client, forward requests
authorYehuda Sadeh <yehuda@inktank.com>
Thu, 23 May 2013 20:09:08 +0000 (13:09 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Thu, 23 May 2013 20:09:08 +0000 (13:09 -0700)
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_auth_s3.cc
src/rgw/rgw_auth_s3.h
src/rgw/rgw_common.h
src/rgw/rgw_env.cc
src/rgw/rgw_rest_client.cc
src/rgw/rgw_rest_client.h
src/rgw/rgw_rest_s3.cc

index e3c08e755265562e76bc4dfbf7ac12e18cf4b528..89cc80d34218e8dbbff55235b859fc14ce727d6f 100644 (file)
@@ -134,4 +134,62 @@ int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string&
   return 0;
 }
 
+static inline bool is_base64_for_content_md5(unsigned char c) {
+  return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
+}
+
+/*
+ * get the header authentication  information required to
+ * compute a request's signature
+ */
+bool rgw_create_s3_canonical_header(req_info& info, utime_t& header_time, string& dest, bool qsr)
+{
+  const char *content_md5 = info.env->get("HTTP_CONTENT_MD5");
+  if (content_md5) {
+    for (const char *p = content_md5; *p; p++) {
+      if (!is_base64_for_content_md5(*p)) {
+        dout(0) << "NOTICE: bad content-md5 provided (not base64), aborting request p=" << *p << " " << (int)*p << dendl;
+        return false;
+      }
+    }
+  }
 
+  const char *content_type = info.env->get("CONTENT_TYPE");
+
+  string date;
+  if (qsr) {
+    date = info.args.get("Expires");
+  } else {
+    const char *str = info.env->get("HTTP_DATE");
+    const char *req_date = str;
+    if (str) {
+      date = str;
+    } else {
+      req_date = info.env->get("HTTP_X_AMZ_DATE");
+      if (!req_date) {
+        dout(0) << "NOTICE: missing date for auth header" << dendl;
+        return false;
+      }
+    }
+
+    struct tm t;
+    if (!parse_rfc2616(req_date, &t)) {
+      dout(0) << "NOTICE: failed to parse date for auth header" << dendl;
+      return false;
+    }
+    if (t.tm_year < 70) {
+      dout(0) << "NOTICE: bad date (predates epoch): " << req_date << dendl;
+      return false;
+    }
+    header_time = utime_t(timegm(&t), 0);
+  }
+
+  map<string, string>& meta_map = info.x_meta_map;
+  map<string, string>& sub_resources = info.args.get_sub_resources();
+
+  rgw_create_s3_canonical_header(info.method, content_md5, content_type, date.c_str(),
+                            meta_map, info.request_uri.c_str(), sub_resources,
+                            dest);
+
+  return true;
+}
index 63813b91717d129aad4b260724907f0925e24148..c8bfbc92c060239519326f631a0eaa51c7fc4349 100644 (file)
@@ -7,6 +7,7 @@
 void rgw_create_s3_canonical_header(const char *method, const char *content_md5, const char *content_type, const char *date,
                             map<string, string>& meta_map, const char *request_uri, map<string, string>& sub_resources,
                             string& dest_str);
+bool rgw_create_s3_canonical_header(req_info& info, utime_t& header_time, string& dest, bool qsr);
 int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string& dest);
 
 
index dc1b0a13bb4613e2f6598ceb50d06a400b0785c1..162e4932ff2e9e174c3427df77234a3780d74326 100644 (file)
@@ -259,6 +259,10 @@ public:
   size_t get_size(const char *name, size_t def_val = 0);
   bool exists(const char *name);
   bool exists_prefix(const char *prefix);
+
+  void remove(const char *name);
+  void set(const char *name, const char *val);
+  std::map<string, string>& get_map() { return env_map; }
 };
 
 class RGWConf {
index e23fa257d1b0063472ef300672603b9172d61146..78ac0d41d7a2714c955a8642b4e7c5309fc5c64a 100644 (file)
@@ -92,6 +92,18 @@ bool RGWEnv::exists_prefix(const char *prefix)
   return (strncmp(iter->first.c_str(), prefix, strlen(prefix)) == 0);
 }
 
+void RGWEnv::set(const char *name, const char *val)
+{
+  env_map[name] = val;
+}
+
+void RGWEnv::remove(const char *name)
+{
+  map<string, string>::iterator iter = env_map.find(name);
+  if (iter != env_map.end())
+    env_map.erase(iter);
+}
+
 void RGWConf::init(CephContext *cct, RGWEnv *env)
 {
   enable_ops_log = cct->_conf->rgw_enable_ops_log;
index 80d58388a899d2c14e42a47cd33edbf4ae309071..c19a71be617f3417861cfe760d3e9cc85b37eac8 100644 (file)
@@ -52,6 +52,14 @@ int RGWRESTClient::read_header(void *ptr, size_t len)
   return 0;
 }
 
+static void get_new_date_str(CephContext *cct, string& date_str)
+{
+  utime_t tm = ceph_clock_now(cct);
+  stringstream s;
+  tm.gmtime(s);
+  date_str = s.str();
+}
+
 int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *resource)
 {
   string new_url = url;
@@ -65,10 +73,8 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
   }
   new_url.append(new_resource);
 
-  utime_t tm = ceph_clock_now(cct);
-  stringstream s;
-  tm.gmtime(s);
-  string date_str = s.str();
+  string date_str;
+  get_new_date_str(cct, date_str);
   headers.push_back(make_pair<string, string>("HTTP_DATE", date_str));
 
   string canonical_header;
@@ -96,3 +102,45 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
   return rgw_http_error_to_errno(status);
 }
 
+int RGWRESTClient::forward_request(RGWAccessKey& key, req_info& info)
+{
+
+  RGWEnv new_env = *info.env; /* copy environment */
+
+  string date_str;
+  get_new_date_str(cct, date_str);
+  new_env.set("HTTP_DATE", date_str.c_str());
+
+  req_info new_info(info);
+  new_info.env = &new_env;
+
+  map<string, string>& m = new_env.get_map();
+
+  string canonical_header;
+  utime_t header_time;
+  if (!rgw_create_s3_canonical_header(new_info, header_time, canonical_header, false)) {
+    ldout(cct, 0) << "failed to create canonical s3 header" << dendl;
+    return -EINVAL;
+  }
+
+  string digest;
+  int ret = rgw_get_s3_header_digest(canonical_header, key.key, digest);
+  if (ret < 0) {
+    return ret;
+  }
+
+  string auth_hdr = "AWS " + key.id + ":" + digest;
+  ldout(cct, 15) << "generated auth header: " << auth_hdr << dendl;
+  
+  m["AUTHORIZATION"] = auth_hdr;
+
+  map<string, string>::iterator iter;
+  for (iter = m.begin(); iter != m.end(); ++iter) {
+    headers.push_back(make_pair<string, string>(iter->first, iter->second));
+  }
+  
+  int r = process(new_info.method, new_info.request_uri.c_str());
+  if (r < 0)
+    return r;
+
+  return rgw_http_error_to_errno(status);}
index 95e1f28697df54838ba3258688852b0f2b47793f..a117bb12a7794e0f49903faa826ccc9d1614b949 100644 (file)
@@ -28,6 +28,7 @@ public:
   int read_header(void *ptr, size_t len);
 
   int execute(RGWAccessKey& key, const char *method, const char *resource);
+  int forward_request(RGWAccessKey& key, req_info& info);
 };
 
 
index 082b310f351d8a2385504b14654ab0467ca82209..00305b54d2b3301cbf9dfd9bea203e3342f62364 100644 (file)
@@ -1900,65 +1900,6 @@ int RGWHandler_ObjStore_S3::init(RGWRados *store, struct req_state *s, RGWClient
   return RGWHandler_ObjStore::init(store, s, cio);
 }
 
-static inline bool is_base64_for_content_md5(unsigned char c) {
-  return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
-}
-
-/*
- * get the header authentication  information required to
- * compute a request's signature
- */
-static bool get_auth_header(req_info& info, utime_t& header_time, string& dest, bool qsr)
-{
-  const char *content_md5 = info.env->get("HTTP_CONTENT_MD5");
-  if (content_md5) {
-    for (const char *p = content_md5; *p; p++) {
-      if (!is_base64_for_content_md5(*p)) {
-        dout(0) << "NOTICE: bad content-md5 provided (not base64), aborting request p=" << *p << " " << (int)*p << dendl;
-        return false;
-      }
-    }
-  }
-
-  const char *content_type = info.env->get("CONTENT_TYPE");
-
-  string date;
-  if (qsr) {
-    date = info.args.get("Expires");
-  } else {
-    const char *str = info.env->get("HTTP_DATE");
-    const char *req_date = str;
-    if (str) {
-      date = str;
-    } else {
-      req_date = info.env->get("HTTP_X_AMZ_DATE");
-      if (!req_date) {
-        dout(0) << "NOTICE: missing date for auth header" << dendl;
-        return false;
-      }
-    }
-
-    struct tm t;
-    if (!parse_rfc2616(req_date, &t)) {
-      dout(0) << "NOTICE: failed to parse date for auth header" << dendl;
-      return false;
-    }
-    if (t.tm_year < 70) {
-      dout(0) << "NOTICE: bad date (predates epoch): " << req_date << dendl;
-      return false;
-    }
-    header_time = utime_t(timegm(&t), 0);
-  }
-
-  map<string, string>& meta_map = info.x_meta_map;
-  map<string, string>& sub_resources = info.args.get_sub_resources();
-
-  rgw_create_s3_canonical_header(info.method, content_md5, content_type, date.c_str(),
-                            meta_map, info.request_uri.c_str(), sub_resources,
-                            dest);
-
-  return true;
-}
 
 /*
  * verify that a signed request comes from the keyholder
@@ -2015,7 +1956,7 @@ int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
   /* now verify signature */
    
   string auth_hdr;
-  if (!get_auth_header(s->info, s->header_time, auth_hdr, qsr)) {
+  if (!rgw_create_s3_canonical_header(s->info, s->header_time, auth_hdr, qsr)) {
     dout(10) << "failed to create auth header\n" << auth_hdr << dendl;
     return -EPERM;
   }