}
}
+EC2Engine::acl_strategy_t
+EC2Engine::get_acl_strategy(const EC2Engine::token_envelope_t&) const
+{
+ /* This is based on the assumption that the default acl strategy in
+ * get_perms_from_aclspec, will take care. Extra acl spec is not required. */
+ return nullptr;
+}
+
+EC2Engine::auth_info_t
+EC2Engine::get_creds_info(const EC2Engine::token_envelope_t& token,
+ const std::vector<std::string>& admin_roles
+ ) const noexcept
+{
+ using acct_privilege_t = \
+ rgw::auth::RemoteApplier::AuthInfo::acct_privilege_t;
+
+ /* Check whether the user has an admin status. */
+ acct_privilege_t level = acct_privilege_t::IS_PLAIN_ACCT;
+ for (const auto& admin_role : admin_roles) {
+ if (token.has_role(admin_role)) {
+ level = acct_privilege_t::IS_ADMIN_ACCT;
+ break;
+ }
+ }
+
+ return auth_info_t {
+ /* Suggested account name for the authenticated user. */
+ rgw_user(token.get_project_id()),
+ /* User's display name (aka real name). */
+ token.get_project_name(),
+ /* Keystone doesn't support RGW's subuser concept, so we cannot cut down
+ * the access rights through the perm_mask. At least at this layer. */
+ RGW_PERM_FULL_CONTROL,
+ level,
+ TYPE_KEYSTONE,
+ };
+}
+
rgw::auth::Engine::result_t EC2Engine::authenticate(std::string access_key_id,
std::string signature,
std::string expires,
return std::make_pair(nullptr, nullptr);
}
+ if (! is_time_skew_ok(header_time, qsr)) {
+ throw -ERR_REQUEST_TIME_SKEWED;
+ }
+
/* check if we have a valid role */
bool found = false;
for (const auto& role : accepted_roles.plain) {
}
}
- if (!found) {
+ if (! found) {
ldout(cct, 5) << "s3 keystone: user does not hold a matching role;"
" required roles: "
<< cct->_conf->rgw_keystone_accepted_roles << dendl;
- }
-
- /* everything seems fine, continue with this user */
- ldout(cct, 5) << "s3 keystone: validated token: " << t.get_project_name()
- << ":" << t.get_user_name()
- << " expires: " << t.get_expires() << dendl;
-#if 0
- return 0;
-}
-
- /* Check for necessary roles. */
- for (const auto& role : accepted_roles.plain) {
- if (t.has_role(role) == true) {
- ldout(cct, 0) << "validated token: " << t.get_project_name()
- << ":" << t.get_user_name()
- << " expires: " << t.get_expires() << dendl;
-
- auto apl = apl_factory->create_apl_remote(cct, get_acl_strategy(t),
- get_creds_info(t, roles.admin));
- return std::make_pair(std::move(apl), nullptr);
- }
- }
-
- ldout(cct, 0) << "user does not hold a matching role; required roles: "
- << g_conf->rgw_keystone_accepted_roles << dendl;
-
- //return std::make_pair(nullptr, nullptr);
-#endif
+ return std::make_pair(nullptr, nullptr);
+ } else {
+ /* everything seems fine, continue with this user */
+ ldout(cct, 5) << "s3 keystone: validated token: " << t.get_project_name()
+ << ":" << t.get_user_name()
+ << " expires: " << t.get_expires() << dendl;
- if (! is_time_skew_ok(header_time, qsr)) {
- throw -ERR_REQUEST_TIME_SKEWED;
+ auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(t),
+ get_creds_info(t, accepted_roles.admin));
+ return std::make_pair(std::move(apl), nullptr);
}
-
- throw -ERR_INVALID_ACCESS_KEY;
}
}; /* namespace keystone */
#include "rgw_client_io.h"
#include "rgw_keystone.h"
+#include "rgw_auth_keystone.h"
#include <typeinfo> // for 'typeid'
store->ctx()->_conf->rgw_keystone_url.empty())
{
// keystone
- int external_auth_result = -EINVAL;
dout(20) << "s3 keystone: trying keystone auth" << dendl;
- RGW_Auth_S3_Keystone_ValidateToken keystone_validator(store->ctx());
- external_auth_result =
- keystone_validator.validate_s3token(s3_access_key,
- string(encoded_policy.c_str(),
- encoded_policy.length()),
- received_signature_str);
-
- if (external_auth_result < 0) {
- ldout(s->cct, 0) << "User lookup failed!" << dendl;
- err_msg = "Bad access key / signature";
- return -EACCES;
- }
+ /* FIXME: stop overriding the aplfact and extr from parent scope.
+ * This will be possible when other S3 engines are ported. */
+ rgw::auth::s3::S3AuthFactory aplfact(store);
+ rgw::auth::s3::RGWS3V2Extractor extr;
- string project_id = keystone_validator.response.get_project_id();
- rgw_user uid(project_id);
-
- user_info.user_id = project_id;
- user_info.display_name = keystone_validator.response.get_project_name();
-
- /* try to store user if it not already exists */
- if (rgw_get_user_info_by_uid(store, uid, user_info) < 0) {
- int ret = rgw_store_user_info(store, user_info, NULL, NULL, real_time(), true);
- if (ret < 0) {
- ldout(store->ctx(), 10)
- << "NOTICE: failed to store new user's info: ret="
- << ret << dendl;
- }
- s->perm_mask = RGW_PERM_FULL_CONTROL;
- }
+ 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<keystone_config_t>());
+ 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;
+ }
} else if (ldap.is_applicable()) {
try {
auto applier = ldap.authenticate();
if (store->ctx()->_conf->rgw_s3_auth_use_keystone
&& !store->ctx()->_conf->rgw_keystone_url.empty()) {
dout(20) << "s3 keystone: trying keystone auth" << dendl;
-
- RGW_Auth_S3_Keystone_ValidateToken keystone_validator(store->ctx());
- string token;
-
- if (!rgw_create_s3_canonical_header(s->info,
- &s->header_time, token, qsr)) {
- dout(10) << "failed to create auth header\n" << token << dendl;
- external_auth_result = -EPERM;
- } else {
- external_auth_result = keystone_validator.validate_s3token(auth_id, token,
- auth_sign);
- if (external_auth_result == 0) {
- // Check for time skew first
- 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;
- return -ERR_REQUEST_TIME_SKEWED;
- }
-
- string project_id = keystone_validator.response.get_project_id();
- s->user->user_id = project_id;
- s->user->display_name = keystone_validator.response.get_project_name(); // wow.
-
- rgw_user uid(project_id);
- /* try to store user if it not already exists */
- if (rgw_get_user_info_by_uid(store, uid, *(s->user)) < 0) {
- int ret = rgw_store_user_info(store, *(s->user), NULL, NULL, real_time(), true);
- if (ret < 0)
- dout(10) << "NOTICE: failed to store new user's info: ret="
- << ret << dendl;
+ /* FIXME: the factory and extractor will be shared across all external
+ * engines after making the transition to S3ExternalAuthStrategy. */
+ rgw::auth::s3::S3AuthFactory aplfact(store);
+ 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<keystone_config_t>());
+ 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;
}
-
- s->perm_mask = RGW_PERM_FULL_CONTROL;
}
+ } catch (int err) {
+ ldout(s->cct, 5) << "keystone auth engine threw err=" << err << dendl;
+ external_auth_result = err;
}
}