]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Fallback to Host header for bucket name. 10693/head
authorRobin H. Johnson <robin.johnson@dreamhost.com>
Thu, 26 May 2016 22:41:20 +0000 (15:41 -0700)
committerRobin H. Johnson <robin.johnson@dreamhost.com>
Thu, 11 Aug 2016 16:51:49 +0000 (09:51 -0700)
RGW should fallback to using the Host header as the bucket name if valid &
possible even when it is NOT a suffix match against the DNS names, or a match
against the CNAME rule.

This mirrors AWS S3 behavior for these cases (The AWS S3 does not do any DNS
lookups regardless).

Backport: jewel
Fixes: http://tracker.ceph.com/issues/15975
Signed-off-by: Robin H. Johnson <robin.johnson@dreamhost.com>
(cherry picked from commit 46aae19eeb91bf3ac78a94c9d4812a788d9042a8)

src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_s3.h
src/rgw/rgw_rest_swift.h

index 826c7a9d78b9a5f09a19110c651e2494f4a51fd3..034929b7b7c82f227a1952c769c3c8762cb0ed01 100644 (file)
@@ -1596,6 +1596,27 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
   s->info.request_uri_aws4 = s->info.request_uri;
 
   s->cio = cio;
+
+  // We need to know if this RGW instance is running the s3website API with a
+  // higher priority than regular S3 API, or possibly in place of the regular
+  // S3 API.
+  // Map the listing of rgw_enable_apis in REVERSE order, so that items near
+  // the front of the list have a higher number assigned (and -1 for items not in the list).
+  list<string> apis;
+  get_str_list(g_conf->rgw_enable_apis, apis);
+  int api_priority_s3 = -1;
+  int api_priority_s3website = -1;
+  auto api_s3website_priority_rawpos = std::find(apis.begin(), apis.end(), "s3website");
+  auto api_s3_priority_rawpos = std::find(apis.begin(), apis.end(), "s3");
+  if (api_s3_priority_rawpos != apis.end()) {
+    api_priority_s3 = apis.size() - std::distance(apis.begin(), api_s3_priority_rawpos);
+  }
+  if (api_s3website_priority_rawpos != apis.end()) {
+    api_priority_s3website = apis.size() - std::distance(apis.begin(), api_s3website_priority_rawpos);
+  }
+  ldout(s->cct, 10) << "rgw api priority: s3=" << api_priority_s3 << " s3website=" << api_priority_s3website << dendl;
+  bool s3website_enabled = api_priority_s3website >= 0;
+
   if (info.host.size()) {
     ldout(s->cct, 10) << "host=" << info.host << dendl;
     string domain;
@@ -1603,7 +1624,6 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
     bool in_hosted_domain_s3website = false;
     bool in_hosted_domain = rgw_find_host_in_domains(info.host, &domain, &subdomain, hostnames_set);
 
-    bool s3website_enabled = g_conf->rgw_enable_apis.find("s3website") != std::string::npos;
     string s3website_domain;
     string s3website_subdomain;
 
@@ -1613,7 +1633,6 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
        in_hosted_domain = true; // TODO: should hostnames be a strict superset of hostnames_s3website?
         domain = s3website_domain;
         subdomain = s3website_subdomain;
-        s->prot_flags |= RGW_REST_WEBSITE;
       }
     }
 
@@ -1653,7 +1672,6 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
                                     // strict superset of hostnames_s3website?
            domain = s3website_domain;
            subdomain = s3website_subdomain;
-           s->prot_flags |= RGW_REST_WEBSITE;
          }
         }
 
@@ -1666,6 +1684,31 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
       }
     }
 
+    // Handle A/CNAME records that point to the RGW storage, but do match the
+    // CNAME test above, per issue http://tracker.ceph.com/issues/15975
+    // If BOTH domain & subdomain variables are empty, then none of the above
+    // cases matched anything, and we should fall back to using the Host header
+    // directly as the bucket name.
+    // As additional checks:
+    // - if the Host header is an IP, we're using path-style access without DNS
+    // - Also check that the Host header is a valid bucket name before using it.
+    if (subdomain.empty()
+        && (domain.empty() || domain != info.host)
+        && !looks_like_ip_address(info.host.c_str())
+        && RGWHandler_REST::validate_bucket_name(info.host)) {
+      subdomain.append(info.host);
+      in_hosted_domain = 1;
+    }
+
+    if (s3website_enabled && api_priority_s3website > api_priority_s3) {
+      in_hosted_domain_s3website = 1;
+    }
+
+    if (in_hosted_domain_s3website) {
+      s->prot_flags |= RGW_REST_WEBSITE;
+    }
+
+
     if (in_hosted_domain && !subdomain.empty()) {
       string encoded_bucket = "/";
       encoded_bucket.append(subdomain);
@@ -1678,6 +1721,16 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO* cio)
     if (!domain.empty()) {
       s->info.domain = domain;
     }
+
+   ldout(s->cct, 20)
+      << "final domain/bucket"
+      << " subdomain=" << subdomain
+      << " domain=" << domain
+      << " in_hosted_domain=" << in_hosted_domain
+      << " in_hosted_domain_s3website=" << in_hosted_domain_s3website
+      << " s->info.domain=" << s->info.domain
+      << " s->info.request_uri=" << s->info.request_uri
+      << dendl;
   }
 
   if (s->info.domain.empty()) {
index b3568cf5794ed24ee2df4c1fbd5b41050bb36d07..fe6a6f553bd761a8efa36d3906f7e091bcacc6be 100644 (file)
@@ -377,16 +377,16 @@ protected:
   virtual RGWOp *op_copy() { return NULL; }
   virtual RGWOp *op_options() { return NULL; }
 
-  virtual int validate_tenant_name(const string& bucket);
-  virtual int validate_bucket_name(const string& bucket);
-  virtual int validate_object_name(const string& object);
-
   static int allocate_formatter(struct req_state *s, int default_formatter,
                                bool configurable);
 public:
   RGWHandler_REST() {}
   virtual ~RGWHandler_REST() {}
 
+  static int validate_tenant_name(const string& bucket);
+  static int validate_bucket_name(const string& bucket);
+  static int validate_object_name(const string& object);
+
   int init_permissions(RGWOp* op);
   int read_permissions(RGWOp* op);
 
index 1482a95287f001779b3f7b3023e7528253e5d813..f14c01cd1fee09451f82078669ef2e48ef4db3e2 100644 (file)
@@ -445,11 +445,8 @@ public:
   RGWHandler_Auth_S3() : RGWHandler_REST() {}
   virtual ~RGWHandler_Auth_S3() {}
 
-  virtual int validate_bucket_name(const string& bucket) {
-    return 0;
-  }
-
-  virtual int validate_object_name(const string& bucket) { return 0; }
+  static int validate_bucket_name(const string& bucket);
+  static int validate_object_name(const string& bucket);
 
   virtual int init(RGWRados *store, struct req_state *s, RGWClientIO *cio);
   virtual int authorize() {
index bbef15bf9b4953d203838f32e79aa9e8ae6b59d1..0c4b1e25100cb113955a960bf0a4450a6e38b6f2 100644 (file)
@@ -197,7 +197,7 @@ public:
   RGWHandler_REST_SWIFT() {}
   virtual ~RGWHandler_REST_SWIFT() {}
 
-  int validate_bucket_name(const string& bucket);
+  static int validate_bucket_name(const string& bucket);
 
   int init(RGWRados *store, struct req_state *s, RGWClientIO *cio);
   int authorize();