From 6b2d3da84c0960260d06433906deda218a2cc43e Mon Sep 17 00:00:00 2001 From: Pritha Srivastava Date: Wed, 10 Mar 2021 12:24:49 +0530 Subject: [PATCH] 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 --- src/rgw/rgw_auth.cc | 32 ++++++++++++++++++-------------- src/rgw/rgw_auth.h | 37 +++++++++++++++---------------------- src/rgw/rgw_auth_s3.h | 8 ++------ src/rgw/rgw_rest_s3.cc | 11 ++++++++--- src/rgw/rgw_rest_sts.cc | 2 +- src/rgw/rgw_sts.cc | 15 +++++++++++---- src/rgw/rgw_sts.h | 19 ++++++++++++++----- 7 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/rgw/rgw_auth.cc b/src/rgw/rgw_auth.cc index b7d48d603f7ee..af23c23d71c9c 100644 --- a/src/rgw/rgw_auth.cc +++ b/src/rgw/rgw_auth.cc @@ -785,11 +785,11 @@ void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWU } 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 << ")"; } @@ -805,7 +805,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; } @@ -813,12 +813,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; } } @@ -829,7 +829,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 @@ -846,9 +846,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)); @@ -860,15 +860,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 fc84a79b5bbe3..82403fad8d4ab 100644 --- a/src/rgw/rgw_auth.h +++ b/src/rgw/rgw_auth.h @@ -686,29 +686,26 @@ public: std::string name; std::string tenant; std::vector role_policies; - } role; + }; + 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; - std::string token_policy; - std::string role_session_name; - std::vector token_claims; - std::string token_issued_at; + Role role; + TokenAttrs token_attrs; public: RoleApplier(CephContext* const cct, const 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 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; @@ -717,7 +714,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 { @@ -736,11 +733,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 5de9e46a5ac13..5ad1516f369a1 100644 --- a/src/rgw/rgw_auth_s3.h +++ b/src/rgw/rgw_auth_s3.h @@ -65,13 +65,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, store, 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 7a8fb8f45b1b7..b7ee647e727d6 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -6084,6 +6084,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()) { std::unique_ptr role = store->get_role(token.roleId); if (role->get_by_id(dpp, y) < 0) { @@ -6100,8 +6101,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; } user = store->get_user(token.user); @@ -6119,7 +6118,13 @@ rgw::auth::s3::STSEngine::authenticate( get_creds_info(token)); return result_t::grant(std::move(apl), completer_factory(token.secret_access_key)); } 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 44810d7126568..388fffd6ab4cd 100644 --- a/src/rgw/rgw_rest_sts.cc +++ b/src/rgw/rgw_rest_sts.cc @@ -637,7 +637,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 6cccaf03265f1..edfb2ae39c012 100644 --- a/src/rgw/rgw_sts.cc +++ b/src/rgw/rgw_sts.cc @@ -44,10 +44,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) { @@ -131,6 +132,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); @@ -385,6 +389,7 @@ AssumeRoleWithWebIdentityResponse STSService::assumeRoleWithWebIdentity(AssumeRo req.getPolicy(), roleId, req.getRoleSessionName(), token_claims, + req.getPrincipalTags(), user_id, nullptr); if (response.assumeRoleResp.retCode < 0) { return response; @@ -435,6 +440,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; @@ -474,6 +480,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 6be5633488af5..d67cd49975415 100644 --- a/src/rgw/rgw_sts.h +++ b/src/rgw/rgw_sts.h @@ -50,6 +50,7 @@ class AssumeRoleWithWebIdentityRequest : public AssumeRoleRequestBase { std::string iss; std::string sub; std::string aud; + std::vector> session_princ_tags; public: AssumeRoleWithWebIdentityRequest( CephContext* cct, const std::string& duration, @@ -59,13 +60,15 @@ public: const std::string& roleSessionName, const std::string& iss, const std::string& sub, - const std::string& aud) + const std::string& aud, + std::vector> session_princ_tags) : AssumeRoleRequestBase(cct, duration, iamPolicy, roleArn, roleSessionName), - providerId(providerId), iss(iss), sub(sub), aud(aud) {} + 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; }; @@ -135,11 +138,12 @@ struct SessionToken { 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); } }; @@ -195,7 +203,8 @@ public: const boost::optional& policy, const boost::optional& roleId, const boost::optional& role_session, - const boost::optional > token_claims, + const boost::optional>& token_claims, + const boost::optional>>& session_princ_tags, boost::optional user, rgw::auth::Identity* identity); const std::string& getAccessKeyId() const { return accessKeyId; } -- 2.39.5