rgw: RGWPostObj_ObjStore_S3 doesn't instantiate auth strategy for each request anymore.

Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
This commit is contained in:
Radoslaw Zarzynski 2017-02-07 15:11:19 +01:00
parent 1ad1d83997
commit f13f04bbb3
4 changed files with 50 additions and 51 deletions

View File

@ -71,12 +71,18 @@ public:
};
template <class ExtractorT>
class AWSv2AuthStrategy : public rgw::auth::Strategy,
public rgw::auth::LocalApplier::Factory {
typedef rgw::auth::IdentityApplier::aplptr_t aplptr_t;
RGWRados* const store;
rgw::auth::s3::RGWS3V2Extractor extractor;
static_assert(std::is_base_of<rgw::auth::s3::Version2ndEngine::Extractor,
ExtractorT>::value,
"ExtractorT must be a subclass of rgw::auth::s3::ExtractorT");
RGWRados* const store;
ExtractorT extractor;
ExternalAuthStrategy external_engines;
LocalVersion2ndEngine local_engine;
@ -99,23 +105,9 @@ public:
local_engine(cct, store, extractor,
static_cast<rgw::auth::LocalApplier::Factory*>(this)) {
add_engine(Control::SUFFICIENT, external_engines);
if (cct->_conf->rgw_s3_auth_use_rados) {
add_engine(Control::SUFFICIENT, local_engine);
}
}
/* FIXME(rzarzynski): hack for S3's browsers upload. */
AWSv2AuthStrategy(CephContext* const cct,
RGWRados* const store,
Version2ndEngine::Extractor* const external_extractor)
: store(store),
extractor(cct),
external_engines(cct, store, external_extractor),
local_engine(cct, store, *external_extractor,
static_cast<rgw::auth::LocalApplier::Factory*>(this)) {
add_engine(Control::SUFFICIENT, external_engines);
if (cct->_conf->rgw_s3_auth_use_rados) {
add_engine(Control::SUFFICIENT, local_engine);
add_engine(Control::FALLBACK, local_engine);
}
}

View File

@ -1334,7 +1334,13 @@ struct req_state;
class RGWEnv;
/* Namespaced forward declarations. */
namespace rgw {
namespace auth {
namespace s3 {
class RGWGetPolicyV2Extractor;
}
}
namespace io {
class BasicClient;
}
@ -1735,6 +1741,21 @@ struct req_state {
std::unique_ptr<rgw::auth::Identity> identity;
std::unique_ptr<rgw::auth::Completer> completer;
/* A container for credentials of the S3's browser upload. It's necessary
* because: 1) the ::authenticate() method of auth engines and strategies
* take req_state only; 2) auth strategies live much longer than RGWOps -
* there is no way to pass additional data dependencies through ctors. */
class {
/* Writer. */
friend class RGWPostObj_ObjStore_S3;
/* Reader. */
friend class rgw::auth::s3::RGWGetPolicyV2Extractor;
std::string access_key;
std::string signature;
ceph::bufferlist encoded_policy;
} s3_postobj_creds;
} auth;
std::unique_ptr<RGWAccessControlPolicy> user_acl;

View File

@ -1798,39 +1798,28 @@ int RGWPostObj_ObjStore_S3::get_params()
return 0;
}
static std::string to_string(ceph::bufferlist& bl)
{
return std::string(bl.c_str(),
static_cast<std::string::size_type>(bl.length()));
}
int RGWPostObj_ObjStore_S3::get_policy()
{
bufferlist encoded_policy;
if (part_bl("policy", &encoded_policy)) {
if (part_bl("policy", &s->auth.s3_postobj_creds.encoded_policy)) {
// check that the signature matches the encoded policy
string s3_access_key;
if (!part_str("AWSAccessKeyId", &s3_access_key)) {
if (! part_str("AWSAccessKeyId", &s->auth.s3_postobj_creds.access_key)) {
ldout(s->cct, 0) << "No S3 access key found!" << dendl;
err_msg = "Missing access key";
return -EINVAL;
}
string received_signature_str;
if (!part_str("signature", &received_signature_str)) {
if (! part_str("signature", &s->auth.s3_postobj_creds.signature)) {
ldout(s->cct, 0) << "No signature found!" << dendl;
err_msg = "Missing signature";
return -EINVAL;
}
rgw::auth::s3::RGWGetPolicyV2Extractor extr(s3_access_key,
received_signature_str,
to_string(encoded_policy));
/* FIXME: this is a makeshift solution. The browser upload authenication will be
/* FIXME: this is a makeshift solution. The browser upload authentication will be
* handled by an instance of rgw::auth::Completer spawned in Handler's authorize()
* method. Thus creating a strategy per request won't be necessary. */
const rgw::auth::s3::AWSv2AuthStrategy strategy(g_ceph_context, store, &extr);
* method. */
static const rgw::auth::s3::AWSv2AuthStrategy<
rgw::auth::s3::RGWGetPolicyV2Extractor> strategy(g_ceph_context, store);
try {
auto result = strategy.authenticate(s);
if (result.get_status() != decltype(result)::Status::GRANTED) {
@ -1859,7 +1848,7 @@ int RGWPostObj_ObjStore_S3::get_policy()
ceph::bufferlist decoded_policy;
try {
decoded_policy.decode_base64(encoded_policy);
decoded_policy.decode_base64(s->auth.s3_postobj_creds.encoded_policy);
} catch (buffer::error& err) {
ldout(s->cct, 0) << "failed to decode_base64 policy" << dendl;
err_msg = "Could not decode policy";
@ -3896,7 +3885,7 @@ int RGW_Auth_S3::authorize_v2(RGWRados *store, struct req_state *s)
{
/* TODO(rzarzynski): this will be moved to the S3 handlers -- in exactly
* way like we currently have in the case of Swift API. */
static const rgw::auth::s3::AWSv2AuthStrategy strategy(g_ceph_context, store);
static const rgw::auth::s3::AWSv2AuthStrategy<rgw::auth::s3::RGWS3V2Extractor> strategy(g_ceph_context, store);
try {
auto result = strategy.authenticate(s);
if (result.get_status() != decltype(result)::Status::GRANTED) {

View File

@ -685,25 +685,22 @@ public:
class RGWGetPolicyV2Extractor : public Version2ndEngine::Extractor {
private:
std::string access_key_id;
std::string signature;
std::string string_to_sign;
static std::string to_string(ceph::bufferlist bl) {
return std::string(bl.c_str(),
static_cast<std::string::size_type>(bl.length()));
}
public:
RGWGetPolicyV2Extractor(std::string access_key_id,
std::string signature,
std::string string_to_sign)
: access_key_id(std::move(access_key_id)),
signature(std::move(signature)),
string_to_sign(std::move(string_to_sign)) {
RGWGetPolicyV2Extractor(CephContext*) {
}
std::tuple<access_key_id_t,
signature_t,
string_to_sign_t>
get_auth_data(const req_state* s) const override {
return std::make_tuple(access_key_id, signature, string_to_sign);
return std::make_tuple(s->auth.s3_postobj_creds.access_key,
s->auth.s3_postobj_creds.signature,
to_string(s->auth.s3_postobj_creds.encoded_policy));
}
};