op_ret = rgw_get_user_info_by_access_key(store, s3_access_key, user_info);
if (op_ret < 0) {
S3AuthFactory aplfact(store, s->account_name);
- RGWGetPolicyLDAPTokenExtractor token_extr(s3_access_key);
- RGWLDAPAuthEngine ldap(s->cct, store, token_extr, &aplfact);
+ RGWGetPolicyV2Extractor extr(s3_access_key, received_signature_str);
+ RGWLDAPAuthEngine ldap(s->cct, store, extr, &aplfact);
// try external authenticators
if (store->ctx()->_conf->rgw_s3_auth_use_keystone &&
store->ctx()->_conf->rgw_keystone_url.empty())
s->perm_mask = RGW_PERM_FULL_CONTROL;
}
} else if (ldap.is_applicable()) {
- auto applier = ldap.authenticate();
- if (! applier) {
+ try {
+ auto applier = ldap.authenticate();
+ 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;
+ }
+ } catch (int err) {
return -EACCES;
- } else {
- applier->load_acct_info(*s->user);
- s->perm_mask = applier->get_perm_mask();
- s->auth_identity = std::move(applier);
}
} else {
return -EACCES;
}
S3AuthFactory aplfact(store, s->account_name);
- RGWLDAPTokenExtractor token_extr(s);
- RGWLDAPAuthEngine ldap(s->cct, store, token_extr, &aplfact);
+ RGWS3V2Extractor extr(s);
+ RGWLDAPAuthEngine ldap(s->cct, store, extr, &aplfact);
if (ldap.is_applicable()) {
- auto applier = ldap.authenticate();
- if (!applier) {
- external_auth_result = -EACCES;
- } else {
- applier->load_acct_info(*s->user);
- s->perm_mask = applier->get_perm_mask();
- s->auth_identity = std::move(applier);
- external_auth_result = 0;
+ try {
+ auto applier = ldap.authenticate();
+ 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) << "ldap auth engine threw err=" << err << dendl;
+ external_auth_result = err;
}
}
- /* keystone failed (or not enabled); check if we want to use rados backend */
- if (!store->ctx()->_conf->rgw_s3_auth_use_rados
- && external_auth_result < 0)
- return external_auth_result;
-
/* now try rados backend, but only if keystone did not succeed */
if (external_auth_result < 0) {
- /* get the user info */
- if (rgw_get_user_info_by_access_key(store, auth_id, *(s->user)) < 0) {
- dout(5) << "error reading user info, uid=" << auth_id
- << " can't authenticate" << dendl;
- return external_auth_result;
- }
+ RGWS3V2LocalAuthEngine localauth(s, store, extr, &aplfact);
- /* now verify signature */
- string auth_hdr;
- if (!rgw_create_s3_canonical_header(s->info, &s->header_time, auth_hdr,
- qsr)) {
- dout(10) << "failed to create auth header\n" << auth_hdr << dendl;
- return -EPERM;
- }
- dout(10) << "auth_hdr:\n" << auth_hdr << dendl;
-
- time_t req_sec = s->header_time.sec();
- if ((req_sec < now - RGW_AUTH_GRACE_MINS * 60 ||
- req_sec > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) {
- dout(10) << "req_sec=" << req_sec << " now=" << now
- << "; now - RGW_AUTH_GRACE_MINS=" << now - RGW_AUTH_GRACE_MINS * 60
- << "; now + RGW_AUTH_GRACE_MINS=" << now + RGW_AUTH_GRACE_MINS * 60
- << dendl;
- dout(0) << "NOTICE: request time skew too big now=" << utime_t(now, 0)
- << " req_time=" << s->header_time
- << dendl;
- return -ERR_REQUEST_TIME_SKEWED;
- }
-
- map<string, RGWAccessKey>::iterator iter =
- s->user->access_keys.find(auth_id);
- if (iter == s->user->access_keys.end()) {
- dout(0) << "ERROR: access key not encoded in user info" << dendl;
- return -EPERM;
- }
- RGWAccessKey& k = iter->second;
-
- if (!k.subuser.empty()) {
- map<string, RGWSubUser>::iterator uiter =
- s->user->subusers.find(k.subuser);
- if (uiter == s->user->subusers.end()) {
- dout(0) << "NOTICE: could not find subuser: " << k.subuser << dendl;
- return -EPERM;
+ if (! localauth.is_applicable()) {
+ return external_auth_result;
+ }
+ try {
+ auto applier = localauth.authenticate();
+ 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;
}
- RGWSubUser& subuser = uiter->second;
- s->perm_mask = subuser.perm_mask;
- } else
- s->perm_mask = RGW_PERM_FULL_CONTROL;
-
- string digest;
- int ret = rgw_get_s3_header_digest(auth_hdr, k.key, digest);
- if (ret < 0) {
- return -EPERM;
- }
-
- dout(15) << "calculated digest=" << digest << dendl;
- dout(15) << "auth_sign=" << auth_sign << dendl;
- dout(15) << "compare=" << auth_sign.compare(digest) << dendl;
-
- if (auth_sign != digest) {
- return -ERR_SIGNATURE_NO_MATCH;
- }
-
if (s->user->system) {
s->system_request = true;
dout(20) << "system request" << dendl;
RGWUserInfo effective_user;
if (!effective_uid.empty()) {
rgw_user euid(effective_uid);
- ret = rgw_get_user_info_by_uid(store, euid, effective_user);
+ 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;
void RGWLDAPAuthEngine::init(CephContext* const cct)
{
- if (!ldh) {
+ if (! ldh) {
std::lock_guard<std::mutex> lck(mtx);
- if (!ldh) {
+ if (! ldh) {
const string& ldap_uri = cct->_conf->rgw_ldap_uri;
const string& ldap_binddn = cct->_conf->rgw_ldap_binddn;
const string& ldap_searchdn = cct->_conf->rgw_ldap_searchdn;
bool RGWLDAPAuthEngine::is_applicable() const noexcept
{
- if (!RGWTokenBasedAuthEngine::is_applicable()) {
+ if (! RGWS3V2AuthEngine::is_applicable()) {
return false;
}
- if (!cct->_conf->rgw_s3_auth_use_ldap ||
+ if (! cct->_conf->rgw_s3_auth_use_ldap ||
cct->_conf->rgw_ldap_uri.empty()) {
return false;
}
- if(!base64_token.valid()) {
- return false;
- }
-
return true;
}
RGWAuthApplier::aplptr_t RGWLDAPAuthEngine::authenticate() const
{
+ if(! base64_token.valid()) {
+ return nullptr;
+ }
+ //TODO: Uncomment, when we have a migration plan in place.
//Check if a user of type other than 'ldap' is already present, if yes, then
//return error.
- RGWUserInfo user_info;
+ /*RGWUserInfo user_info;
user_info.user_id = base64_token.id;
if (rgw_get_user_info_by_uid(store, user_info.user_id, user_info) >= 0) {
if (user_info.type != TYPE_LDAP) {
ldout(cct, 10) << "ERROR: User id of type: " << user_info.type << " is already present" << dendl;
return nullptr;
}
- }
+ }*/
if (ldh->auth(base64_token.id, base64_token.key) != 0) {
return nullptr;
return apl_factory->create_apl_remote(cct, get_acl_strategy(), get_creds_info(base64_token));
}
-std::string RGWLDAPTokenExtractor::get_token() const
+void RGWS3V2Extractor::get_auth_keys(std::string& access_key_id,
+ std::string& signature,
+ std::string& expires,
+ bool& qsr) const
{
- string token = "";
- if (!s->http_auth || !(*s->http_auth)) {
- token = s->info.args.get("AWSAccessKeyId");
+ qsr = false;
+ if (! s->http_auth || !(*s->http_auth)) {
+ access_key_id = s->info.args.get("AWSAccessKeyId");
+ signature = s->info.args.get("Signature");
+ expires = s->info.args.get("Expires");
+ qsr = true;
} else {
string auth_str(s->http_auth + 4);
int pos = auth_str.rfind(':');
- if (pos >=0 ) {
- token = auth_str.substr(0, pos);
+ if (pos >= 0) {
+ access_key_id = auth_str.substr(0, pos);
+ signature = auth_str.substr(pos + 1);
+ }
+ }
+}
+
+bool RGWS3V2LocalAuthEngine::is_applicable() const noexcept
+{
+ if (! RGWS3V2AuthEngine::is_applicable()) {
+ return false;
+ }
+ if (! s->cct->_conf->rgw_s3_auth_use_rados) {
+ return false;
+ }
+
+ return true;
+}
+
+RGWAuthApplier::aplptr_t RGWS3V2LocalAuthEngine::authenticate() const
+{
+ if (access_key_id.empty() || signature.empty()) {
+ ldout(s->cct, 5) << "access_key_id or signature is empty" << dendl;
+ throw -EINVAL;
+ }
+
+ time_t now;
+ time(&now);
+ if (! expires.empty()) {
+ time_t exp = atoll(expires.c_str());
+ if (now >= exp) {
+ throw -EPERM;
+ }
+ }
+ /* get the user info */
+ string access_key = access_key_id;
+ if (rgw_get_user_info_by_access_key(store, access_key, *(s->user)) < 0) {
+ ldout(s->cct, 5) << "error reading user info, uid=" << access_key_id
+ << " can't authenticate" << dendl;
+ return nullptr;
+ }
+ //TODO: Uncomment, when we have a migration plan in place.
+ /*else {
+ if (s->user->type != TYPE_RGW) {
+ ldout(cct, 10) << "ERROR: User id of type: " << s->user->type << " is present" << dendl;
+ throw -EPERM;
}
+ }*/
+
+ /* now verify signature */
+ string auth_hdr;
+ if (! rgw_create_s3_canonical_header(s->info, &s->header_time, auth_hdr,
+ qsr)) {
+ ldout(s->cct, 10) << "failed to create auth header\n" << auth_hdr << dendl;
+ throw -EPERM;
+ }
+ ldout(s->cct, 10) << "auth_hdr:\n" << auth_hdr << dendl;
+
+ time_t req_sec = s->header_time.sec();
+ if ((req_sec < now - RGW_AUTH_GRACE_MINS * 60 ||
+ req_sec > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) {
+ ldout(s->cct, 10) << "req_sec=" << req_sec << " now=" << now
+ << "; now - RGW_AUTH_GRACE_MINS=" << now - RGW_AUTH_GRACE_MINS * 60
+ << "; now + RGW_AUTH_GRACE_MINS=" << now + RGW_AUTH_GRACE_MINS * 60
+ << dendl;
+ ldout(s->cct, 0) << "NOTICE: request time skew too big now=" << utime_t(now, 0)
+ << " req_time=" << s->header_time
+ << dendl;
+ throw -ERR_REQUEST_TIME_SKEWED;
+ }
+
+ map<string, RGWAccessKey>::iterator iter = s->user->access_keys.find(access_key_id);
+ if (iter == s->user->access_keys.end()) {
+ ldout(s->cct, 0) << "ERROR: access key not encoded in user info" << dendl;
+ throw -EPERM;
+ }
+ RGWAccessKey& k = iter->second;
+
+ string digest;
+ int ret = rgw_get_s3_header_digest(auth_hdr, k.key, digest);
+ if (ret < 0) {
+ throw -EPERM;
}
- return token;
+
+ ldout(s->cct, 15) << "calculated digest=" << digest << dendl;
+ ldout(s->cct, 15) << "auth_sign=" << signature << dendl;
+ ldout(s->cct, 15) << "compare=" << signature.compare(digest) << dendl;
+
+ if (signature != digest) {
+ throw -ERR_SIGNATURE_NO_MATCH;
+ }
+
+ return apl_factory->create_apl_local(cct, *(s->user), k.subuser);
}
return 0;
}
-class RGWLDAPAuthEngine: RGWTokenBasedAuthEngine
+class RGWS3V2AuthEngine : public RGWAuthEngine {
+protected:
+ std::string access_key_id;
+ std::string signature;
+ std::string expires;
+ bool qsr;
+
+public:
+ class Extractor {
+ public:
+ virtual ~Extractor() {};
+ virtual void get_auth_keys(std::string& access_key_id,
+ std::string& signature,
+ std::string& expires,
+ bool& qsr) const = 0;
+ };
+
+ RGWS3V2AuthEngine(CephContext* const cct, const Extractor& extr)
+ : RGWAuthEngine(cct) {
+ extr.get_auth_keys(access_key_id, signature, expires, qsr);
+ }
+
+ bool is_applicable() const noexcept override {
+ return ! (access_key_id.empty() && signature.empty());
+ }
+};
+
+class RGWS3V2Extractor : public RGWS3V2AuthEngine::Extractor {
+protected:
+ const req_state* const s;
+
+public:
+ RGWS3V2Extractor(const req_state * const s)
+ : s(s) {}
+
+ void get_auth_keys(std::string& access_key_id,
+ std::string& signature,
+ std::string& expires,
+ bool& qsr) const override;
+};
+
+class RGWLDAPAuthEngine: RGWS3V2AuthEngine
{
static rgw::LDAPHelper* ldh;
static std::mutex mtx;
RGWRados* const store,
Extractor &ex,
const RGWRemoteAuthApplier::Factory * const apl_factory)
- : RGWTokenBasedAuthEngine(cct, ex),
+ : RGWS3V2AuthEngine(cct, ex),
store(store),
apl_factory(apl_factory) {
init(cct);
- base64_token = rgw::from_base64(token);
+ base64_token = rgw::from_base64(access_key_id);
}
const char* get_name() const noexcept override {
return "RGWLDAPAuthEngine";
RGWAuthApplier::aplptr_t authenticate() const override;
};
-class RGWLDAPTokenExtractor : public RGWTokenBasedAuthEngine::Extractor {
+class RGWS3V2LocalAuthEngine: RGWS3V2AuthEngine
+{
protected:
- const req_state * const s;
+ req_state* const s;
+ RGWRados* const store;
+ const RGWLocalAuthApplier::Factory* const apl_factory;
public:
- RGWLDAPTokenExtractor(const req_state * const s)
- : s(s) {
+ RGWS3V2LocalAuthEngine(req_state* const s,
+ RGWRados* const store,
+ const Extractor& extr,
+ const RGWLocalAuthApplier::Factory * const apl_factory)
+ : RGWS3V2AuthEngine(s->cct, extr),
+ s(s),
+ store(store),
+ apl_factory(apl_factory) {
+ }
+
+ const char* get_name() const noexcept override {
+ return "RGWS3V2LocalAuthEngine";
}
- std::string get_token() const override;
+ bool is_applicable() const noexcept override;
+ RGWAuthApplier::aplptr_t authenticate() const override;
};
-class RGWGetPolicyLDAPTokenExtractor : public RGWTokenBasedAuthEngine::Extractor {
+class RGWGetPolicyV2Extractor:public RGWS3V2AuthEngine::Extractor {
+private:
std::string access_key_id;
+ std::string signature;
+
public:
- RGWGetPolicyLDAPTokenExtractor(std::string access_key_id) {
- access_key_id = std::move(access_key_id);
+ RGWGetPolicyV2Extractor(std::string access_key_id, std::string signature) {
+ access_key_id = std::move(access_key_id),
+ signature = std::move(signature);
}
- std::string get_token() const {
- return access_key_id;
+ void get_auth_keys(std::string& access_key_id,
+ std::string& signature,
+ std::string& expires,
+ bool& qsr) const override {
+ access_key_id = this->access_key_id;
+ signature = this->signature;
}
};
-class S3AuthFactory : public RGWRemoteAuthApplier::Factory {
+class S3AuthFactory : public RGWRemoteAuthApplier::Factory,
+ public RGWLocalAuthApplier::Factory {
typedef RGWAuthApplier::aplptr_t aplptr_t;
- RGWRados * const store;
+ RGWRados* const store;
const std::string acct_override;
public:
- S3AuthFactory(RGWRados * const store,
+ S3AuthFactory(RGWRados* const store,
const std::string& acct_override)
: store(store),
acct_override(acct_override) {
}
- aplptr_t create_apl_remote(CephContext * const cct,
+ aplptr_t create_apl_remote(CephContext* const cct,
RGWRemoteAuthApplier::acl_strategy_t&& acl_alg,
const RGWRemoteAuthApplier::AuthInfo info
) const override {
RGWRemoteAuthApplier(cct, store, std::move(acl_alg), info),
store, acct_override));
}
+ aplptr_t create_apl_local(CephContext* const cct,
+ const RGWUserInfo& user_info,
+ const std::string& subuser) const override {
+ return aplptr_t(
+ new RGWThirdPartyAccountAuthApplier<RGWLocalAuthApplier>(
+ RGWLocalAuthApplier(cct, user_info, subuser),
+ store, acct_override));
+ }
};
#endif /* CEPH_RGW_REST_S3_H */