From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/rgw/rgw_rest_sts.h | 235 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 src/rgw/rgw_rest_sts.h (limited to 'src/rgw/rgw_rest_sts.h') diff --git a/src/rgw/rgw_rest_sts.h b/src/rgw/rgw_rest_sts.h new file mode 100644 index 000000000..ec15de245 --- /dev/null +++ b/src/rgw/rgw_rest_sts.h @@ -0,0 +1,235 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +#pragma once + +#include "rgw_auth.h" +#include "rgw_auth_filters.h" +#include "rgw_rest.h" +#include "rgw_sts.h" +#include "rgw_web_idp.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#include "jwt-cpp/jwt.h" +#pragma clang diagnostic pop +#pragma GCC diagnostic pop +#include "rgw_oidc_provider.h" + + +namespace rgw::auth::sts { + +class WebTokenEngine : public rgw::auth::Engine { + static constexpr std::string_view princTagsNamespace = "https://aws.amazon.com/tags"; + CephContext* const cct; + rgw::sal::Driver* driver; + + using result_t = rgw::auth::Engine::result_t; + using Pair = std::pair; + using token_t = std::unordered_multimap; + using principal_tags_t = std::set; + + const rgw::auth::TokenExtractor* const extractor; + const rgw::auth::WebIdentityApplier::Factory* const apl_factory; + + bool is_applicable(const std::string& token) const noexcept; + + bool is_client_id_valid(std::vector& client_ids, const std::string& client_id) const; + + bool is_cert_valid(const std::vector& thumbprints, const std::string& cert) const; + + std::unique_ptr get_provider(const DoutPrefixProvider *dpp, const std::string& role_arn, const std::string& iss) const; + + std::string get_role_tenant(const std::string& role_arn) const; + + std::string get_role_name(const string& role_arn) const; + + std::string get_cert_url(const std::string& iss, const DoutPrefixProvider *dpp,optional_yield y) const; + + std::tuple, boost::optional> + get_from_jwt(const DoutPrefixProvider* dpp, const std::string& token, const req_state* const s, optional_yield y) const; + + void validate_signature (const DoutPrefixProvider* dpp, const jwt::decoded_jwt& decoded, const std::string& algorithm, const std::string& iss, const std::vector& thumbprints, optional_yield y) const; + + result_t authenticate(const DoutPrefixProvider* dpp, + const std::string& token, + const req_state* s, optional_yield y) const; + + template + void recurse_and_insert(const string& key, const jwt::claim& c, T& t) const; + WebTokenEngine::token_t get_token_claims(const jwt::decoded_jwt& decoded) const; + +public: + WebTokenEngine(CephContext* const cct, + rgw::sal::Driver* driver, + const rgw::auth::TokenExtractor* const extractor, + const rgw::auth::WebIdentityApplier::Factory* const apl_factory) + : cct(cct), + driver(driver), + extractor(extractor), + apl_factory(apl_factory) { + } + + const char* get_name() const noexcept override { + return "rgw::auth::sts::WebTokenEngine"; + } + + result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const override { + return authenticate(dpp, extractor->get_token(s), s, y); + } +}; /* class WebTokenEngine */ + +class DefaultStrategy : public rgw::auth::Strategy, + public rgw::auth::TokenExtractor, + public rgw::auth::WebIdentityApplier::Factory { + rgw::sal::Driver* driver; + const ImplicitTenants& implicit_tenant_context; + + /* The engine. */ + const WebTokenEngine web_token_engine; + + using aplptr_t = rgw::auth::IdentityApplier::aplptr_t; + + /* The method implements TokenExtractor for Web Token in req_state. */ + std::string get_token(const req_state* const s) const override { + return s->info.args.get("WebIdentityToken"); + } + + aplptr_t create_apl_web_identity( CephContext* cct, + const req_state* s, + const std::string& role_session, + const std::string& role_tenant, + const std::unordered_multimap& token, + boost::optional> role_tags, + boost::optional>> principal_tags) const override { + auto apl = rgw::auth::add_sysreq(cct, driver, s, + rgw::auth::WebIdentityApplier(cct, driver, role_session, role_tenant, token, role_tags, principal_tags)); + return aplptr_t(new decltype(apl)(std::move(apl))); + } + +public: + DefaultStrategy(CephContext* const cct, + const ImplicitTenants& implicit_tenant_context, + rgw::sal::Driver* driver) + : driver(driver), + implicit_tenant_context(implicit_tenant_context), + web_token_engine(cct, driver, + static_cast(this), + static_cast(this)) { + /* When the constructor's body is being executed, all member engines + * should be initialized. Thus, we can safely add them. */ + using Control = rgw::auth::Strategy::Control; + add_engine(Control::SUFFICIENT, web_token_engine); + } + + const char* get_name() const noexcept override { + return "rgw::auth::sts::DefaultStrategy"; + } +}; + +} // namespace rgw::auth::sts + +class RGWREST_STS : public RGWRESTOp { +protected: + STS::STSService sts; +public: + RGWREST_STS() = default; + int verify_permission(optional_yield y) override; + void send_response() override; +}; + +class RGWSTSAssumeRoleWithWebIdentity : public RGWREST_STS { +protected: + std::string duration; + std::string providerId; + std::string policy; + std::string roleArn; + std::string roleSessionName; + std::string sub; + std::string aud; + std::string iss; +public: + RGWSTSAssumeRoleWithWebIdentity() = default; + void execute(optional_yield y) override; + int get_params(); + const char* name() const override { return "assume_role_web_identity"; } + RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE_WEB_IDENTITY; } +}; + +class RGWSTSAssumeRole : public RGWREST_STS { +protected: + std::string duration; + std::string externalId; + std::string policy; + std::string roleArn; + std::string roleSessionName; + std::string serialNumber; + std::string tokenCode; +public: + RGWSTSAssumeRole() = default; + void execute(optional_yield y) override; + int get_params(); + const char* name() const override { return "assume_role"; } + RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE; } +}; + +class RGWSTSGetSessionToken : public RGWREST_STS { +protected: + std::string duration; + std::string serialNumber; + std::string tokenCode; +public: + RGWSTSGetSessionToken() = default; + void execute(optional_yield y) override; + int verify_permission(optional_yield y) override; + int get_params(); + const char* name() const override { return "get_session_token"; } + RGWOpType get_type() override { return RGW_STS_GET_SESSION_TOKEN; } +}; + +class RGW_Auth_STS { +public: + static int authorize(const DoutPrefixProvider *dpp, + rgw::sal::Driver* driver, + const rgw::auth::StrategyRegistry& auth_registry, + req_state *s, optional_yield y); +}; + +class RGWHandler_REST_STS : public RGWHandler_REST { + const rgw::auth::StrategyRegistry& auth_registry; + RGWOp *op_post() override; +public: + + static bool action_exists(const req_state* s); + + RGWHandler_REST_STS(const rgw::auth::StrategyRegistry& auth_registry) + : RGWHandler_REST(), + auth_registry(auth_registry) {} + ~RGWHandler_REST_STS() override = default; + + int init(rgw::sal::Driver* driver, + req_state *s, + rgw::io::BasicClient *cio) override; + int authorize(const DoutPrefixProvider* dpp, optional_yield y) override; + int postauth_init(optional_yield y) override { return 0; } +}; + +class RGWRESTMgr_STS : public RGWRESTMgr { +public: + RGWRESTMgr_STS() = default; + ~RGWRESTMgr_STS() override = default; + + RGWRESTMgr *get_resource_mgr(req_state* const s, + const std::string& uri, + std::string* const out_uri) override { + return this; + } + + RGWHandler_REST* get_handler(rgw::sal::Driver* driver, + req_state*, + const rgw::auth::StrategyRegistry&, + const std::string&) override; +}; + -- cgit v1.2.3