#include "rgw_rest_s3.h"
#include "rgw_auth.h"
+#include "rgw_auth_filters.h"
#include "rgw_auth_keystone.h"
rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg,
const rgw::auth::RemoteApplier::AuthInfo info
) const override {
- return aplptr_t(
- new rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info));
+ auto apl = rgw::auth::add_sysreq(cct, store, s,
+ rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info));
+ /* TODO(rzarzynski): replace with static_ptr. */
+ return aplptr_t(new decltype(apl)(std::move(apl)));
}
public:
return "rgw::auth::s3::AWSv2ExternalAuthStrategy";
}
};
+
+
+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;
+ ExternalAuthStrategy external_engines;
+ LocalVersion2ndEngine local_engine;
+
+ aplptr_t create_apl_local(CephContext* const cct,
+ const req_state* const s,
+ const RGWUserInfo& user_info,
+ const std::string& subuser) const override {
+ auto apl = rgw::auth::add_sysreq(cct, store, s,
+ rgw::auth::LocalApplier(cct, user_info, subuser));
+ /* TODO(rzarzynski): replace with static_ptr. */
+ return aplptr_t(new decltype(apl)(std::move(apl)));
+ }
+
+public:
+ AWSv2AuthStrategy(CephContext* const cct,
+ RGWRados* const store)
+ : store(store),
+ external_engines(cct, store, &extractor),
+ 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);
+ }
+ }
+
+ const char* get_name() const noexcept override {
+ return "rgw::auth::s3::AWSv2AuthStrategy";
+ }
+};
+
} /* namespace s3 */
} /* namespace auth */
} /* namespace rgw */
err_msg = "Missing signature";
return -EINVAL;
}
- RGWUserInfo user_info;
-
- op_ret = rgw_get_user_info_by_access_key(store, s3_access_key, user_info);
- if (op_ret < 0) {
- // try external authenticators
- rgw::auth::s3::RGWGetPolicyV2Extractor extr(s3_access_key, received_signature_str);
- /* FIXME: this is a makeshift solution. The browser upload authenication 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. */
- rgw::auth::s3::ExternalAuthStrategy strategy(s->cct, store, &extr);
- try {
- auto result = strategy.authenticate(s);
- auto& applier = result.first;
- if (! applier) {
- return -EACCES;
- }
- try {
- applier->load_acct_info(user_info);
- s->perm_mask = applier->get_perm_mask();
- applier->modify_request_state(s);
- s->auth.identity = std::move(applier);
- } catch (int err) {
- return -EACCES;
- }
- } catch (int err) {
+ rgw::auth::s3::RGWGetPolicyV2Extractor extr(s3_access_key, received_signature_str);
+ /* FIXME: this is a makeshift solution. The browser upload authenication 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);
+ try {
+ auto result = strategy.authenticate(s);
+ auto& applier = result.first;
+ if (! applier) {
return -EACCES;
}
- } else {
- map<string, RGWAccessKey> access_keys = user_info.access_keys;
-
- map<string, RGWAccessKey>::const_iterator iter =
- access_keys.find(s3_access_key);
- // We know the key must exist, since the user was returned by
- // rgw_get_user_info_by_access_key, but it doesn't hurt to check!
- if (iter == access_keys.end()) {
- ldout(s->cct, 0) << "Secret key lookup failed!" << dendl;
- err_msg = "No secret key for matching access key";
- return -EACCES;
- }
- string s3_secret_key = (iter->second).key;
-
- char expected_signature_char[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
-
- calc_hmac_sha1(s3_secret_key.c_str(), s3_secret_key.size(),
- encoded_policy.c_str(), encoded_policy.length(),
- expected_signature_char);
- bufferlist expected_signature_hmac_raw;
- bufferlist expected_signature_hmac_encoded;
- expected_signature_hmac_raw.append(expected_signature_char,
- CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
- expected_signature_hmac_raw.encode_base64(
- expected_signature_hmac_encoded);
- expected_signature_hmac_encoded.append((char)0); /* null terminate */
-
- if (received_signature_str.compare(
- expected_signature_hmac_encoded.c_str()) != 0) {
- ldout(s->cct, 0) << "Signature verification failed!" << dendl;
- ldout(s->cct, 0) << "received: " << received_signature_str.c_str()
- << dendl;
- ldout(s->cct, 0) << "expected: "
- << expected_signature_hmac_encoded.c_str() << dendl;
- err_msg = "Bad access key / signature";
- return -EACCES;
+
+ try {
+ applier->load_acct_info(*s->user);
+ s->perm_mask = applier->get_perm_mask();
+ applier->modify_request_state(s);
+ s->auth.identity = std::move(applier);
+
+ s->owner.set_id(s->user->user_id);
+ s->owner.set_name(s->user->display_name);
+ /* OK, fall through. */
+ } catch (int err) {
+ return -EACCES;
}
+ } catch (int err) {
+ return -EACCES;
}
ldout(s->cct, 0) << "Successful Signature Verification!" << dendl;
return r;
}
- // deep copy
- *(s->user) = user_info;
- s->owner.set_id(user_info.user_id);
- s->owner.set_name(user_info.display_name);
-
- /* FIXME: remove this after switching S3 to the new authentication
- * infrastructure. */
- s->auth.identity = rgw::auth::transform_old_authinfo(s);
} else {
ldout(s->cct, 0) << "No attached policy found!" << dendl;
}
auth_sign = auth_str.substr(pos + 1);
}
- rgw::auth::s3::S3AuthFactory aplfact(store);
- rgw::auth::s3::RGWS3V2Extractor extr;
-
- /* TODO(rzarzynski): the final strategy will be a part of Handler - exactly
- * like in the case of Swift API. */
- static rgw::auth::s3::ExternalAuthStrategy strategy(g_ceph_context,
- store, &extr);
- /* try external auth first */
- int external_auth_result = -ERR_INVALID_ACCESS_KEY;
+ /* 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);
try {
auto result = strategy.authenticate(s);
auto& applier = result.first;
if (! applier) {
- return -EACCES;
+ return -EPERM;
}
-
try {
applier->load_acct_info(*s->user);
s->perm_mask = applier->get_perm_mask();
applier->modify_request_state(s);
s->auth.identity = std::move(applier);
- } catch (int err) {
- ldout(s->cct, 5) << "applier threw err=" << err << dendl;
- external_auth_result = err;
- }
- } catch (int err) {
- ldout(s->cct, 5) << "external auth strategy threw err=" << err << dendl;
- external_auth_result = err;
- }
- /* now try rados backend, but only if externals did not succeed */
- /* TODO(rzarzynski): aggregate the externals with the local engine in
- * as a final AuthStrategy for S3V2. */
- if (external_auth_result < 0) {
- rgw::auth::s3::LocalVersion2ndEngine localauth(s->cct, store, extr, &aplfact);
+ /* Populate the owner info. */
+ s->owner.set_id(s->user->user_id);
+ s->owner.set_name(s->user->display_name);
- if (! s->cct->_conf->rgw_s3_auth_use_rados) {
- return external_auth_result;
- }
- try {
- auto result = localauth.authenticate(s);
- auto& applier = result.first;
- if (! applier) {
- return external_auth_result;
- }
- try {
- applier->load_acct_info(*s->user);
- s->perm_mask = applier->get_perm_mask();
- applier->modify_request_state(s);
- s->auth.identity = std::move(applier);
- } catch (int err) {
- ldout(s->cct, 5) << "applier threw err=" << err << dendl;
- return err;
- }
- } catch (int err) {
- ldout(s->cct, 5) << "local auth engine threw err=" << err << dendl;
- return err;
- }
- if (s->user->system) {
- s->system_request = true;
- dout(20) << "system request" << dendl;
- s->info.args.set_system();
- string effective_uid = s->info.args.get(RGW_SYS_PARAM_PREFIX "uid");
- RGWUserInfo effective_user;
- if (!effective_uid.empty()) {
- rgw_user euid(effective_uid);
- int ret = rgw_get_user_info_by_uid(store, euid, effective_user);
- if (ret < 0) {
- ldout(s->cct, 0) << "User lookup failed!" << dendl;
- return -EACCES;
- }
- *(s->user) = effective_user;
- }
+ /* Success - not throwed. */
+ return 0;
+ } catch (const int err) {
+ ldout(s->cct, 5) << "applier threw err=" << err << dendl;
+ return err;
}
+ } catch (const int err) {
+ ldout(s->cct, 5) << "local auth engine threw err=" << err << dendl;
+ return err;
+ }
- } /* if external_auth_result < 0 */
-
- // populate the owner info
- s->owner.set_id(s->user->user_id);
- s->owner.set_name(s->user->display_name);
-
- return 0;
+ return -ERR_SIGNATURE_NO_MATCH;
}
int RGWHandler_Auth_S3::init(RGWRados *store, struct req_state *state,