summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@redhat.com>2021-02-19 18:42:12 +0100
committerYehuda Sadeh <yehuda@redhat.com>2021-03-09 11:04:58 +0100
commitd98ed0cb9f4f90266503dfc889746c678b7f946d (patch)
tree17a1833a70255724170faefe2435114151f10a3c
parentrgw: rest client: sign awsv4 content (if possible) (diff)
downloadceph-d98ed0cb9f4f90266503dfc889746c678b7f946d.tar.xz
ceph-d98ed0cb9f4f90266503dfc889746c678b7f946d.zip
rgw: auth v4: extract service from url
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
-rw-r--r--src/rgw/rgw_auth_s3.cc7
-rw-r--r--src/rgw/rgw_auth_s3.h3
-rw-r--r--src/rgw/rgw_rest_client.cc62
-rw-r--r--src/rgw/rgw_rest_client.h1
-rw-r--r--src/rgw/rgw_rest_s3.cc3
-rw-r--r--src/rgw/rgw_rest_s3.h1
6 files changed, 54 insertions, 23 deletions
diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc
index 0ea45f19721..f59f3126344 100644
--- a/src/rgw/rgw_auth_s3.cc
+++ b/src/rgw/rgw_auth_s3.cc
@@ -495,7 +495,8 @@ int parse_v4_credentials(const req_info& info, /* in */
}
string gen_v4_scope(const ceph::real_time& timestamp,
- const string& region)
+ const string& region,
+ const string& service)
{
auto sec = real_clock::to_time_t(timestamp);
@@ -507,8 +508,8 @@ string gen_v4_scope(const ceph::real_time& timestamp,
auto mon = bt.tm_mon + 1;
auto day = bt.tm_mday;
- return fmt::format(FMT_STRING("{:d}{:02d}{:02d}/{:s}/s3/aws4_request"),
- year, mon, day, region);
+ return fmt::format(FMT_STRING("{:d}{:02d}{:02d}/{:s}/{:s}/aws4_request"),
+ year, mon, day, region, service);
}
std::string get_v4_canonical_qs(const req_info& info, const bool using_qs)
diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h
index f0598495bd2..7b479894dbf 100644
--- a/src/rgw/rgw_auth_s3.h
+++ b/src/rgw/rgw_auth_s3.h
@@ -467,7 +467,8 @@ int parse_v4_credentials(const req_info& info, /* in */
const DoutPrefixProvider *dpp); /* in */
string gen_v4_scope(const ceph::real_time& timestamp,
- const string& region);
+ const string& region,
+ const string& service);
static inline bool char_needs_aws4_escaping(const char c, bool encode_slash)
{
diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc
index 1918adbc800..ccdf0f38817 100644
--- a/src/rgw/rgw_rest_client.cc
+++ b/src/rgw/rgw_rest_client.cc
@@ -187,7 +187,9 @@ void RGWHTTPSimpleRequest::get_out_headers(map<string, string> *pheaders)
out_headers.clear();
}
-static int sign_request(const DoutPrefixProvider *dpp, RGWAccessKey& key, const string& region, RGWEnv& env, req_info& info)
+static int sign_request(const DoutPrefixProvider *dpp, RGWAccessKey& key,
+ const string& region, const string& service,
+ RGWEnv& env, req_info& info)
{
/* don't sign if no key is provided */
if (key.key.empty()) {
@@ -204,7 +206,7 @@ static int sign_request(const DoutPrefixProvider *dpp, RGWAccessKey& key, const
rgw::auth::s3::AWSSignerV4 signer(dpp);
- auto sigv4_data = signer.prepare(key.id, region, info, true);
+ auto sigv4_data = signer.prepare(key.id, region, service, info, true);
auto sigv4_headers = sigv4_data.signature_factory(dpp, key.key, sigv4_data);
for (auto& entry : sigv4_headers) {
@@ -227,46 +229,67 @@ static string extract_region_name(string&& s)
}
-static std::optional<string> identify_region(CephContext *cct, const string& host)
+static bool identify_scope(CephContext *cct,
+ const string& host,
+ string *region,
+ string *service)
{
if (!boost::algorithm::ends_with(host, "amazonaws.com")) {
ldout(cct, 20) << "NOTICE: cannot identify region for connection to: " << host << dendl;
- return std::nullopt;
+ return false;
}
vector<string> vec;
get_str_vec(host, ".", vec);
+ *service = "s3"; /* default */
+
for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
auto& s = *iter;
if (s == "s3" ||
s == "execute-api") {
+ if (s == "execute-api") {
+ *service = s;
+ }
++iter;
if (iter == vec.end()) {
ldout(cct, 0) << "WARNING: cannot identify region name from host name: " << host << dendl;
- return std::nullopt;
+ return false;
}
auto& next = *iter;
if (next == "amazonaws") {
- return "us-east-1";
+ *region = "us-east-1";
+ return true;
}
- return next;
+ *region = next;
+ return true;
} else if (boost::algorithm::starts_with(s, "s3-")) {
- return extract_region_name(std::move(s));
+ *region = extract_region_name(std::move(s));
+ return true;
}
}
- return std::nullopt;
+ return false;
}
-static string region_from_api_name(CephContext *cct, const string& host, std::optional<string> api_name)
+static void scope_from_api_name(CephContext *cct,
+ const string& host,
+ std::optional<string> api_name,
+ string *region,
+ string *service)
{
- if (!api_name) {
- api_name = identify_region(cct, host);
+ if (api_name) {
+ *region = *api_name;
+ *service = "s3";
+ return;
+ }
+
+ if (!identify_scope(cct, host, region, service)) {
+ *region = cct->_conf->rgw_zonegroup;
+ *service = "s3";
+ return;
}
-#warning need to be period->api_name instead of rgw_zonegroup
- return api_name.value_or(cct->_conf->rgw_zonegroup);
}
int RGWRESTSimpleRequest::forward_request(RGWAccessKey& key, req_info& info, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y)
@@ -299,14 +322,17 @@ int RGWRESTSimpleRequest::forward_request(RGWAccessKey& key, req_info& info, siz
new_env.set("HTTP_CONTENT_MD5", content_md5);
}
- string region = region_from_api_name(cct, host, api_name);
+ string region;
+ string service;
+
+ scope_from_api_name(cct, host, api_name, &region, &service);
const char *maybe_payload_hash = info.env->get("HTTP_X_AMZ_CONTENT_SHA256");
if (maybe_payload_hash) {
new_env.set("HTTP_X_AMZ_CONTENT_SHA256", maybe_payload_hash);
}
- int ret = sign_request(this, key, region, new_env, new_info);
+ int ret = sign_request(this, key, region, service, new_env, new_info);
if (ret < 0) {
ldout(cct, 0) << "ERROR: failed to sign request" << dendl;
return ret;
@@ -475,7 +501,7 @@ void RGWRESTGenerateHTTPHeaders::init(const string& _method, const string& host,
const string& resource, const param_vec_t& params,
std::optional<string> api_name)
{
- region = region_from_api_name(cct, host, api_name);
+ scope_from_api_name(cct, host, api_name, &region, &service);
string params_str;
map<string, string>& args = new_info->args.get_params();
@@ -592,7 +618,7 @@ void RGWRESTGenerateHTTPHeaders::set_content(const bufferlist& bl)
int RGWRESTGenerateHTTPHeaders::sign(RGWAccessKey& key)
{
- int ret = sign_request(this, key, region, *new_env, *new_info);
+ int ret = sign_request(this, key, region, service, *new_env, *new_info);
if (ret < 0) {
ldout(cct, 0) << "ERROR: failed to sign request" << dendl;
return ret;
diff --git a/src/rgw/rgw_rest_client.h b/src/rgw/rgw_rest_client.h
index 03b12a730ff..3bf95c68143 100644
--- a/src/rgw/rgw_rest_client.h
+++ b/src/rgw/rgw_rest_client.h
@@ -80,6 +80,7 @@ class RGWRESTGenerateHTTPHeaders : public DoutPrefix {
RGWEnv *new_env;
req_info *new_info;
string region;
+ string service;
string method;
string url;
string resource;
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 2b9ca215935..5c28caff731 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -5200,6 +5200,7 @@ AWSGeneralAbstractor::get_v4_canonical_headers(
AWSSignerV4::prepare_result_t
AWSSignerV4::prepare(const std::string& access_key_id,
const string& region,
+ const string& service,
const req_info& info,
bool s3_op) const
{
@@ -5214,7 +5215,7 @@ AWSSignerV4::prepare(const std::string& access_key_id,
std::string date = ceph::to_iso_8601_no_separators(timestamp, ceph::iso_8601_format::YMDhms);
- std::string credential_scope = gen_v4_scope(timestamp, region);
+ std::string credential_scope = gen_v4_scope(timestamp, region, service);
extra_headers["x-amz-date"] = date;
auto iter = info.x_meta_map.find("x-amz-content-sha256");
diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h
index fc48693692a..025b7cf24c0 100644
--- a/src/rgw/rgw_rest_s3.h
+++ b/src/rgw/rgw_rest_s3.h
@@ -1110,6 +1110,7 @@ public:
prepare_result_t prepare(const std::string& access_key_id,
const string& region,
+ const string& service,
const req_info& info,
bool s3_op) const;
};