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 CephContext
* const cct
;
20 using result_t
= rgw::auth::Engine::result_t
;
21 using token_t
= rgw::web_idp::WebTokenClaims
;
23 const rgw::auth::TokenExtractor
* const extractor
;
24 const rgw::auth::WebIdentityApplier::Factory
* const apl_factory
;
26 bool is_applicable(const std::string
& token
) const noexcept
;
28 bool is_client_id_valid(vector
<string
>& client_ids
, const string
& client_id
) const;
30 bool is_cert_valid(const vector
<string
>& thumbprints
, const string
& cert
) const;
32 boost::optional
<RGWOIDCProvider
> get_provider(const DoutPrefixProvider
*dpp
, const string
& role_arn
, const string
& iss
) const;
34 std::string
get_role_tenant(const string
& role_arn
) const;
36 boost::optional
<WebTokenEngine::token_t
>
37 get_from_jwt(const DoutPrefixProvider
* dpp
, const std::string
& token
, const req_state
* const s
, optional_yield y
) const;
39 void validate_signature (const DoutPrefixProvider
* dpp
, const jwt::decoded_jwt
& decoded
, const string
& algorithm
, const string
& iss
, const vector
<string
>& thumbprints
, optional_yield y
) const;
41 result_t
authenticate(const DoutPrefixProvider
* dpp
,
42 const std::string
& token
,
43 const req_state
* s
, optional_yield y
) const;
46 WebTokenEngine(CephContext
* const cct
,
48 const rgw::auth::TokenExtractor
* const extractor
,
49 const rgw::auth::WebIdentityApplier::Factory
* const apl_factory
)
53 apl_factory(apl_factory
) {
56 const char* get_name() const noexcept override
{
57 return "rgw::auth::sts::WebTokenEngine";
60 result_t
authenticate(const DoutPrefixProvider
* dpp
, const req_state
* const s
, optional_yield y
) const override
{
61 return authenticate(dpp
, extractor
->get_token(s
), s
, y
);
63 }; /* class WebTokenEngine */
65 class DefaultStrategy
: public rgw::auth::Strategy
,
66 public rgw::auth::TokenExtractor
,
67 public rgw::auth::WebIdentityApplier::Factory
{
69 ImplicitTenants
& implicit_tenant_context
;
72 const WebTokenEngine web_token_engine
;
74 using aplptr_t
= rgw::auth::IdentityApplier::aplptr_t
;
76 /* The method implements TokenExtractor for Web Token in req_state. */
77 std::string
get_token(const req_state
* const s
) const override
{
78 return s
->info
.args
.get("WebIdentityToken");
81 aplptr_t
create_apl_web_identity( CephContext
* cct
,
83 const string
& role_session
,
84 const string
& role_tenant
,
85 const rgw::web_idp::WebTokenClaims
& token
) const override
{
86 auto apl
= rgw::auth::add_sysreq(cct
, ctl
, s
,
87 rgw::auth::WebIdentityApplier(cct
, ctl
, role_session
, role_tenant
, token
));
88 return aplptr_t(new decltype(apl
)(std::move(apl
)));
92 DefaultStrategy(CephContext
* const cct
,
93 ImplicitTenants
& implicit_tenant_context
,
96 implicit_tenant_context(implicit_tenant_context
),
97 web_token_engine(cct
, ctl
,
98 static_cast<rgw::auth::TokenExtractor
*>(this),
99 static_cast<rgw::auth::WebIdentityApplier::Factory
*>(this)) {
100 /* When the constructor's body is being executed, all member engines
101 * should be initialized. Thus, we can safely add them. */
102 using Control
= rgw::auth::Strategy::Control
;
103 add_engine(Control::SUFFICIENT
, web_token_engine
);
106 const char* get_name() const noexcept override
{
107 return "rgw::auth::sts::DefaultStrategy";
111 } // namespace rgw::auth::sts
113 class RGWREST_STS
: public RGWRESTOp
{
117 RGWREST_STS() = default;
118 int verify_permission(optional_yield y
) override
;
119 void send_response() override
;
122 class RGWSTSAssumeRoleWithWebIdentity
: public RGWREST_STS
{
128 string roleSessionName
;
133 RGWSTSAssumeRoleWithWebIdentity() = default;
134 void execute(optional_yield y
) override
;
136 const char* name() const override
{ return "assume_role_web_identity"; }
137 RGWOpType
get_type() override
{ return RGW_STS_ASSUME_ROLE_WEB_IDENTITY
; }
140 class RGWSTSAssumeRole
: public RGWREST_STS
{
146 string roleSessionName
;
150 RGWSTSAssumeRole() = default;
151 void execute(optional_yield y
) override
;
153 const char* name() const override
{ return "assume_role"; }
154 RGWOpType
get_type() override
{ return RGW_STS_ASSUME_ROLE
; }
157 class RGWSTSGetSessionToken
: public RGWREST_STS
{
163 RGWSTSGetSessionToken() = default;
164 void execute(optional_yield y
) override
;
165 int verify_permission(optional_yield y
) override
;
167 const char* name() const override
{ return "get_session_token"; }
168 RGWOpType
get_type() override
{ return RGW_STS_GET_SESSION_TOKEN
; }
173 static int authorize(const DoutPrefixProvider
*dpp
,
174 rgw::sal::RGWRadosStore
*store
,
175 const rgw::auth::StrategyRegistry
& auth_registry
,
176 struct req_state
*s
, optional_yield y
);
179 class RGWHandler_REST_STS
: public RGWHandler_REST
{
180 const rgw::auth::StrategyRegistry
& auth_registry
;
181 const string
& post_body
;
182 RGWOp
*op_post() override
;
183 void rgw_sts_parse_input();
186 static int init_from_header(struct req_state
*s
, int default_formatter
, bool configurable_format
);
188 RGWHandler_REST_STS(const rgw::auth::StrategyRegistry
& auth_registry
, const string
& post_body
="")
190 auth_registry(auth_registry
),
191 post_body(post_body
) {}
192 ~RGWHandler_REST_STS() override
= default;
194 int init(rgw::sal::RGWRadosStore
*store
,
196 rgw::io::BasicClient
*cio
) override
;
197 int authorize(const DoutPrefixProvider
* dpp
, optional_yield y
) override
;
198 int postauth_init(optional_yield y
) override
{ return 0; }
201 class RGWRESTMgr_STS
: public RGWRESTMgr
{
203 RGWRESTMgr_STS() = default;
204 ~RGWRESTMgr_STS() override
= default;
206 RGWRESTMgr
*get_resource_mgr(struct req_state
* const s
,
207 const std::string
& uri
,
208 std::string
* const out_uri
) override
{
212 RGWHandler_REST
* get_handler(rgw::sal::RGWRadosStore
*store
,
214 const rgw::auth::StrategyRegistry
&,
215 const std::string
&) override
;