OPTION(rgw_sts_entry, OPT_STR)
OPTION(rgw_sts_key, OPT_STR)
OPTION(rgw_s3_auth_use_sts, OPT_BOOL) // should we try to use sts for s3?
+OPTION(rgw_sts_max_session_duration, OPT_U64) // Max duration in seconds for which the session token is valid.
.set_default(false)
.set_description("Should S3 authentication use STS."),
+ Option("rgw_sts_max_session_duration", Option::TYPE_UINT, Option::LEVEL_ADVANCED)
+ .set_default("43200")
+ .set_description("Session token max duration")
+ .set_long_description("Max duration in seconds for which the session token is valid."),
});
}
TokenEngine::authenticate(const std::string& token,
const req_state* const s) const
{
+ //If Keystone is enabled and the request has a session token, then keystone shouldn't authenticate it.
+ if (s->info.args.exists("X-Amz-Security-Token") ||
+ s->info.env->exists("HTTP_X_AMZ_SECURITY_TOKEN")) {
+ return result_t::deny();
+ }
+
boost::optional<TokenEngine::token_envelope_t> t;
/* This will be initialized on the first call to this method. In C++11 it's
RGW_OP_DEL_BUCKET_META_SEARCH,
/* sts specific*/
RGW_STS_ASSUME_ROLE,
+ RGW_STS_GET_SESSION_TOKEN,
};
class RGWAccessControlPolicy;
end_header(s);
}
+int RGWSTSGetSessionToken::verify_permission()
+{
+ return 0;
+}
+
+int RGWSTSGetSessionToken::get_params()
+{
+ duration = s->info.args.get("DurationSeconds");
+ serialNumber = s->info.args.get("SerialNumber");
+ tokenCode = s->info.args.get("TokenCode");
+
+ if (! duration.empty()) {
+ uint64_t duration_in_secs = stoull(duration);
+ if (duration_in_secs < STS::GetSessionTokenRequest::getMinDuration() ||
+ duration_in_secs > s->cct->_conf->rgw_sts_max_session_duration)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void RGWSTSGetSessionToken::execute()
+{
+ if (op_ret = get_params(); op_ret < 0) {
+ return;
+ }
+
+ STS::STSService sts(s->cct, store, s->user->user_id);
+
+ STS::GetSessionTokenRequest req(duration, serialNumber, tokenCode);
+ const auto& [ret, creds] = sts.getSessionToken(req);
+ op_ret = std::move(ret);
+ //Dump the output
+ if (op_ret == 0) {
+ s->formatter->open_object_section("Credentials");
+ creds.dump(s->formatter);
+ s->formatter->close_section();
+ }
+}
+
int RGWSTSAssumeRole::get_params()
{
duration = s->info.args.get("DurationSeconds");
RGWOp *RGWHandler_REST_STS::op_post()
{
if (s->info.args.exists("Action")) {
- if (string action = s->info.args.get("Action"); action == "AssumeRole") {
+ string action = s->info.args.get("Action");
+ if (action == "AssumeRole") {
return new RGWSTSAssumeRole;
+ } else if (action == "GetSessionToken") {
+ return new RGWSTSGetSessionToken;
}
}
return nullptr;
RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE; }
};
+class RGWSTSGetSessionToken : public RGWREST_STS {
+protected:
+ string duration;
+ string serialNumber;
+ string tokenCode;
+public:
+ RGWSTSGetSessionToken() = default;
+ void execute() override;
+ int verify_permission() override;
+ int get_params();
+ const char* name() const override { return "get_keystone_session_token"; }
+ RGWOpType get_type() override { return RGW_STS_GET_SESSION_TOKEN; }
+};
+
class RGWHandler_REST_STS : public RGWHandler_REST {
const rgw::auth::StrategyRegistry& auth_registry;
RGWOp *op_post() override;
token.acct_type = TYPE_NONE;
}
- string encrypted_str;
buffer::list input, enc_output;
encode(token, input);
return make_tuple(0, user, cred, packedPolicySize);
}
+GetSessionTokenRequest::GetSessionTokenRequest(string& duration, string& serialNumber, string& tokenCode)
+{
+ if (duration.empty()) {
+ this->duration = DEFAULT_DURATION_IN_SECS;
+ } else {
+ this->duration = stoull(duration);
+ }
+ this->serialNumber = serialNumber;
+ this->tokenCode = tokenCode;
+}
+
+GetSessionTokenResponse STSService::getSessionToken(GetSessionTokenRequest& req)
+{
+ int ret;
+ Credentials cred;
+
+ //Generate Credentials
+ if (ret = cred.generateCredentials(cct,
+ req.getDuration(),
+ boost::none,
+ boost::none); ret < 0) {
+ return make_tuple(ret, cred);
+ }
+
+ return make_tuple(0, cred);
+}
+
}
\ No newline at end of file
int validate_input() const;
};
+class GetSessionTokenRequest {
+protected:
+ static constexpr uint64_t MIN_DURATION_IN_SECS = 900;
+ static constexpr uint64_t DEFAULT_DURATION_IN_SECS = 3600;
+ uint64_t duration;
+ string serialNumber;
+ string tokenCode;
+
+public:
+ GetSessionTokenRequest(string& duration, string& serialNumber, string& tokenCode);
+
+ const uint64_t& getDuration() const { return duration; }
+ static const uint64_t& getMinDuration() { return MIN_DURATION_IN_SECS; }
+};
class AssumedRoleUser {
string arn;
//AssumedRoleUser, Credentials, PackedpolicySize
using AssumeRoleResponse = std::tuple<int, AssumedRoleUser, Credentials, uint64_t> ;
+using GetSessionTokenResponse = std::tuple<int, Credentials>;
class STSService {
CephContext* cct;
STSService(CephContext* cct, RGWRados *store, rgw_user user_id, rgw::auth::Identity* identity) : cct(cct), store(store), user_id(user_id), identity(identity) {}
std::tuple<int, RGWRole> getRoleInfo(const string& arn);
AssumeRoleResponse assumeRole(AssumeRoleRequest& req);
+ GetSessionTokenResponse getSessionToken(GetSessionTokenRequest& req);
};
}
#endif /* CEPH_RGW_STS_H */