}
-/* RGWRemoteAuthApplier */
-uint32_t RGWRemoteAuthApplier::get_perms_from_aclspec(const aclspec_t& aclspec) const
-{
- uint32_t perm = 0;
-
- /* For backward compatibility with ACLOwner. */
- perm |= rgw_perms_from_aclspec_default_strategy(info.acct_user,
- aclspec);
-
- /* We also need to cover cases where rgw_keystone_implicit_tenants
- * was enabled. */
- if (info.acct_user.tenant.empty()) {
- const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
-
- perm |= rgw_perms_from_aclspec_default_strategy(tenanted_acct_user,
- aclspec);
- }
-
- /* Now it's a time for invoking additional strategy that was supplied by
- * a specific auth engine. */
- if (extra_acl_strategy) {
- perm |= extra_acl_strategy(aclspec);
- }
-
- ldout(cct, 20) << "from ACL got perm=" << perm << dendl;
- return perm;
-}
-
-bool RGWRemoteAuthApplier::is_admin_of(const rgw_user& uid) const
-{
- return info.is_admin;
-}
-
-bool RGWRemoteAuthApplier::is_owner_of(const rgw_user& uid) const
-{
- if (info.acct_user.tenant.empty()) {
- const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
-
- if (tenanted_acct_user == uid) {
- return true;
- }
- }
-
- return info.acct_user == uid;
-}
-
-void RGWRemoteAuthApplier::to_str(std::ostream& out) const
-{
- out << "RGWRemoteAuthApplier(acct_user=" << info.acct_user
- << ", acct_name=" << info.acct_name
- << ", perm_mask=" << info.perm_mask
- << ", is_admin=" << info.is_admin << ")";
-}
-
-void RGWRemoteAuthApplier::create_account(const rgw_user& acct_user,
- RGWUserInfo& user_info) const /* out */
-{
- rgw_user new_acct_user = acct_user;
-
- if (info.acct_type) {
- //ldap/keystone for s3 users
- user_info.type = info.acct_type;
- }
-
- /* Administrator may enforce creating new accounts within their own tenants.
- * The config parameter name is kept due to legacy. */
- if (new_acct_user.tenant.empty() && g_conf->rgw_keystone_implicit_tenants) {
- new_acct_user.tenant = new_acct_user.id;
- }
-
- user_info.user_id = new_acct_user;
- user_info.display_name = info.acct_name;
-
- int ret = rgw_store_user_info(store, user_info, nullptr, nullptr,
- real_time(), true);
- if (ret < 0) {
- ldout(cct, 0) << "ERROR: failed to store new user info: user="
- << user_info.user_id << " ret=" << ret << dendl;
- throw ret;
- }
-}
-
-/* TODO(rzarzynski): we need to handle display_name changes. */
-void RGWRemoteAuthApplier::load_acct_info(RGWUserInfo& user_info) const /* out */
-{
- /* It's supposed that RGWRemoteAuthApplier tries to load account info
- * that belongs to the authenticated identity. Another policy may be
- * applied by using a RGWThirdPartyAccountAuthApplier decorator. */
- const rgw_user& acct_user = info.acct_user;
-
- /* Normally, empty "tenant" field of acct_user means the authenticated
- * identity has the legacy, global tenant. However, due to inclusion
- * of multi-tenancy, we got some special compatibility kludge for remote
- * backends like Keystone.
- * If the global tenant is the requested one, we try the same tenant as
- * the user name first. If that RGWUserInfo exists, we use it. This way,
- * migrated OpenStack users can get their namespaced containers and nobody's
- * the wiser.
- * If that fails, we look up in the requested (possibly empty) tenant.
- * If that fails too, we create the account within the global or separated
- * namespace depending on rgw_keystone_implicit_tenants. */
- if (acct_user.tenant.empty()) {
- const rgw_user tenanted_uid(acct_user.id, acct_user.id);
-
- if (rgw_get_user_info_by_uid(store, tenanted_uid, user_info) >= 0) {
- /* Succeeded. */
- return;
- }
- }
-
- if (rgw_get_user_info_by_uid(store, acct_user, user_info) < 0) {
- ldout(cct, 0) << "NOTICE: couldn't map swift user " << acct_user << dendl;
- create_account(acct_user, user_info);
- }
-
- /* Succeeded if we are here (create_account() hasn't throwed). */
-}
-
-
-/* LocalAuthApplier */
-/* static declaration */
-const std::string RGWLocalAuthApplier::NO_SUBUSER;
-
-uint32_t RGWLocalAuthApplier::get_perms_from_aclspec(const aclspec_t& aclspec) const
-{
- return rgw_perms_from_aclspec_default_strategy(user_info.user_id, aclspec);
-}
-
-bool RGWLocalAuthApplier::is_admin_of(const rgw_user& uid) const
-{
- return user_info.admin || user_info.system;
-}
-
-bool RGWLocalAuthApplier::is_owner_of(const rgw_user& uid) const
-{
- return uid == user_info.user_id;
-}
-
-void RGWLocalAuthApplier::to_str(std::ostream& out) const
-{
- out << "RGWLocalAuthApplier(acct_user=" << user_info.user_id
- << ", acct_name=" << user_info.display_name
- << ", subuser=" << subuser
- << ", perm_mask=" << get_perm_mask()
- << ", is_admin=" << static_cast<int>(user_info.admin) << ")";
-}
-
-uint32_t RGWLocalAuthApplier::get_perm_mask(const std::string& subuser_name,
- const RGWUserInfo &uinfo) const
-{
- if (!subuser_name.empty() && subuser_name != NO_SUBUSER) {
- const auto iter = uinfo.subusers.find(subuser_name);
-
- if (iter != std::end(uinfo.subusers)) {
- return iter->second.perm_mask;
- } else {
- /* Subuser specified but not found. */
- return RGW_PERM_NONE;
- }
- } else {
- /* Due to backward compatibility. */
- return RGW_PERM_FULL_CONTROL;
- }
-}
-
-void RGWLocalAuthApplier::load_acct_info(RGWUserInfo& user_info) const /* out */
-{
- /* Load the account that belongs to the authenticated identity. An extra call
- * to RADOS may be safely skipped in this case. */
- user_info = this->user_info;
-}
-
-
-RGWAuthApplier::aplptr_t RGWAnonymousAuthEngine::authenticate() const
-{
- RGWUserInfo user_info;
- rgw_get_anon_user(user_info);
-
- return apl_factory->create_apl_local(cct, user_info,
- RGWLocalAuthApplier::NO_SUBUSER);
-}
-
-
-/* Keystone */
-bool RGWKeystoneAuthEngine::is_applicable() const noexcept
-{
- if (! RGWTokenBasedAuthEngine::is_applicable()) {
- return false;
- }
-
- return ! cct->_conf->rgw_keystone_url.empty();
-}
-
-rgw::keystone::TokenEnvelope
-RGWKeystoneAuthEngine::decode_pki_token(const std::string& token) const
-{
- bufferlist token_body_bl;
- int ret = rgw_decode_b64_cms(cct, token, token_body_bl);
- if (ret < 0) {
- ldout(cct, 20) << "cannot decode pki token" << dendl;
- throw ret;
- } else {
- ldout(cct, 20) << "successfully decoded pki token" << dendl;
- }
-
- rgw::keystone::TokenEnvelope token_body;
- ret = token_body.parse(cct, token, token_body_bl,
- rgw::keystone::CephCtxConfig::get_instance().get_api_version());
- if (ret < 0) {
- throw ret;
- }
-
- return token_body;
-}
-
-rgw::keystone::TokenEnvelope
-RGWKeystoneAuthEngine::get_from_keystone(const std::string& token) const
-{
- using RGWValidateKeystoneToken
- = rgw::keystone::Service::RGWValidateKeystoneToken;
-
- bufferlist token_body_bl;
- RGWValidateKeystoneToken validate(cct, &token_body_bl);
-
- std::string url
- = rgw::keystone::CephCtxConfig::get_instance().get_endpoint_url();
- if (url.empty()) {
- throw -EINVAL;
- }
-
- const auto keystone_version = rgw::keystone::CephCtxConfig::get_instance().get_api_version();
- if (keystone_version == rgw::keystone::ApiVersion::VER_2) {
- url.append("v2.0/tokens/" + token);
- } else if (keystone_version == rgw::keystone::ApiVersion::VER_3) {
- url.append("v3/auth/tokens");
- validate.append_header("X-Subject-Token", token);
- }
-
- std::string admin_token;
- if (rgw::keystone::Service::get_admin_token(
- cct,
- rgw::keystone::TokenCache::get_instance<rgw::keystone::CephCtxConfig>(),
- rgw::keystone::CephCtxConfig::get_instance(),
- admin_token) < 0) {
- throw -EINVAL;
- }
-
- validate.append_header("X-Auth-Token", admin_token);
- validate.set_send_length(0);
-
- int ret = validate.process(url.c_str());
- if (ret < 0) {
- throw ret;
- }
-
- /* NULL terminate for debug output. */
- token_body_bl.append(static_cast<char>(0));
- ldout(cct, 20) << "received response status=" << validate.get_http_status()
- << ", body=" << token_body_bl.c_str() << dendl;
-
- /* Detect Keystone rejection earlier than during the token parsing.
- * Although failure at the parsing phase doesn't impose a threat,
- * this allows to return proper error code (EACCESS instead of EINVAL
- * or similar) and thus improves logging. */
- if (validate.get_http_status() ==
- /* Most likely: wrong admin credentials or admin token. */
- RGWValidateKeystoneToken::HTTP_STATUS_UNAUTHORIZED ||
- validate.get_http_status() ==
- /* Most likely: non-existent token supplied by the client. */
- RGWValidateKeystoneToken::HTTP_STATUS_NOTFOUND) {
- throw -EACCES;
- }
-
- rgw::keystone::TokenEnvelope token_body;
- ret = token_body.parse(cct, token, token_body_bl, keystone_version);
- if (ret < 0) {
- throw ret;
- }
-
- return token_body;
-}
-
-RGWRemoteAuthApplier::AuthInfo
-RGWKeystoneAuthEngine::get_creds_info(const rgw::keystone::TokenEnvelope& token,
- const std::vector<std::string>& admin_roles
- ) const noexcept
-{
- using acct_privilege_t = RGWRemoteAuthApplier::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 RGWRemoteAuthApplier::AuthInfo {
- /* 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,
- };
-}
-
static inline const std::string make_spec_item(const std::string& tenant,
const std::string& id)
{
return tenant + ":" + id;
}
-RGWKeystoneAuthEngine::acl_strategy_t
-RGWKeystoneAuthEngine::get_acl_strategy(const rgw::keystone::TokenEnvelope& token) const
-{
- /* The primary identity is constructed upon UUIDs. */
- const auto& tenant_uuid = token.get_project_id();
- const auto& user_uuid = token.get_user_id();
-
- /* For Keystone v2 an alias may be also used. */
- const auto& tenant_name = token.get_project_name();
- const auto& user_name = token.get_user_name();
-
- /* Construct all possible combinations including Swift's wildcards. */
- const std::array<std::string, 6> allowed_items = {
- make_spec_item(tenant_uuid, user_uuid),
- make_spec_item(tenant_name, user_name),
-
- /* Wildcards. */
- make_spec_item(tenant_uuid, "*"),
- make_spec_item(tenant_name, "*"),
- make_spec_item("*", user_uuid),
- make_spec_item("*", user_name),
- };
-
- /* Lambda will obtain a copy of (not a reference to!) allowed_items. */
- return [allowed_items](const RGWIdentityApplier::aclspec_t& aclspec) {
- uint32_t perm = 0;
-
- for (const auto& allowed_item : allowed_items) {
- const auto iter = aclspec.find(allowed_item);
-
- if (std::end(aclspec) != iter) {
- perm |= iter->second;
- }
- }
-
- return perm;
- };
-}
-
-RGWAuthApplier::aplptr_t RGWKeystoneAuthEngine::authenticate() const
-{
- rgw::keystone::TokenEnvelope t;
-
- /* This will be initialized on the first call to this method. In C++11 it's
- * also thread-safe. */
- static struct RolesCacher {
- RolesCacher(CephContext * const cct) {
- get_str_vec(cct->_conf->rgw_keystone_accepted_roles, plain);
- get_str_vec(cct->_conf->rgw_keystone_accepted_admin_roles, admin);
-
- /* Let's suppose that having an admin role implies also a regular one. */
- plain.insert(std::end(plain), std::begin(admin), std::end(admin));
- }
-
- std::vector<std::string> plain;
- std::vector<std::string> admin;
- } roles(cct);
-
- /* Token ID is a concept that makes dealing with PKI tokens more effective.
- * Instead of storing several kilobytes, a short hash can be burried. */
- const auto& token_id = rgw_get_token_id(token);
- ldout(cct, 20) << "token_id=" << token_id << dendl;
-
- /* Check cache first. */
- if (rgw::keystone::TokenCache::get_instance<rgw::keystone::CephCtxConfig>().find(token_id, t)) {
- ldout(cct, 20) << "cached token.project.id=" << t.get_project_id()
- << dendl;
- return apl_factory->create_apl_remote(cct,
- get_acl_strategy(t),
- get_creds_info(t, roles.admin));
- }
-
- /* Retrieve token. */
- if (rgw_is_pki_token(token)) {
- try {
- t = decode_pki_token(token);
- } catch (...) {
- /* Last resort. */
- t = get_from_keystone(token);
- }
- } else {
- /* Can't decode, just go to the Keystone server for validation. */
- t = get_from_keystone(token);
- }
-
- /* Verify expiration. */
- if (t.expired()) {
- ldout(cct, 0) << "got expired token: " << t.get_project_name()
- << ":" << t.get_user_name()
- << " expired: " << t.get_expires() << dendl;
- return nullptr;
- }
-
- /* Check for necessary roles. */
- for (const auto& role : 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;
- rgw::keystone::TokenCache::get_instance<rgw::keystone::CephCtxConfig>().add(token_id, t);
- return apl_factory->create_apl_remote(cct,
- get_acl_strategy(t),
- get_creds_info(t, roles.admin));
- }
- }
-
- ldout(cct, 0) << "user does not hold a matching role; required roles: "
- << g_conf->rgw_keystone_accepted_roles << dendl;
-
- return nullptr;
-}
rgw::auth::Engine::result_t
rgw::auth::Strategy::authenticate(const req_state* const s) const
#define RGW_USER_ANON_ID "anonymous"
-/* Load information about identity that will be used by RGWOp to authorize
- * any operation that comes from an authenticated user. */
-class RGWIdentityApplier {
-public:
- typedef std::map<std::string, int> aclspec_t;
-
- virtual ~RGWIdentityApplier() {};
-
- /* Translate the ACL provided in @aclspec into concrete permission set that
- * can be used in authorization phase (particularly in verify_permission
- * method of a given RGWOp).
- *
- * XXX: implementation is responsible for giving the real semantic to the
- * items in @aclspec. That is, their meaning may depend on particular auth
- * engine that was used. */
- virtual uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const = 0;
-
- /* Verify whether a given identity *can be treated as* an admin of
- * the rgw_user (account in Swift's terminology) specified in @uid. */
- virtual bool is_admin_of(const rgw_user& uid) const = 0;
-
- /* Verify whether a given identity *is* the owner of the rgw_user
- * (account in Swift's terminology) specified in @uid. */
- virtual bool is_owner_of(const rgw_user& uid) const = 0;
-
- /* Return the permission mask that is used to narrow down the set of
- * operations allowed for a given identity. This method reflects the idea
- * of subuser tied to RGWUserInfo. */
- virtual uint32_t get_perm_mask() const = 0;
-
- virtual bool is_anonymous() const final {
- /* If the identity owns the anonymous account (rgw_user), it's considered
- * the anonymous identity. */
- return is_owner_of(rgw_user(RGW_USER_ANON_ID));
- }
-
- virtual void to_str(std::ostream& out) const = 0;
-};
-
-inline std::ostream& operator<<(std::ostream& out,
- const RGWIdentityApplier &id) {
- id.to_str(out);
- return out;
-}
-
-uint32_t rgw_perms_from_aclspec_default_strategy(
- const rgw_user& uid,
- const RGWIdentityApplier::aclspec_t& aclspec);
-
-
-/* Interface for classes applying changes to request state/RADOS store imposed
- * by a particular RGWAuthEngine.
- *
- * Implementations must also conform to RGWIdentityApplier interface to apply
- * authorization policy (ACLs, account's ownership and entitlement).
- *
- * In contrast to RGWAuthEngine, implementations of this interface are allowed
- * to handle req_state or RGWRados in the read-write manner. */
-class RGWAuthApplier : public RGWIdentityApplier {
- template <typename DecorateeT> friend class RGWDecoratingAuthApplier;
-
-protected:
- CephContext * const cct;
-
-public:
- typedef std::unique_ptr<RGWAuthApplier> aplptr_t;
-
- RGWAuthApplier(CephContext * const cct) : cct(cct) {}
- ~RGWAuthApplier() override {};
-
- /* Fill provided RGWUserInfo with information about the account that
- * RGWOp will operate on. Errors are handled solely through exceptions.
- *
- * XXX: be aware that the "account" term refers to rgw_user. The naming
- * is legacy. */
- virtual void load_acct_info(RGWUserInfo& user_info) const = 0; /* out */
-
- /* Apply any changes to request state. This method will be most useful for
- * TempURL of Swift API or AWSv4. */
- virtual void modify_request_state(req_state * s) const {} /* in/out */
-};
-
-
-/* RGWRemoteAuthApplier targets those authentication engines which don't need
- * to ask the RADOS store while performing the auth process. Instead, they
- * obtain credentials from an external source like Keystone or LDAP.
- *
- * As the authenticated user may not have an account yet, RGWRemoteAuthApplier
- * must be able to create it basing on data passed by an auth engine. Those
- * data will be used to fill RGWUserInfo structure. */
-class RGWRemoteAuthApplier : public RGWAuthApplier {
-public:
- class AuthInfo {
- friend class RGWRemoteAuthApplier;
- protected:
- const rgw_user acct_user;
- const std::string acct_name;
- const uint32_t perm_mask;
- const bool is_admin;
- const uint32_t acct_type;
-
- public:
- enum class acct_privilege_t {
- IS_ADMIN_ACCT,
- IS_PLAIN_ACCT
- };
-
- AuthInfo(const rgw_user& acct_user,
- const std::string& acct_name,
- const uint32_t perm_mask,
- const acct_privilege_t level,
- const uint32_t acct_type=TYPE_NONE)
- : acct_user(acct_user),
- acct_name(acct_name),
- perm_mask(perm_mask),
- is_admin(acct_privilege_t::IS_ADMIN_ACCT == level),
- acct_type(acct_type) {
- }
- };
-
- using aclspec_t = rgw::auth::Identity::aclspec_t;
- typedef std::function<uint32_t(const aclspec_t&)> acl_strategy_t;
-
-protected:
- /* Read-write is intensional here due to RGWUserInfo creation process. */
- RGWRados * const store;
-
- /* Supplemental strategy for extracting permissions from ACLs. Its results
- * will be combined (ORed) with a default strategy that is responsible for
- * handling backward compatibility. */
- const acl_strategy_t extra_acl_strategy;
-
- const AuthInfo info;
-
- virtual void create_account(const rgw_user& acct_user,
- RGWUserInfo& user_info) const; /* out */
-
-public:
- RGWRemoteAuthApplier(CephContext * const cct,
- RGWRados * const store,
- acl_strategy_t&& extra_acl_strategy,
- const AuthInfo& info)
- : RGWAuthApplier(cct),
- store(store),
- extra_acl_strategy(std::move(extra_acl_strategy)),
- info(info) {
- }
-
- uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override;
- bool is_admin_of(const rgw_user& uid) const override;
- bool is_owner_of(const rgw_user& uid) const override;
- uint32_t get_perm_mask() const override { return info.perm_mask; }
- void to_str(std::ostream& out) const override;
- void load_acct_info(RGWUserInfo& user_info) const override; /* out */
-
- struct Factory {
- virtual ~Factory() {}
- /* Providing r-value reference here is required intensionally. Callee is
- * thus disallowed to handle std::function in a way that could inhibit
- * the move behaviour (like forgetting about std::moving a l-value). */
- virtual aplptr_t create_apl_remote(CephContext * const cct,
- acl_strategy_t&& extra_acl_strategy,
- const AuthInfo info) const = 0;
- };
-};
-
-
-/* Local auth applier targets those auth engines that store user information
- * in the RADOS store. As a consequence of performing the authentication, they
- * will have the RGWUserInfo structure loaded. Exploiting this trait allows to
- * avoid additional call to underlying RADOS store. */
-class RGWLocalAuthApplier : public RGWAuthApplier {
-protected:
- const RGWUserInfo user_info;
- const std::string subuser;
-
- uint32_t get_perm_mask(const std::string& subuser_name,
- const RGWUserInfo &uinfo) const;
-
-public:
- static const std::string NO_SUBUSER;
-
- RGWLocalAuthApplier(CephContext * const cct,
- const RGWUserInfo& user_info,
- const std::string subuser)
- : RGWAuthApplier(cct),
- user_info(user_info),
- subuser(subuser) {
- }
-
-
- uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override;
- bool is_admin_of(const rgw_user& uid) const override;
- bool is_owner_of(const rgw_user& uid) const override;
- uint32_t get_perm_mask() const override {
- return get_perm_mask(subuser, user_info);
- }
- void to_str(std::ostream& out) const override;
- void load_acct_info(RGWUserInfo& user_info) const override; /* out */
-
- struct Factory {
- virtual ~Factory() {}
- virtual aplptr_t create_apl_local(CephContext * const cct,
- const RGWUserInfo& user_info,
- const std::string& subuser) const = 0;
- };
-};
-
-
-/* Abstract class for authentication backends (auth engines) in RadosGW.
- *
- * An engine is supposed only to:
- * - authenticate (not authorize!) a given request basing on req_state,
- * - provide an upper layer with RGWAuthApplier to commit all changes to
- * data structures (like req_state) and to the RADOS store (creating
- * an account, synchronizing user personal info).
- * Auth engine MUST NOT make any changes to req_state nor RADOS store.
- *
- * Separation between authentication and global state modification has been
- * introduced because many auth engines are perfectly orthogonal to applier
- * and thus they can be decoupled. Additional motivation is clearly distinguish
- * all places which can modify underlying data structures. */
-class RGWAuthEngine {
-protected:
- CephContext * const cct;
-
- RGWAuthEngine(CephContext * const cct)
- : cct(cct) {
- }
- /* Make the engines non-copyable and non-moveable due to const-correctness
- * and aggregating applier factories less costly and error-prone. */
- RGWAuthEngine(const RGWAuthEngine&) = delete;
- RGWAuthEngine& operator=(const RGWAuthEngine&) = delete;
-
-public:
- /* Get name of the auth engine. */
- virtual const char* get_name() const noexcept = 0;
-
- /* Fast, non-throwing method for screening whether a concrete engine may
- * be interested in handling a specific request. */
- virtual bool is_applicable() const noexcept = 0;
-
- /* Throwing method for identity verification. When the check is positive
- * an implementation should return RGWAuthApplier::aplptr_t containing
- * a non-null pointer to object conforming the RGWAuthApplier interface.
- * Otherwise, the authentication is treated as failed.
- * An error may be signalised by throwing an exception of int type with
- * errno value inside. Those value are always negative. */
- virtual RGWAuthApplier::aplptr_t authenticate() const = 0;
-
- virtual ~RGWAuthEngine() {};
-};
-
-
-/* Abstract base class for all token-based auth engines. */
-class RGWTokenBasedAuthEngine : public RGWAuthEngine {
-protected:
- const std::string token;
-
-public:
- class Extractor {
- public:
- virtual ~Extractor() {};
- virtual std::string get_token() const = 0;
- };
-
- RGWTokenBasedAuthEngine(CephContext * const cct,
- const Extractor& extr)
- : RGWAuthEngine(cct),
- token(extr.get_token()) {
- }
-
- bool is_applicable() const noexcept override {
- return !token.empty();
- }
-};
-
-/* Keystone. */
-class RGWKeystoneAuthEngine : public RGWTokenBasedAuthEngine {
-protected:
- using acl_strategy_t = RGWRemoteAuthApplier::acl_strategy_t;
- using token_envelope_t = rgw::keystone::TokenEnvelope;
-
- const RGWRemoteAuthApplier::Factory * const apl_factory;
-
- /* Helper methods. */
- token_envelope_t decode_pki_token(const std::string& token) const;
- token_envelope_t get_from_keystone(const std::string& token) const;
- acl_strategy_t get_acl_strategy(const token_envelope_t& token) const;
- RGWRemoteAuthApplier::AuthInfo get_creds_info(const token_envelope_t& token,
- const std::vector<std::string>& admin_roles
- ) const noexcept;
-public:
- RGWKeystoneAuthEngine(CephContext * const cct,
- const Extractor& extr,
- const RGWRemoteAuthApplier::Factory * const apl_factory)
- : RGWTokenBasedAuthEngine(cct, extr),
- apl_factory(apl_factory) {
- }
-
- const char* get_name() const noexcept override {
- return "RGWKeystoneAuthEngine";
- }
-
- bool is_applicable() const noexcept override;
- RGWAuthApplier::aplptr_t authenticate() const override;
-};
-
-
-/* Anonymous */
-class RGWAnonymousAuthEngine : public RGWTokenBasedAuthEngine {
- const RGWLocalAuthApplier::Factory * const apl_factory;
-
-public:
- RGWAnonymousAuthEngine(CephContext * const cct,
- const Extractor& extr,
- const RGWLocalAuthApplier::Factory * const apl_factory)
- : RGWTokenBasedAuthEngine(cct, extr),
- apl_factory(apl_factory) {
- }
-
- bool is_applicable() const noexcept override {
- return token.empty();
- }
-
- const char* get_name() const noexcept override {
- return "RGWAnonymousAuthEngine";
- }
-
- RGWAuthApplier::aplptr_t authenticate() const override;
-};
-
-
namespace rgw {
namespace auth {