From 8228784be04ff506d97941ae28368a8e48c61ff7 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Mon, 17 Jul 2017 08:39:13 -0400 Subject: [PATCH] rgw: add support for Swift's TempURLs with prefix-based scope. Fixes: http://tracker.ceph.com/issues/20398 Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_swift_auth.cc | 69 +++++++++++++++++++++++++++++++++++++-- src/rgw/rgw_swift_auth.h | 1 + 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/rgw/rgw_swift_auth.cc b/src/rgw/rgw_swift_auth.cc index 39c80f0d4b1a9..525671c34b4ad 100644 --- a/src/rgw/rgw_swift_auth.cc +++ b/src/rgw/rgw_swift_auth.cc @@ -5,6 +5,8 @@ #include #include +#include +#include #include "rgw_swift_auth.h" #include "rgw_rest.h" @@ -190,6 +192,53 @@ public: }; /* TempURLEngine::SignatureHelper */ +class TempURLEngine::PrefixableSignatureHelper + : private TempURLEngine::SignatureHelper { + using base_t = SignatureHelper; + + const boost::string_view decoded_uri; + const boost::string_view object_name; + boost::string_view no_obj_uri; + + const boost::optional prefix; + +public: + PrefixableSignatureHelper(const std::string& decoded_uri, + const std::string& object_name, + const boost::optional prefix) + : decoded_uri(decoded_uri), + object_name(object_name), + prefix(prefix) { + /* Transform: v1/acct/cont/obj - > v1/acct/cont/ */ + no_obj_uri = \ + decoded_uri.substr(0, decoded_uri.length() - object_name.length()); + } + + const char* calc(const std::string& key, + const boost::string_view& method, + const boost::string_view& path, + const std::string& expires) { + if (!prefix) { + return base_t::calc(key, method, path, expires); + } else { + const auto prefixed_path = \ + string_cat_reserve("prefix:", no_obj_uri, *prefix); + return base_t::calc(key, method, prefixed_path, expires); + } + } + + bool is_equal_to(const std::string& rhs) const { + bool is_auth_ok = base_t::is_equal_to(rhs); + + if (prefix && is_auth_ok) { + const auto prefix_uri = string_cat_reserve(no_obj_uri, *prefix); + is_auth_ok = boost::algorithm::starts_with(decoded_uri, prefix_uri); + } + + return is_auth_ok; + } +}; /* TempURLEngine::PrefixableSignatureHelper */ + TempURLEngine::result_t TempURLEngine::authenticate(const req_state* const s) const { @@ -197,13 +246,22 @@ TempURLEngine::authenticate(const req_state* const s) const return result_t::deny(); } - const string& temp_url_sig = s->info.args.get("temp_url_sig"); - const string& temp_url_expires = s->info.args.get("temp_url_expires"); + /* NOTE(rzarzynski): RGWHTTPArgs::get(), in contrast to RGWEnv::get(), + * never returns nullptr. If the requested parameter is absent, we will + * get the empty string. */ + const std::string& temp_url_sig = s->info.args.get("temp_url_sig"); + const std::string& temp_url_expires = s->info.args.get("temp_url_expires"); if (temp_url_sig.empty() || temp_url_expires.empty()) { return result_t::deny(); } + /* Though, for prefixed tempurls we need to differentiate between empty + * prefix and lack of prefix. Empty prefix means allowance for whole + * container. */ + const boost::optional temp_url_prefix = \ + s->info.args.get_optional("temp_url_prefix"); + RGWUserInfo owner_info; try { get_owner_info(s, owner_info); @@ -250,7 +308,12 @@ TempURLEngine::authenticate(const req_state* const s) const } /* Need to try each combination of keys, allowed path and methods. */ - SignatureHelper sig_helper; + PrefixableSignatureHelper sig_helper { + s->decoded_uri, + s->object.name, + temp_url_prefix + }; + for (const auto& kv : owner_info.temp_url_keys) { const int temp_url_key_num = kv.first; const string& temp_url_key = kv.second; diff --git a/src/rgw/rgw_swift_auth.h b/src/rgw/rgw_swift_auth.h index 055d541d3273a..afab8e069745a 100644 --- a/src/rgw/rgw_swift_auth.h +++ b/src/rgw/rgw_swift_auth.h @@ -49,6 +49,7 @@ class TempURLEngine : public rgw::auth::Engine { bool is_expired(const std::string& expires) const; class SignatureHelper; + class PrefixableSignatureHelper; public: TempURLEngine(CephContext* const cct, -- 2.39.5