From: Pritha Srivastava Date: Wed, 10 Mar 2021 06:54:49 +0000 (+0530) Subject: rgw/sts: code to use session tags in AssumeRoleWithWebIdentity call, X-Git-Tag: v16.2.11~244^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=33ad94eda0e30ed6153c721d593408467fb85253;p=ceph.git rgw/sts: code to use session tags in AssumeRoleWithWebIdentity call, as aws:PrincipalTags in an IAM policy's Condition element. The incoming session tags in AssumeRoleWithWebIdentity call are passed along with the session credentials (temporary creds) as aws:PrincipalTags, and those can be used as Condition element of an IAM Policy. Signed-off-by: Pritha Srivastava (cherry picked from commit 6b2d3da84c0960260d06433906deda218a2cc43e) --- diff --git a/src/rgw/rgw_auth.cc b/src/rgw/rgw_auth.cc index e5492c36425f..e7c25cf87492 100644 --- a/src/rgw/rgw_auth.cc +++ b/src/rgw/rgw_auth.cc @@ -794,11 +794,11 @@ void rgw::auth::LocalApplier::write_ops_log_entry(rgw_log_entry& entry) const } void rgw::auth::RoleApplier::to_str(std::ostream& out) const { - out << "rgw::auth::LocalApplier(role name =" << role.name; + out << "rgw::auth::RoleApplier(role name =" << role.name; for (auto& policy: role.role_policies) { out << ", role policy =" << policy; } - out << ", token policy =" << token_policy; + out << ", token policy =" << token_attrs.token_policy; out << ")"; } @@ -814,7 +814,7 @@ bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const { } } else if (p.is_assumed_role()) { string tenant = p.get_tenant(); - string role_session = role.name + "/" + role_session_name; //role/role-session + string role_session = role.name + "/" + token_attrs.role_session_name; //role/role-session if (role.tenant == tenant && role_session == p.get_role_session()) { return true; } @@ -822,12 +822,12 @@ bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const { string id = p.get_id(); string tenant = p.get_tenant(); string oidc_id; - if (user_id.ns.empty()) { - oidc_id = user_id.id; + if (token_attrs.user_id.ns.empty()) { + oidc_id = token_attrs.user_id.id; } else { - oidc_id = user_id.ns + "$" + user_id.id; + oidc_id = token_attrs.user_id.ns + "$" + token_attrs.user_id.id; } - if (oidc_id == id && user_id.tenant == tenant) { + if (oidc_id == id && token_attrs.user_id.tenant == tenant) { return true; } } @@ -838,7 +838,7 @@ bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const { void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */ { /* Load the user id */ - user_info.user_id = this->user_id; + user_info.user_id = this->token_attrs.user_id; } void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const @@ -855,9 +855,9 @@ void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, } } - if (!this->token_policy.empty()) { + if (!this->token_attrs.token_policy.empty()) { try { - string policy = this->token_policy; + string policy = this->token_attrs.token_policy; bufferlist bl = bufferlist::static_from_string(policy); const rgw::IAM::Policy p(s->cct, role.tenant, bl); s->session_policies.push_back(std::move(p)); @@ -869,15 +869,19 @@ void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, } string condition = "aws:userid"; - string value = role.id + ":" + role_session_name; + string value = role.id + ":" + token_attrs.role_session_name; s->env.emplace(condition, value); - s->env.emplace("aws:TokenIssueTime", token_issued_at); + s->env.emplace("aws:TokenIssueTime", token_attrs.token_issued_at); + + for (auto& m : token_attrs.principal_tags) { + s->env.emplace(m.first, m.second); + } s->token_claims.emplace_back("sts"); s->token_claims.emplace_back("role_name:" + role.tenant + "$" + role.name); - s->token_claims.emplace_back("role_session:" + role_session_name); - for (auto& it : token_claims) { + s->token_claims.emplace_back("role_session:" + token_attrs.role_session_name); + for (auto& it : token_attrs.token_claims) { s->token_claims.emplace_back(it); } } diff --git a/src/rgw/rgw_auth.h b/src/rgw/rgw_auth.h index 1614259815e0..c0df09818f7a 100644 --- a/src/rgw/rgw_auth.h +++ b/src/rgw/rgw_auth.h @@ -702,33 +702,30 @@ public: class RoleApplier : public IdentityApplier { public: struct Role { - string id; - string name; - string tenant; - vector role_policies; - } role; + std::string id; + std::string name; + std::string tenant; + std::vector role_policies; + }; + struct TokenAttrs { + rgw_user user_id; + std::string token_policy; + std::string role_session_name; + std::vector token_claims; + std::string token_issued_at; + std::vector> principal_tags; + }; protected: - const rgw_user user_id; - string token_policy; - string role_session_name; - std::vector token_claims; - string token_issued_at; + Role role; + TokenAttrs token_attrs; public: RoleApplier(CephContext* const cct, const Role& role, - const rgw_user& user_id, - const string& token_policy, - const string& role_session_name, - const std::vector& token_claims, - const string& token_issued_at) + const TokenAttrs& token_attrs) : role(role), - user_id(user_id), - token_policy(token_policy), - role_session_name(role_session_name), - token_claims(token_claims), - token_issued_at(token_issued_at) {} + token_attrs(token_attrs) {} uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override { return 0; @@ -737,7 +734,7 @@ public: return false; } bool is_owner_of(const rgw_user& uid) const override { - return (this->user_id.id == uid.id && this->user_id.tenant == uid.tenant && this->user_id.ns == uid.ns); + return (this->token_attrs.user_id.id == uid.id && this->token_attrs.user_id.tenant == uid.tenant && this->token_attrs.user_id.ns == uid.ns); } bool is_identity(const idset_t& ids) const override; uint32_t get_perm_mask() const override { @@ -756,11 +753,7 @@ public: virtual aplptr_t create_apl_role( CephContext* cct, const req_state* s, const rgw::auth::RoleApplier::Role& role, - const rgw_user& user_id, - const std::string& token_policy, - const std::string& role_session, - const std::vector& token_claims, - const std::string& token_issued_at) const = 0; + const rgw::auth::RoleApplier::TokenAttrs& token_attrs) const = 0; }; }; diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h index cc1dbf90b0e5..0a1390a1eecf 100644 --- a/src/rgw/rgw_auth_s3.h +++ b/src/rgw/rgw_auth_s3.h @@ -66,13 +66,9 @@ class STSAuthStrategy : public rgw::auth::Strategy, aplptr_t create_apl_role(CephContext* const cct, const req_state* const s, const rgw::auth::RoleApplier::Role& role, - const rgw_user& user_id, - const std::string& token_policy, - const std::string& role_session_name, - const std::vector& token_claims, - const std::string& token_issued_at) const override { + const rgw::auth::RoleApplier::TokenAttrs& token_attrs) const override { auto apl = rgw::auth::add_sysreq(cct, ctl, s, - rgw::auth::RoleApplier(cct, role, user_id, token_policy, role_session_name, token_claims, token_issued_at)); + rgw::auth::RoleApplier(cct, role, token_attrs)); return aplptr_t(new decltype(apl)(std::move(apl))); } diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 8945e929fcb0..948ffb81b4d5 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -5921,6 +5921,7 @@ rgw::auth::s3::STSEngine::authenticate( rgw_user user_id; string role_id; rgw::auth::RoleApplier::Role r; + rgw::auth::RoleApplier::TokenAttrs t_attrs; if (! token.roleId.empty()) { RGWRole role(s->cct, ctl, token.roleId); if (role.get_by_id(dpp, y) < 0) { @@ -5937,8 +5938,6 @@ rgw::auth::s3::STSEngine::authenticate( r.role_policies.push_back(std::move(perm_policy)); } } - // This is mostly needed to assign the owner of a bucket during its creation - user_id = token.user; } if (! token.user.empty() && token.acct_type != TYPE_ROLE) { @@ -5955,7 +5954,13 @@ rgw::auth::s3::STSEngine::authenticate( get_creds_info(token)); return result_t::grant(std::move(apl), completer_factory(boost::none)); } else if (token.acct_type == TYPE_ROLE) { - auto apl = role_apl_factory->create_apl_role(cct, s, r, user_id, token.policy, token.role_session, token.token_claims, token.issued_at); + t_attrs.user_id = std::move(token.user); // This is mostly needed to assign the owner of a bucket during its creation + t_attrs.token_policy = std::move(token.policy); + t_attrs.role_session_name = std::move(token.role_session); + t_attrs.token_claims = std::move(token.token_claims); + t_attrs.token_issued_at = std::move(token.issued_at); + t_attrs.principal_tags = std::move(token.principal_tags); + auto apl = role_apl_factory->create_apl_role(cct, s, r, t_attrs); return result_t::grant(std::move(apl), completer_factory(token.secret_access_key)); } else { // This is for all local users of type TYPE_RGW or TYPE_NONE string subuser; diff --git a/src/rgw/rgw_rest_sts.cc b/src/rgw/rgw_rest_sts.cc index e84e7271419a..0d8532e973f9 100644 --- a/src/rgw/rgw_rest_sts.cc +++ b/src/rgw/rgw_rest_sts.cc @@ -595,7 +595,7 @@ void RGWSTSAssumeRoleWithWebIdentity::execute(optional_yield y) } STS::AssumeRoleWithWebIdentityRequest req(s->cct, duration, providerId, policy, roleArn, - roleSessionName, iss, sub, aud); + roleSessionName, iss, sub, aud, s->principal_tags); STS::AssumeRoleWithWebIdentityResponse response = sts.assumeRoleWithWebIdentity(req); op_ret = std::move(response.assumeRoleResp.retCode); diff --git a/src/rgw/rgw_sts.cc b/src/rgw/rgw_sts.cc index bb125cdc60b3..f46d100354f0 100644 --- a/src/rgw/rgw_sts.cc +++ b/src/rgw/rgw_sts.cc @@ -42,10 +42,11 @@ void Credentials::dump(Formatter *f) const int Credentials::generateCredentials(CephContext* cct, const uint64_t& duration, - const boost::optional& policy, - const boost::optional& roleId, - const boost::optional& role_session, - const boost::optional> token_claims, + const boost::optional& policy, + const boost::optional& roleId, + const boost::optional& role_session, + const boost::optional>& token_claims, + const boost::optional>>& session_princ_tags, boost::optional user, rgw::auth::Identity* identity) { @@ -129,6 +130,9 @@ int Credentials::generateCredentials(CephContext* cct, token.role_session = role_session.get(); } + if (session_princ_tags) { + token.principal_tags = std::move(*session_princ_tags); + } buffer::list input, enc_output; encode(token, input); @@ -384,6 +388,7 @@ AssumeRoleWithWebIdentityResponse STSService::assumeRoleWithWebIdentity(AssumeRo req.getPolicy(), roleId, req.getRoleSessionName(), token_claims, + req.getPrincipalTags(), user_id, nullptr); if (response.assumeRoleResp.retCode < 0) { return response; @@ -434,6 +439,7 @@ AssumeRoleResponse STSService::assumeRole(const DoutPrefixProvider *dpp, req.getPolicy(), roleId, req.getRoleSessionName(), boost::none, + boost::none, user_id, nullptr); if (response.retCode < 0) { return response; @@ -473,6 +479,7 @@ GetSessionTokenResponse STSService::getSessionToken(GetSessionTokenRequest& req) boost::none, boost::none, boost::none, + boost::none, user_id, identity); ret < 0) { return make_tuple(ret, cred); diff --git a/src/rgw/rgw_sts.h b/src/rgw/rgw_sts.h index 14c783c1cde0..aca9e24d10dd 100644 --- a/src/rgw/rgw_sts.h +++ b/src/rgw/rgw_sts.h @@ -45,27 +45,30 @@ public: class AssumeRoleWithWebIdentityRequest : public AssumeRoleRequestBase { static constexpr uint64_t MIN_PROVIDER_ID_LEN = 4; static constexpr uint64_t MAX_PROVIDER_ID_LEN = 2048; - string providerId; - string iamPolicy; - string iss; - string sub; - string aud; + std::string providerId; + std::string iamPolicy; + std::string iss; + std::string sub; + std::string aud; + std::vector> session_princ_tags; public: AssumeRoleWithWebIdentityRequest( CephContext* cct, - const string& duration, - const string& providerId, - const string& iamPolicy, - const string& roleArn, - const string& roleSessionName, - const string& iss, - const string& sub, - const string& aud) + const std::string& duration, + const std::string& providerId, + const std::string& iamPolicy, + const std::string& roleArn, + const std::string& roleSessionName, + const std::string& iss, + const std::string& sub, + const std::string& aud, + std::vector> session_princ_tags) : AssumeRoleRequestBase(cct, duration, iamPolicy, roleArn, roleSessionName), - providerId(providerId), iss(iss), sub(sub), aud(aud) {} - const string& getProviderId() const { return providerId; } - const string& getIss() const { return iss; } - const string& getAud() const { return aud; } - const string& getSub() const { return sub; } + providerId(providerId), iss(iss), sub(sub), aud(aud), session_princ_tags(session_princ_tags) {} + const std::string& getProviderId() const { return providerId; } + const std::string& getIss() const { return iss; } + const std::string& getAud() const { return aud; } + const std::string& getSub() const { return sub; } + const std::vector>& getPrincipalTags() const { return session_princ_tags; } int validate_input() const; }; @@ -132,14 +135,15 @@ struct SessionToken { uint32_t perm_mask; bool is_admin; uint32_t acct_type; - string role_session; - std::vector token_claims; - string issued_at; + std::string role_session; + std::vector token_claims; + std::string issued_at; + std::vector> principal_tags; SessionToken() {} void encode(bufferlist& bl) const { - ENCODE_START(4, 1, bl); + ENCODE_START(5, 1, bl); encode(access_key_id, bl); encode(secret_access_key, bl); encode(expiration, bl); @@ -153,11 +157,12 @@ struct SessionToken { encode(role_session, bl); encode(token_claims, bl); encode(issued_at, bl); + encode(principal_tags, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { - DECODE_START(4, bl); + DECODE_START(5, bl); decode(access_key_id, bl); decode(secret_access_key, bl); decode(expiration, bl); @@ -177,6 +182,9 @@ struct SessionToken { if (struct_v >= 4) { decode(issued_at, bl); } + if (struct_v >= 5) { + decode(principal_tags, bl); + } DECODE_FINISH(bl); } }; @@ -192,10 +200,11 @@ class Credentials { public: int generateCredentials(CephContext* cct, const uint64_t& duration, - const boost::optional& policy, - const boost::optional& roleId, - const boost::optional& role_session, - const boost::optional > token_claims, + const boost::optional& policy, + const boost::optional& roleId, + const boost::optional& role_session, + const boost::optional>& token_claims, + const boost::optional>>& session_princ_tags, boost::optional user, rgw::auth::Identity* identity); const string& getAccessKeyId() const { return accessKeyId; }