1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
7 #include "rgw_auth_filters.h"
10 #include "rgw_web_idp.h"
11 #include "jwt-cpp/jwt.h"
12 #include "rgw_oidc_provider.h"
14 namespace rgw::auth::sts
{
16 class WebTokenEngine
: public rgw::auth::Engine
{
17 static constexpr std::string_view princTagsNamespace
= "https://aws.amazon.com/tags";
18 CephContext
* const cct
;
19 rgw::sal::Store
* store
;
21 using result_t
= rgw::auth::Engine::result_t
;
22 using Pair
= std::pair
<std::string
, std::string
>;
23 using token_t
= std::unordered_multimap
<string
, string
>;
24 using principal_tags_t
= std::set
<Pair
>;
26 const rgw::auth::TokenExtractor
* const extractor
;
27 const rgw::auth::WebIdentityApplier::Factory
* const apl_factory
;
29 bool is_applicable(const std::string
& token
) const noexcept
;
31 bool is_client_id_valid(std::vector
<std::string
>& client_ids
, const std::string
& client_id
) const;
33 bool is_cert_valid(const std::vector
<std::string
>& thumbprints
, const std::string
& cert
) const;
35 std::unique_ptr
<rgw::sal::RGWOIDCProvider
> get_provider(const DoutPrefixProvider
*dpp
, const std::string
& role_arn
, const std::string
& iss
) const;
37 std::string
get_role_tenant(const std::string
& role_arn
) const;
39 std::string
get_role_name(const string
& role_arn
) const;
41 std::string
get_cert_url(const std::string
& iss
, const DoutPrefixProvider
*dpp
,optional_yield y
) const;
43 std::tuple
<boost::optional
<WebTokenEngine::token_t
>, boost::optional
<WebTokenEngine::principal_tags_t
>>
44 get_from_jwt(const DoutPrefixProvider
* dpp
, const std::string
& token
, const req_state
* const s
, optional_yield y
) const;
46 void validate_signature (const DoutPrefixProvider
* dpp
, const jwt::decoded_jwt
& decoded
, const std::string
& algorithm
, const std::string
& iss
, const std::vector
<std::string
>& thumbprints
, optional_yield y
) const;
48 result_t
authenticate(const DoutPrefixProvider
* dpp
,
49 const std::string
& token
,
50 const req_state
* s
, optional_yield y
) const;
53 void recurse_and_insert(const string
& key
, const jwt::claim
& c
, T
& t
) const;
54 WebTokenEngine::token_t
get_token_claims(const jwt::decoded_jwt
& decoded
) const;
57 WebTokenEngine(CephContext
* const cct
,
58 rgw::sal::Store
* store
,
59 const rgw::auth::TokenExtractor
* const extractor
,
60 const rgw::auth::WebIdentityApplier::Factory
* const apl_factory
)
64 apl_factory(apl_factory
) {
67 const char* get_name() const noexcept override
{
68 return "rgw::auth::sts::WebTokenEngine";
71 result_t
authenticate(const DoutPrefixProvider
* dpp
, const req_state
* const s
, optional_yield y
) const override
{
72 return authenticate(dpp
, extractor
->get_token(s
), s
, y
);
74 }; /* class WebTokenEngine */
76 class DefaultStrategy
: public rgw::auth::Strategy
,
77 public rgw::auth::TokenExtractor
,
78 public rgw::auth::WebIdentityApplier::Factory
{
79 rgw::sal::Store
* store
;
80 ImplicitTenants
& implicit_tenant_context
;
83 const WebTokenEngine web_token_engine
;
85 using aplptr_t
= rgw::auth::IdentityApplier::aplptr_t
;
87 /* The method implements TokenExtractor for Web Token in req_state. */
88 std::string
get_token(const req_state
* const s
) const override
{
89 return s
->info
.args
.get("WebIdentityToken");
92 aplptr_t
create_apl_web_identity( CephContext
* cct
,
94 const std::string
& role_session
,
95 const std::string
& role_tenant
,
96 const std::unordered_multimap
<std::string
, std::string
>& token
,
97 boost::optional
<std::multimap
<std::string
, std::string
>> role_tags
,
98 boost::optional
<std::set
<std::pair
<std::string
, std::string
>>> principal_tags
) const override
{
99 auto apl
= rgw::auth::add_sysreq(cct
, store
, s
,
100 rgw::auth::WebIdentityApplier(cct
, store
, role_session
, role_tenant
, token
, role_tags
, principal_tags
));
101 return aplptr_t(new decltype(apl
)(std::move(apl
)));
105 DefaultStrategy(CephContext
* const cct
,
106 ImplicitTenants
& implicit_tenant_context
,
107 rgw::sal::Store
* store
)
109 implicit_tenant_context(implicit_tenant_context
),
110 web_token_engine(cct
, store
,
111 static_cast<rgw::auth::TokenExtractor
*>(this),
112 static_cast<rgw::auth::WebIdentityApplier::Factory
*>(this)) {
113 /* When the constructor's body is being executed, all member engines
114 * should be initialized. Thus, we can safely add them. */
115 using Control
= rgw::auth::Strategy::Control
;
116 add_engine(Control::SUFFICIENT
, web_token_engine
);
119 const char* get_name() const noexcept override
{
120 return "rgw::auth::sts::DefaultStrategy";
124 } // namespace rgw::auth::sts
126 class RGWREST_STS
: public RGWRESTOp
{
130 RGWREST_STS() = default;
131 int verify_permission(optional_yield y
) override
;
132 void send_response() override
;
135 class RGWSTSAssumeRoleWithWebIdentity
: public RGWREST_STS
{
137 std::string duration
;
138 std::string providerId
;
141 std::string roleSessionName
;
146 RGWSTSAssumeRoleWithWebIdentity() = default;
147 void execute(optional_yield y
) override
;
149 const char* name() const override
{ return "assume_role_web_identity"; }
150 RGWOpType
get_type() override
{ return RGW_STS_ASSUME_ROLE_WEB_IDENTITY
; }
153 class RGWSTSAssumeRole
: public RGWREST_STS
{
155 std::string duration
;
156 std::string externalId
;
159 std::string roleSessionName
;
160 std::string serialNumber
;
161 std::string tokenCode
;
163 RGWSTSAssumeRole() = default;
164 void execute(optional_yield y
) override
;
166 const char* name() const override
{ return "assume_role"; }
167 RGWOpType
get_type() override
{ return RGW_STS_ASSUME_ROLE
; }
170 class RGWSTSGetSessionToken
: public RGWREST_STS
{
172 std::string duration
;
173 std::string serialNumber
;
174 std::string tokenCode
;
176 RGWSTSGetSessionToken() = default;
177 void execute(optional_yield y
) override
;
178 int verify_permission(optional_yield y
) override
;
180 const char* name() const override
{ return "get_session_token"; }
181 RGWOpType
get_type() override
{ return RGW_STS_GET_SESSION_TOKEN
; }
186 static int authorize(const DoutPrefixProvider
*dpp
,
187 rgw::sal::Store
* store
,
188 const rgw::auth::StrategyRegistry
& auth_registry
,
189 struct req_state
*s
, optional_yield y
);
192 class RGWHandler_REST_STS
: public RGWHandler_REST
{
193 const rgw::auth::StrategyRegistry
& auth_registry
;
194 const std::string
& post_body
;
195 RGWOp
*op_post() override
;
196 void rgw_sts_parse_input();
199 static int init_from_header(struct req_state
*s
, int default_formatter
, bool configurable_format
);
201 RGWHandler_REST_STS(const rgw::auth::StrategyRegistry
& auth_registry
, const std::string
& post_body
="")
203 auth_registry(auth_registry
),
204 post_body(post_body
) {}
205 ~RGWHandler_REST_STS() override
= default;
207 int init(rgw::sal::Store
* store
,
209 rgw::io::BasicClient
*cio
) override
;
210 int authorize(const DoutPrefixProvider
* dpp
, optional_yield y
) override
;
211 int postauth_init(optional_yield y
) override
{ return 0; }
214 class RGWRESTMgr_STS
: public RGWRESTMgr
{
216 RGWRESTMgr_STS() = default;
217 ~RGWRESTMgr_STS() override
= default;
219 RGWRESTMgr
*get_resource_mgr(struct req_state
* const s
,
220 const std::string
& uri
,
221 std::string
* const out_uri
) override
{
225 RGWHandler_REST
* get_handler(rgw::sal::Store
* store
,
227 const rgw::auth::StrategyRegistry
&,
228 const std::string
&) override
;