From aeb26c22c3fbd4a2ac016d084925cd966ad5e7e1 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Fri, 6 Jan 2017 16:59:49 +0100 Subject: [PATCH] rgw: aggregate S3's external auth engine as the ExternalAuthStrategy. Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_auth_s3.h | 60 +++++++++++++++++ src/rgw/rgw_rest_s3.cc | 148 +++++++++++------------------------------ 2 files changed, 98 insertions(+), 110 deletions(-) diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h index f5728caea23..345ac0ce840 100644 --- a/src/rgw/rgw_auth_s3.h +++ b/src/rgw/rgw_auth_s3.h @@ -8,6 +8,66 @@ #include #include "rgw_common.h" +#include "rgw_rest_s3.h" + +#include "rgw_auth.h" +#include "rgw_auth_keystone.h" + + +namespace rgw { +namespace auth { +namespace s3 { + +class ExternalAuthStrategy : public rgw::auth::Strategy, + public rgw::auth::RemoteApplier::Factory { + typedef rgw::auth::IdentityApplier::aplptr_t aplptr_t; + RGWRados* const store; + + using keystone_config_t = rgw::keystone::CephCtxConfig; + using keystone_cache_t = rgw::keystone::TokenCache; + using EC2Engine = rgw::auth::keystone::EC2Engine; + + EC2Engine keystone_engine; + LDAPEngine ldap_engine; + + aplptr_t create_apl_remote(CephContext* const cct, + 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)); + } + +public: + ExternalAuthStrategy(CephContext* const cct, + RGWRados* const store, + Version2ndEngine::Extractor* const extractor) + : store(store), + keystone_engine(cct, extractor, + static_cast(this), + keystone_config_t::get_instance(), + keystone_cache_t::get_instance()), + ldap_engine(cct, store, *extractor, + static_cast(this)) { + + if (cct->_conf->rgw_s3_auth_use_keystone && + ! cct->_conf->rgw_keystone_url.empty()) { + add_engine(Control::SUFFICIENT, keystone_engine); + } + + if (cct->_conf->rgw_s3_auth_use_ldap && + ! cct->_conf->rgw_ldap_uri.empty()) { + add_engine(Control::SUFFICIENT, ldap_engine); + } + } + + const char* get_name() const noexcept override { + return "rgw::auth::s3::AWSv2ExternalAuthStrategy"; + } +}; +} /* namespace s3 */ +} /* namespace auth */ +} /* namespace rgw */ void rgw_create_s3_canonical_header( const char *method, diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 119cb43e492..ef11286ca52 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1821,66 +1821,28 @@ int RGWPostObj_ObjStore_S3::get_policy() op_ret = rgw_get_user_info_by_access_key(store, s3_access_key, user_info); if (op_ret < 0) { - rgw::auth::s3::S3AuthFactory aplfact(store); - // try external authenticators - if (store->ctx()->_conf->rgw_s3_auth_use_keystone && - store->ctx()->_conf->rgw_keystone_url.empty()) - { - // keystone - dout(20) << "s3 keystone: trying keystone auth" << dendl; - - rgw::auth::s3::RGWS3V2Extractor extr; - - using keystone_config_t = rgw::keystone::CephCtxConfig; - using keystone_cache_t = rgw::keystone::TokenCache; - using EC2Engine = rgw::auth::keystone::EC2Engine; - - EC2Engine keystone_s3(s->cct, &extr, &aplfact, - keystone_config_t::get_instance(), - keystone_cache_t::get_instance()); - try { - auto result = keystone_s3.authenticate(s); - auto& applier = result.first; - if (! applier) { - return -EACCES; - } else { - 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) { - ldout(s->cct, 5) << "applier threw err=" << err << dendl; - return err; - } - } - } catch (int err) { - ldout(s->cct, 5) << "keystone auth engine threw err=" << err << dendl; - return err; + // 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; } - } else if (s->cct->_conf->rgw_s3_auth_use_ldap && - ! s->cct->_conf->rgw_ldap_uri.empty()) { - rgw::auth::s3::RGWGetPolicyV2Extractor extr(s3_access_key, received_signature_str); - rgw::auth::s3::LDAPEngine ldap(s->cct, store, extr, &aplfact); - try { - auto result = ldap.authenticate(s); - auto& applier = result.first; - if (! applier) { - 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); - } catch (int err) { - 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; } - } else { + } catch (int err) { return -EACCES; } } else { @@ -3995,70 +3957,36 @@ int RGW_Auth_S3::authorize_v2(RGWRados *store, struct req_state *s) rgw::auth::s3::S3AuthFactory aplfact(store); rgw::auth::s3::RGWS3V2Extractor extr; - /* try keystone auth first */ + /* 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; - if (store->ctx()->_conf->rgw_s3_auth_use_keystone - && !store->ctx()->_conf->rgw_keystone_url.empty()) { - dout(20) << "s3 keystone: trying keystone auth" << dendl; - - using keystone_config_t = rgw::keystone::CephCtxConfig; - using keystone_cache_t = rgw::keystone::TokenCache; - using EC2Engine = rgw::auth::keystone::EC2Engine; - - EC2Engine keystone_s3(s->cct, &extr, &aplfact, - keystone_config_t::get_instance(), - keystone_cache_t::get_instance()); - try { - auto result = keystone_s3.authenticate(s); - auto& applier = result.first; - if (! applier) { - external_auth_result = -EACCES; - } else { - 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); - external_auth_result = 0; - } catch (int err) { - ldout(s->cct, 5) << "applier threw err=" << err << dendl; - external_auth_result = err; - } - } - } catch (int err) { - ldout(s->cct, 5) << "keystone auth engine threw err=" << err << dendl; - external_auth_result = err; + try { + auto result = strategy.authenticate(s); + auto& applier = result.first; + if (! applier) { + return -EACCES; } - } - - if (s->cct->_conf->rgw_s3_auth_use_ldap && - ! s->cct->_conf->rgw_ldap_uri.empty()) { - rgw::auth::s3::LDAPEngine ldap(s->cct, store, extr, &aplfact); try { - auto result = ldap.authenticate(s); - auto& applier = result.first; - if (! applier) { - external_auth_result = -EACCES; - } else { - 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); - external_auth_result = 0; - } catch (int err) { - ldout(s->cct, 5) << "applier threw err=" << err << dendl; - external_auth_result = err; - } - } + 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) << "ldap auth engine threw err=" << err << dendl; + 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 keystone did not succeed */ + /* 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); -- 2.39.5