// vim: ts=8 sw=2 smarttab ft=cpp
#include <array>
+#include <string>
#include "rgw_common.h"
#include "rgw_auth.h"
string idp_url = get_idp_url();
string condition = idp_url + ":app_id";
- if (! token_claims.client_id.empty()) {
- s->env.emplace(condition, token_claims.client_id);
- } else {
- s->env.emplace(condition, token_claims.aud);
- }
+
+ s->env.emplace(condition, token_claims.aud);
+
+ condition.clear();
+ condition = idp_url + ":sub";
+ s->env.emplace(condition, token_claims.sub);
}
bool rgw::auth::WebIdentityApplier::is_identity(const idset_t& ids) const
}
void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
- out << "rgw::auth::LocalApplier(role name =" << role_name;
- for (auto policy : role_policies) {
+ out << "rgw::auth::LocalApplier(role name =" << role.name;
+ for (auto& policy: role.role_policies) {
out << ", role policy =" << policy;
}
+ out << ", token policy =" << token_policy;
out << ")";
}
bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const {
for (auto& p : ids) {
- string name;
- string tenant = p.get_tenant();
- if (tenant.empty()) {
- name = p.get_id();
- } else {
- name = tenant + "$" + p.get_id();
- }
if (p.is_wildcard()) {
return true;
- } else if (p.is_role() && name == role_name) {
- return true;
+ } else if (p.is_role()) {
+ string name = p.get_id();
+ string tenant = p.get_tenant();
+ if (name == role.name && tenant == role.tenant) {
+ return true;
+ }
+ } else if (p.is_assumed_role()) {
+ string tenant = p.get_tenant();
+ string role_session = role.name + "/" + role_session_name; //role/role-session
+ if (role.tenant == tenant && role_session == p.get_role_session()) {
+ return true;
+ }
+ } else {
+ string id = p.get_id();
+ if (user_id.id == id) {
+ return true;
+ }
}
}
return false;
{
/* Load the user id */
user_info.user_id = this->user_id;
+
+ user_info.user_id.tenant = role.tenant;
}
void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
{
- for (auto it : role_policies) {
+ for (auto it: role.role_policies) {
try {
bufferlist bl = bufferlist::static_from_string(it);
- const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
+ const rgw::IAM::Policy p(s->cct, role.tenant, bl);
s->iam_user_policies.push_back(std::move(p));
} catch (rgw::IAM::PolicyParseException& e) {
//Control shouldn't reach here as the policy has already been
//verified earlier
- ldpp_dout(dpp, 20) << "failed to parse policy: " << e.what() << dendl;
+ ldpp_dout(dpp, 20) << "failed to parse role policy: " << e.what() << dendl;
}
}
+
+ try {
+ string policy = this->token_policy;
+ bufferlist bl = bufferlist::static_from_string(policy);
+ const rgw::IAM::Policy p(s->cct, role.tenant, bl);
+ s->iam_user_policies.push_back(std::move(p));
+ } catch (rgw::IAM::PolicyParseException& e) {
+ //Control shouldn't reach here as the policy has already been
+ //verified earlier
+ ldpp_dout(dpp, 20) << "failed to parse token policy: " << e.what() << dendl;
+ }
+
+ string condition = "aws:userid";
+ string value = role.id + ":" + role_session_name;
+ s->env.emplace(condition, value);
}
rgw::auth::Engine::result_t
protected:
CephContext* const cct;
RGWCtl* const ctl;
+ string role_session;
rgw::web_idp::WebTokenClaims token_claims;
string get_idp_url() const;
public:
WebIdentityApplier( CephContext* const cct,
RGWCtl* const ctl,
+ const string& role_session,
const rgw::web_idp::WebTokenClaims& token_claims)
: cct(cct),
ctl(ctl),
+ role_session(role_session),
token_claims(token_claims) {
}
virtual aplptr_t create_apl_web_identity( CephContext* cct,
const req_state* s,
+ const string& role_session,
const rgw::web_idp::WebTokenClaims& token) const = 0;
};
};
};
class RoleApplier : public IdentityApplier {
+public:
+ struct Role {
+ string id;
+ string name;
+ string tenant;
+ vector<string> role_policies;
+ } role;
protected:
- const string role_name;
const rgw_user user_id;
- vector<std::string> role_policies;
+ string token_policy;
+ string role_session_name;
public:
RoleApplier(CephContext* const cct,
- const string& role_name,
+ const Role& role,
const rgw_user& user_id,
- const vector<std::string>& role_policies)
- : role_name(role_name),
+ const string& token_policy,
+ const string& role_session_name)
+ : role(role),
user_id(user_id),
- role_policies(role_policies) {}
+ token_policy(token_policy),
+ role_session_name(role_session_name) {}
uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
return 0;
virtual ~Factory() {}
virtual aplptr_t create_apl_role( CephContext* cct,
const req_state* s,
- const string& role_name,
+ const rgw::auth::RoleApplier::Role& role_name,
const rgw_user& user_id,
- const vector<std::string>& role_policies) const = 0;
+ const std::string& token_policy,
+ const std::string& role_session) const = 0;
};
};
aplptr_t create_apl_role(CephContext* const cct,
const req_state* const s,
- const string& role_name,
+ const rgw::auth::RoleApplier::Role& role,
const rgw_user& user_id,
- const vector<std::string>& role_policies) const override {
+ const std::string& token_policy,
+ const std::string& role_session_name) const override {
auto apl = rgw::auth::add_sysreq(cct, ctl, s,
- rgw::auth::RoleApplier(cct, role_name, user_id, role_policies));
+ rgw::auth::RoleApplier(cct, role, user_id, token_policy, role_session_name));
return aplptr_t(new decltype(apl)(std::move(apl)));
}
namespace rgw {
namespace auth {
class Principal {
- enum types { User, Role, Tenant, Wildcard, OidcProvider };
+ enum types { User, Role, Tenant, Wildcard, OidcProvider, AssumedRole };
types t;
rgw_user u;
std::string idp_url;
return Principal(std::move(idp_url));
}
+ static Principal assumed_role(std::string&& t, std::string&& u) {
+ return Principal(AssumedRole, std::move(t), std::move(u));
+ }
+
bool is_wildcard() const {
return t == Wildcard;
}
return t == OidcProvider;
}
+ bool is_assumed_role() const {
+ return t == AssumedRole;
+ }
+
const std::string& get_tenant() const {
return u.tenant;
}
return idp_url;
}
+ const string& get_role_session() const {
+ return u.id;
+ }
+
+ const string& get_role() const {
+ return u.id;
+ }
+
bool operator ==(const Principal& o) const {
return (t == o.t) && (u == o.u);
}
if (match[1] == "oidc-provider") {
return Principal::oidc_provider(std::move(match[2]));
}
+ if (match[1] == "assumed-role") {
+ return Principal::assumed_role(std::move(a->account), match[2]);
+ }
}
} else {
if (std::none_of(s.begin(), s.end(),
// Get all the authorization info
RGWUserInfo user_info;
rgw_user user_id;
- vector<string> role_policies;
- string role_name;
+ string role_id;
+ rgw::auth::RoleApplier::Role r;
if (! token.roleId.empty()) {
RGWRole role(s->cct, ctl, token.roleId);
if (role.get_by_id() < 0) {
return result_t::deny(-EPERM);
}
+ r.id = token.roleId;
+ r.name = role.get_name();
+ r.tenant = role.get_tenant();
+
vector<string> role_policy_names = role.get_role_policy_names();
for (auto& policy_name : role_policy_names) {
string perm_policy;
if (int ret = role.get_role_policy(policy_name, perm_policy); ret == 0) {
- role_policies.push_back(std::move(perm_policy));
+ r.role_policies.push_back(std::move(perm_policy));
}
}
- if (! token.policy.empty()) {
- role_policies.push_back(std::move(token.policy));
- }
// This is mostly needed to assign the owner of a bucket during its creation
user_id = token.user;
- role_name = role.get_name();
}
if (! token.user.empty() && token.acct_type != TYPE_ROLE) {
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, role_name, user_id, role_policies);
+ auto apl = role_apl_factory->create_apl_role(cct, s, r, user_id, token.policy, token.role_session);
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;
}
if (t) {
- auto apl = apl_factory->create_apl_web_identity(cct, s, *t);
+ string role_session = s->info.args.get("RoleSessionName");
+ if (role_session.empty()) {
+ return result_t::deny(-EACCES);
+ }
+ auto apl = apl_factory->create_apl_web_identity(cct, s, role_session, *t);
return result_t::grant(std::move(apl));
}
return result_t::deny(-EACCES);
aplptr_t create_apl_web_identity( CephContext* cct,
const req_state* s,
+ const string& role_session,
const rgw::web_idp::WebTokenClaims& token) const override {
auto apl = rgw::auth::add_sysreq(cct, ctl, s,
- rgw::auth::WebIdentityApplier(cct, ctl, token));
+ rgw::auth::WebIdentityApplier(cct, ctl, role_session, token));
return aplptr_t(new decltype(apl)(std::move(apl)));
}
int read_id(const string& role_name, const string& tenant, string& role_id);
int read_name();
int read_info();
- void set_id(const string& id) { this->id = id; }
bool validate_input();
void extract_name_tenant(const std::string& str);
const string& get_id() const { return id; }
const string& get_name() const { return name; }
+ const string& get_tenant() const { return tenant; }
const string& get_path() const { return path; }
const string& get_create_date() const { return creation_date; }
const string& get_assume_role_policy() const { return trust_policy;}
const uint64_t& get_max_session_duration() const { return max_session_duration; }
+ void set_id(const string& id) { this->id = id; }
+
int create(bool exclusive);
int delete_obj();
int get();
const uint64_t& duration,
const boost::optional<string>& policy,
const boost::optional<string>& roleId,
+ const boost::optional<string>& role_session,
boost::optional<rgw_user> user,
rgw::auth::Identity* identity)
{
token.perm_mask = 0;
token.is_admin = 0;
token.acct_type = TYPE_ROLE;
+ token.role_session = role_session.get();
}
buffer::list input, enc_output;
//Role and Policy provide the authorization info, user id and applier info are not needed
response.assumeRoleResp.retCode = response.assumeRoleResp.creds.generateCredentials(cct, req.getDuration(),
req.getPolicy(), roleId,
+ req.getRoleSessionName(),
user_id, nullptr);
if (response.assumeRoleResp.retCode < 0) {
return response;
//Role and Policy provide the authorization info, user id and applier info are not needed
response.retCode = response.creds.generateCredentials(cct, req.getDuration(),
req.getPolicy(), roleId,
+ req.getRoleSessionName(),
user_id, nullptr);
if (response.retCode < 0) {
return response;
req.getDuration(),
boost::none,
boost::none,
+ boost::none,
user_id,
identity); ret < 0) {
return make_tuple(ret, cred);
uint32_t perm_mask;
bool is_admin;
uint32_t acct_type;
+ string role_session;
SessionToken() {}
void encode(bufferlist& bl) const {
- ENCODE_START(1, 1, bl);
+ ENCODE_START(2, 1, bl);
encode(access_key_id, bl);
encode(secret_access_key, bl);
encode(expiration, bl);
encode(perm_mask, bl);
encode(is_admin, bl);
encode(acct_type, bl);
+ encode(role_session, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
- DECODE_START(1, bl);
+ DECODE_START(2, bl);
decode(access_key_id, bl);
decode(secret_access_key, bl);
decode(expiration, bl);
decode(perm_mask, bl);
decode(is_admin, bl);
decode(acct_type, bl);
+ if (struct_v >= 2) {
+ decode(role_session, bl);
+ }
DECODE_FINISH(bl);
}
};
const uint64_t& duration,
const boost::optional<string>& policy,
const boost::optional<string>& roleId,
+ const boost::optional<string>& role_session,
boost::optional<rgw_user> user,
rgw::auth::Identity* identity);
const string& getAccessKeyId() const { return accessKeyId; }