]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
11fdf7f2 | 3 | |
9f95a23c | 4 | #pragma once |
11fdf7f2 TL |
5 | |
6 | #include "rgw_auth.h" | |
7 | #include "rgw_auth_filters.h" | |
f67539c2 | 8 | #include "rgw_rest.h" |
11fdf7f2 TL |
9 | #include "rgw_sts.h" |
10 | #include "rgw_web_idp.h" | |
2a845540 TL |
11 | #pragma GCC diagnostic push |
12 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
13 | ||
14 | #pragma clang diagnostic push | |
15 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
f91f0fd5 | 16 | #include "jwt-cpp/jwt.h" |
2a845540 TL |
17 | #pragma clang diagnostic pop |
18 | #pragma GCC diagnostic pop | |
f91f0fd5 | 19 | #include "rgw_oidc_provider.h" |
11fdf7f2 | 20 | |
2a845540 | 21 | |
9f95a23c | 22 | namespace rgw::auth::sts { |
11fdf7f2 TL |
23 | |
24 | class WebTokenEngine : public rgw::auth::Engine { | |
20effc67 | 25 | static constexpr std::string_view princTagsNamespace = "https://aws.amazon.com/tags"; |
11fdf7f2 | 26 | CephContext* const cct; |
1e59de90 | 27 | rgw::sal::Driver* driver; |
11fdf7f2 TL |
28 | |
29 | using result_t = rgw::auth::Engine::result_t; | |
20effc67 TL |
30 | using Pair = std::pair<std::string, std::string>; |
31 | using token_t = std::unordered_multimap<string, string>; | |
32 | using principal_tags_t = std::set<Pair>; | |
11fdf7f2 TL |
33 | |
34 | const rgw::auth::TokenExtractor* const extractor; | |
35 | const rgw::auth::WebIdentityApplier::Factory* const apl_factory; | |
36 | ||
37 | bool is_applicable(const std::string& token) const noexcept; | |
38 | ||
20effc67 | 39 | bool is_client_id_valid(std::vector<std::string>& client_ids, const std::string& client_id) const; |
f91f0fd5 | 40 | |
20effc67 | 41 | bool is_cert_valid(const std::vector<std::string>& thumbprints, const std::string& cert) const; |
f91f0fd5 | 42 | |
20effc67 | 43 | std::unique_ptr<rgw::sal::RGWOIDCProvider> get_provider(const DoutPrefixProvider *dpp, const std::string& role_arn, const std::string& iss) const; |
f91f0fd5 | 44 | |
20effc67 | 45 | std::string get_role_tenant(const std::string& role_arn) const; |
f67539c2 | 46 | |
20effc67 TL |
47 | std::string get_role_name(const string& role_arn) const; |
48 | ||
49 | std::string get_cert_url(const std::string& iss, const DoutPrefixProvider *dpp,optional_yield y) const; | |
1e59de90 | 50 | |
20effc67 | 51 | std::tuple<boost::optional<WebTokenEngine::token_t>, boost::optional<WebTokenEngine::principal_tags_t>> |
f67539c2 | 52 | get_from_jwt(const DoutPrefixProvider* dpp, const std::string& token, const req_state* const s, optional_yield y) const; |
f91f0fd5 | 53 | |
20effc67 | 54 | 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; |
11fdf7f2 TL |
55 | |
56 | result_t authenticate(const DoutPrefixProvider* dpp, | |
57 | const std::string& token, | |
f67539c2 | 58 | const req_state* s, optional_yield y) const; |
11fdf7f2 | 59 | |
20effc67 TL |
60 | template <typename T> |
61 | void recurse_and_insert(const string& key, const jwt::claim& c, T& t) const; | |
62 | WebTokenEngine::token_t get_token_claims(const jwt::decoded_jwt& decoded) const; | |
63 | ||
11fdf7f2 TL |
64 | public: |
65 | WebTokenEngine(CephContext* const cct, | |
1e59de90 | 66 | rgw::sal::Driver* driver, |
11fdf7f2 TL |
67 | const rgw::auth::TokenExtractor* const extractor, |
68 | const rgw::auth::WebIdentityApplier::Factory* const apl_factory) | |
69 | : cct(cct), | |
1e59de90 | 70 | driver(driver), |
11fdf7f2 TL |
71 | extractor(extractor), |
72 | apl_factory(apl_factory) { | |
73 | } | |
74 | ||
75 | const char* get_name() const noexcept override { | |
76 | return "rgw::auth::sts::WebTokenEngine"; | |
77 | } | |
78 | ||
f67539c2 TL |
79 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const override { |
80 | return authenticate(dpp, extractor->get_token(s), s, y); | |
11fdf7f2 TL |
81 | } |
82 | }; /* class WebTokenEngine */ | |
83 | ||
84 | class DefaultStrategy : public rgw::auth::Strategy, | |
85 | public rgw::auth::TokenExtractor, | |
86 | public rgw::auth::WebIdentityApplier::Factory { | |
1e59de90 TL |
87 | rgw::sal::Driver* driver; |
88 | const ImplicitTenants& implicit_tenant_context; | |
11fdf7f2 TL |
89 | |
90 | /* The engine. */ | |
91 | const WebTokenEngine web_token_engine; | |
92 | ||
93 | using aplptr_t = rgw::auth::IdentityApplier::aplptr_t; | |
94 | ||
95 | /* The method implements TokenExtractor for Web Token in req_state. */ | |
96 | std::string get_token(const req_state* const s) const override { | |
97 | return s->info.args.get("WebIdentityToken"); | |
98 | } | |
99 | ||
100 | aplptr_t create_apl_web_identity( CephContext* cct, | |
101 | const req_state* s, | |
20effc67 TL |
102 | const std::string& role_session, |
103 | const std::string& role_tenant, | |
104 | const std::unordered_multimap<std::string, std::string>& token, | |
105 | boost::optional<std::multimap<std::string, std::string>> role_tags, | |
106 | boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags) const override { | |
1e59de90 TL |
107 | auto apl = rgw::auth::add_sysreq(cct, driver, s, |
108 | rgw::auth::WebIdentityApplier(cct, driver, role_session, role_tenant, token, role_tags, principal_tags)); | |
11fdf7f2 TL |
109 | return aplptr_t(new decltype(apl)(std::move(apl))); |
110 | } | |
111 | ||
112 | public: | |
113 | DefaultStrategy(CephContext* const cct, | |
1e59de90 TL |
114 | const ImplicitTenants& implicit_tenant_context, |
115 | rgw::sal::Driver* driver) | |
116 | : driver(driver), | |
9f95a23c | 117 | implicit_tenant_context(implicit_tenant_context), |
1e59de90 | 118 | web_token_engine(cct, driver, |
11fdf7f2 TL |
119 | static_cast<rgw::auth::TokenExtractor*>(this), |
120 | static_cast<rgw::auth::WebIdentityApplier::Factory*>(this)) { | |
121 | /* When the constructor's body is being executed, all member engines | |
122 | * should be initialized. Thus, we can safely add them. */ | |
123 | using Control = rgw::auth::Strategy::Control; | |
124 | add_engine(Control::SUFFICIENT, web_token_engine); | |
125 | } | |
126 | ||
127 | const char* get_name() const noexcept override { | |
128 | return "rgw::auth::sts::DefaultStrategy"; | |
129 | } | |
130 | }; | |
131 | ||
9f95a23c | 132 | } // namespace rgw::auth::sts |
11fdf7f2 TL |
133 | |
134 | class RGWREST_STS : public RGWRESTOp { | |
135 | protected: | |
136 | STS::STSService sts; | |
137 | public: | |
138 | RGWREST_STS() = default; | |
f67539c2 | 139 | int verify_permission(optional_yield y) override; |
11fdf7f2 TL |
140 | void send_response() override; |
141 | }; | |
142 | ||
143 | class RGWSTSAssumeRoleWithWebIdentity : public RGWREST_STS { | |
144 | protected: | |
20effc67 TL |
145 | std::string duration; |
146 | std::string providerId; | |
147 | std::string policy; | |
148 | std::string roleArn; | |
149 | std::string roleSessionName; | |
150 | std::string sub; | |
151 | std::string aud; | |
152 | std::string iss; | |
11fdf7f2 TL |
153 | public: |
154 | RGWSTSAssumeRoleWithWebIdentity() = default; | |
f67539c2 | 155 | void execute(optional_yield y) override; |
11fdf7f2 TL |
156 | int get_params(); |
157 | const char* name() const override { return "assume_role_web_identity"; } | |
158 | RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE_WEB_IDENTITY; } | |
159 | }; | |
160 | ||
161 | class RGWSTSAssumeRole : public RGWREST_STS { | |
162 | protected: | |
20effc67 TL |
163 | std::string duration; |
164 | std::string externalId; | |
165 | std::string policy; | |
166 | std::string roleArn; | |
167 | std::string roleSessionName; | |
168 | std::string serialNumber; | |
169 | std::string tokenCode; | |
11fdf7f2 TL |
170 | public: |
171 | RGWSTSAssumeRole() = default; | |
f67539c2 | 172 | void execute(optional_yield y) override; |
11fdf7f2 TL |
173 | int get_params(); |
174 | const char* name() const override { return "assume_role"; } | |
175 | RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE; } | |
176 | }; | |
177 | ||
178 | class RGWSTSGetSessionToken : public RGWREST_STS { | |
179 | protected: | |
20effc67 TL |
180 | std::string duration; |
181 | std::string serialNumber; | |
182 | std::string tokenCode; | |
11fdf7f2 TL |
183 | public: |
184 | RGWSTSGetSessionToken() = default; | |
f67539c2 TL |
185 | void execute(optional_yield y) override; |
186 | int verify_permission(optional_yield y) override; | |
11fdf7f2 TL |
187 | int get_params(); |
188 | const char* name() const override { return "get_session_token"; } | |
189 | RGWOpType get_type() override { return RGW_STS_GET_SESSION_TOKEN; } | |
190 | }; | |
191 | ||
192 | class RGW_Auth_STS { | |
193 | public: | |
194 | static int authorize(const DoutPrefixProvider *dpp, | |
1e59de90 | 195 | rgw::sal::Driver* driver, |
11fdf7f2 | 196 | const rgw::auth::StrategyRegistry& auth_registry, |
1e59de90 | 197 | req_state *s, optional_yield y); |
11fdf7f2 TL |
198 | }; |
199 | ||
200 | class RGWHandler_REST_STS : public RGWHandler_REST { | |
201 | const rgw::auth::StrategyRegistry& auth_registry; | |
202 | RGWOp *op_post() override; | |
11fdf7f2 TL |
203 | public: |
204 | ||
1e59de90 | 205 | static bool action_exists(const req_state* s); |
11fdf7f2 | 206 | |
1e59de90 | 207 | RGWHandler_REST_STS(const rgw::auth::StrategyRegistry& auth_registry) |
11fdf7f2 | 208 | : RGWHandler_REST(), |
1e59de90 | 209 | auth_registry(auth_registry) {} |
11fdf7f2 TL |
210 | ~RGWHandler_REST_STS() override = default; |
211 | ||
1e59de90 TL |
212 | int init(rgw::sal::Driver* driver, |
213 | req_state *s, | |
11fdf7f2 | 214 | rgw::io::BasicClient *cio) override; |
f67539c2 TL |
215 | int authorize(const DoutPrefixProvider* dpp, optional_yield y) override; |
216 | int postauth_init(optional_yield y) override { return 0; } | |
11fdf7f2 TL |
217 | }; |
218 | ||
219 | class RGWRESTMgr_STS : public RGWRESTMgr { | |
220 | public: | |
221 | RGWRESTMgr_STS() = default; | |
222 | ~RGWRESTMgr_STS() override = default; | |
1e59de90 TL |
223 | |
224 | RGWRESTMgr *get_resource_mgr(req_state* const s, | |
11fdf7f2 TL |
225 | const std::string& uri, |
226 | std::string* const out_uri) override { | |
227 | return this; | |
228 | } | |
229 | ||
1e59de90 TL |
230 | RGWHandler_REST* get_handler(rgw::sal::Driver* driver, |
231 | req_state*, | |
11fdf7f2 TL |
232 | const rgw::auth::StrategyRegistry&, |
233 | const std::string&) override; | |
234 | }; | |
2a845540 | 235 |