]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae | 3 | |
1e59de90 | 4 | #pragma once |
7c673cae | 5 | |
e306af50 TL |
6 | #include "rgw_common.h" |
7 | #include "rgw_user.h" | |
7c673cae FG |
8 | #include "rgw_op.h" |
9 | #include "rgw_rest.h" | |
10 | #include "rgw_auth.h" | |
11 | #include "rgw_auth_keystone.h" | |
12 | #include "rgw_auth_filters.h" | |
9f95a23c | 13 | #include "rgw_sal.h" |
7c673cae FG |
14 | |
15 | #define RGW_SWIFT_TOKEN_EXPIRATION (15 * 60) | |
16 | ||
17 | namespace rgw { | |
18 | namespace auth { | |
19 | namespace swift { | |
20 | ||
21 | /* TempURL: applier. */ | |
22 | class TempURLApplier : public rgw::auth::LocalApplier { | |
23 | public: | |
24 | TempURLApplier(CephContext* const cct, | |
25 | const RGWUserInfo& user_info) | |
2a845540 | 26 | : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, std::nullopt, LocalApplier::NO_ACCESS_KEY) { |
7c673cae FG |
27 | }; |
28 | ||
11fdf7f2 | 29 | void modify_request_state(const DoutPrefixProvider* dpp, req_state * s) const override; /* in/out */ |
2a845540 | 30 | void write_ops_log_entry(rgw_log_entry& entry) const override; |
7c673cae FG |
31 | |
32 | struct Factory { | |
33 | virtual ~Factory() {} | |
34 | virtual aplptr_t create_apl_turl(CephContext* cct, | |
35 | const req_state* s, | |
36 | const RGWUserInfo& user_info) const = 0; | |
37 | }; | |
38 | }; | |
39 | ||
40 | /* TempURL: engine */ | |
41 | class TempURLEngine : public rgw::auth::Engine { | |
42 | using result_t = rgw::auth::Engine::result_t; | |
43 | ||
44 | CephContext* const cct; | |
1e59de90 | 45 | rgw::sal::Driver* driver; |
7c673cae FG |
46 | const TempURLApplier::Factory* const apl_factory; |
47 | ||
48 | /* Helper methods. */ | |
1e59de90 | 49 | void get_owner_info(const DoutPrefixProvider* dpp, |
11fdf7f2 | 50 | const req_state* s, |
f67539c2 TL |
51 | RGWUserInfo& owner_info, |
52 | optional_yield y) const; | |
11fdf7f2 | 53 | std::string convert_from_iso8601(std::string expires) const; |
7c673cae FG |
54 | bool is_applicable(const req_state* s) const noexcept; |
55 | bool is_expired(const std::string& expires) const; | |
494da23a | 56 | bool is_disallowed_header_present(const req_info& info) const; |
7c673cae FG |
57 | |
58 | class SignatureHelper; | |
d2e6a577 | 59 | class PrefixableSignatureHelper; |
7c673cae FG |
60 | |
61 | public: | |
62 | TempURLEngine(CephContext* const cct, | |
1e59de90 | 63 | rgw::sal::Driver* _driver , |
7c673cae FG |
64 | const TempURLApplier::Factory* const apl_factory) |
65 | : cct(cct), | |
1e59de90 | 66 | driver(_driver), |
7c673cae FG |
67 | apl_factory(apl_factory) { |
68 | } | |
69 | ||
70 | /* Interface implementations. */ | |
71 | const char* get_name() const noexcept override { | |
72 | return "rgw::auth::swift::TempURLEngine"; | |
73 | } | |
74 | ||
f67539c2 | 75 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const override; |
7c673cae FG |
76 | }; |
77 | ||
78 | ||
79 | /* AUTH_rgwtk */ | |
80 | class SignedTokenEngine : public rgw::auth::Engine { | |
81 | using result_t = rgw::auth::Engine::result_t; | |
82 | ||
83 | CephContext* const cct; | |
1e59de90 | 84 | rgw::sal::Driver* driver; |
7c673cae FG |
85 | const rgw::auth::TokenExtractor* const extractor; |
86 | const rgw::auth::LocalApplier::Factory* const apl_factory; | |
87 | ||
88 | bool is_applicable(const std::string& token) const noexcept; | |
f67539c2 | 89 | using rgw::auth::Engine::authenticate; |
11fdf7f2 TL |
90 | result_t authenticate(const DoutPrefixProvider* dpp, |
91 | const std::string& token, | |
7c673cae FG |
92 | const req_state* s) const; |
93 | ||
94 | public: | |
95 | SignedTokenEngine(CephContext* const cct, | |
1e59de90 | 96 | rgw::sal::Driver* _driver, |
7c673cae FG |
97 | const rgw::auth::TokenExtractor* const extractor, |
98 | const rgw::auth::LocalApplier::Factory* const apl_factory) | |
99 | : cct(cct), | |
1e59de90 | 100 | driver(_driver), |
7c673cae FG |
101 | extractor(extractor), |
102 | apl_factory(apl_factory) { | |
103 | } | |
104 | ||
105 | const char* get_name() const noexcept override { | |
106 | return "rgw::auth::swift::SignedTokenEngine"; | |
107 | } | |
108 | ||
f67539c2 TL |
109 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, |
110 | optional_yield y) const override { | |
11fdf7f2 | 111 | return authenticate(dpp, extractor->get_token(s), s); |
7c673cae FG |
112 | } |
113 | }; | |
114 | ||
115 | ||
116 | /* External token */ | |
117 | class ExternalTokenEngine : public rgw::auth::Engine { | |
118 | using result_t = rgw::auth::Engine::result_t; | |
119 | ||
120 | CephContext* const cct; | |
1e59de90 | 121 | rgw::sal::Driver* driver; |
7c673cae FG |
122 | const rgw::auth::TokenExtractor* const extractor; |
123 | const rgw::auth::LocalApplier::Factory* const apl_factory; | |
124 | ||
125 | bool is_applicable(const std::string& token) const noexcept; | |
11fdf7f2 TL |
126 | result_t authenticate(const DoutPrefixProvider* dpp, |
127 | const std::string& token, | |
f67539c2 | 128 | const req_state* s, optional_yield y) const; |
7c673cae FG |
129 | |
130 | public: | |
131 | ExternalTokenEngine(CephContext* const cct, | |
1e59de90 | 132 | rgw::sal::Driver* _driver, |
7c673cae FG |
133 | const rgw::auth::TokenExtractor* const extractor, |
134 | const rgw::auth::LocalApplier::Factory* const apl_factory) | |
135 | : cct(cct), | |
1e59de90 | 136 | driver(_driver), |
7c673cae FG |
137 | extractor(extractor), |
138 | apl_factory(apl_factory) { | |
139 | } | |
140 | ||
141 | const char* get_name() const noexcept override { | |
142 | return "rgw::auth::swift::ExternalTokenEngine"; | |
143 | } | |
144 | ||
f67539c2 TL |
145 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, |
146 | optional_yield y) const override { | |
147 | return authenticate(dpp, extractor->get_token(s), s, y); | |
7c673cae FG |
148 | } |
149 | }; | |
150 | ||
e306af50 TL |
151 | /* SwiftAnonymous: applier. */ |
152 | class SwiftAnonymousApplier : public rgw::auth::LocalApplier { | |
153 | public: | |
154 | SwiftAnonymousApplier(CephContext* const cct, | |
155 | const RGWUserInfo& user_info) | |
2a845540 | 156 | : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, std::nullopt, LocalApplier::NO_ACCESS_KEY) { |
20effc67 | 157 | } |
e306af50 | 158 | bool is_admin_of(const rgw_user& uid) const {return false;} |
f91f0fd5 | 159 | bool is_owner_of(const rgw_user& uid) const {return uid.id.compare(RGW_USER_ANON_ID) == 0;} |
e306af50 | 160 | }; |
7c673cae FG |
161 | |
162 | class SwiftAnonymousEngine : public rgw::auth::AnonymousEngine { | |
163 | const rgw::auth::TokenExtractor* const extractor; | |
164 | ||
165 | bool is_applicable(const req_state* s) const noexcept override { | |
166 | return extractor->get_token(s).empty(); | |
167 | } | |
168 | ||
169 | public: | |
170 | SwiftAnonymousEngine(CephContext* const cct, | |
e306af50 | 171 | const SwiftAnonymousApplier::Factory* const apl_factory, |
7c673cae FG |
172 | const rgw::auth::TokenExtractor* const extractor) |
173 | : AnonymousEngine(cct, apl_factory), | |
174 | extractor(extractor) { | |
175 | } | |
176 | ||
177 | const char* get_name() const noexcept override { | |
178 | return "rgw::auth::swift::SwiftAnonymousEngine"; | |
179 | } | |
180 | }; | |
181 | ||
182 | ||
183 | class DefaultStrategy : public rgw::auth::Strategy, | |
7c673cae FG |
184 | public rgw::auth::RemoteApplier::Factory, |
185 | public rgw::auth::LocalApplier::Factory, | |
186 | public rgw::auth::swift::TempURLApplier::Factory { | |
1e59de90 TL |
187 | rgw::sal::Driver* driver; |
188 | const ImplicitTenants& implicit_tenant_context; | |
7c673cae FG |
189 | |
190 | /* The engines. */ | |
191 | const rgw::auth::swift::TempURLEngine tempurl_engine; | |
192 | const rgw::auth::swift::SignedTokenEngine signed_engine; | |
3efd9988 | 193 | boost::optional <const rgw::auth::keystone::TokenEngine> keystone_engine; |
7c673cae FG |
194 | const rgw::auth::swift::ExternalTokenEngine external_engine; |
195 | const rgw::auth::swift::SwiftAnonymousEngine anon_engine; | |
196 | ||
197 | using keystone_config_t = rgw::keystone::CephCtxConfig; | |
198 | using keystone_cache_t = rgw::keystone::TokenCache; | |
199 | using aplptr_t = rgw::auth::IdentityApplier::aplptr_t; | |
200 | using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t; | |
201 | ||
202 | /* The method implements TokenExtractor for X-Auth-Token present in req_state. */ | |
1e59de90 TL |
203 | struct AuthTokenExtractor : rgw::auth::TokenExtractor { |
204 | std::string get_token(const req_state* const s) const override { | |
205 | /* Returning a reference here would end in GCC complaining about a reference | |
206 | * to temporary. */ | |
207 | return s->info.env->get("HTTP_X_AUTH_TOKEN", ""); | |
208 | } | |
209 | } auth_token_extractor; | |
210 | ||
211 | /* The method implements TokenExtractor for X-Service-Token present in req_state. */ | |
212 | struct ServiceTokenExtractor : rgw::auth::TokenExtractor { | |
213 | std::string get_token(const req_state* const s) const override { | |
214 | return s->info.env->get("HTTP_X_SERVICE_TOKEN", ""); | |
215 | } | |
216 | } service_token_extractor; | |
7c673cae FG |
217 | |
218 | aplptr_t create_apl_remote(CephContext* const cct, | |
219 | const req_state* const s, | |
220 | acl_strategy_t&& extra_acl_strategy, | |
11fdf7f2 | 221 | const rgw::auth::RemoteApplier::AuthInfo &info) const override { |
7c673cae | 222 | auto apl = \ |
1e59de90 TL |
223 | rgw::auth::add_3rdparty(driver, rgw_user(s->account_name), |
224 | rgw::auth::add_sysreq(cct, driver, s, | |
225 | rgw::auth::RemoteApplier(cct, driver, std::move(extra_acl_strategy), info, | |
9f95a23c TL |
226 | implicit_tenant_context, |
227 | rgw::auth::ImplicitTenants::IMPLICIT_TENANTS_SWIFT))); | |
7c673cae FG |
228 | /* TODO(rzarzynski): replace with static_ptr. */ |
229 | return aplptr_t(new decltype(apl)(std::move(apl))); | |
230 | } | |
231 | ||
232 | aplptr_t create_apl_local(CephContext* const cct, | |
233 | const req_state* const s, | |
234 | const RGWUserInfo& user_info, | |
11fdf7f2 | 235 | const std::string& subuser, |
2a845540 TL |
236 | const std::optional<uint32_t>& perm_mask, |
237 | const std::string& access_key_id) const override { | |
7c673cae | 238 | auto apl = \ |
1e59de90 TL |
239 | rgw::auth::add_3rdparty(driver, rgw_user(s->account_name), |
240 | rgw::auth::add_sysreq(cct, driver, s, | |
2a845540 | 241 | rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id))); |
7c673cae FG |
242 | /* TODO(rzarzynski): replace with static_ptr. */ |
243 | return aplptr_t(new decltype(apl)(std::move(apl))); | |
244 | } | |
245 | ||
246 | aplptr_t create_apl_turl(CephContext* const cct, | |
247 | const req_state* const s, | |
248 | const RGWUserInfo& user_info) const override { | |
249 | /* TempURL doesn't need any user account override. It's a Swift-specific | |
250 | * mechanism that requires account name internally, so there is no | |
251 | * business with delegating the responsibility outside. */ | |
252 | return aplptr_t(new rgw::auth::swift::TempURLApplier(cct, user_info)); | |
253 | } | |
254 | ||
255 | public: | |
256 | DefaultStrategy(CephContext* const cct, | |
1e59de90 TL |
257 | const ImplicitTenants& implicit_tenant_context, |
258 | rgw::sal::Driver* _driver) | |
259 | : driver(_driver), | |
9f95a23c | 260 | implicit_tenant_context(implicit_tenant_context), |
7c673cae | 261 | tempurl_engine(cct, |
1e59de90 | 262 | driver, |
7c673cae FG |
263 | static_cast<rgw::auth::swift::TempURLApplier::Factory*>(this)), |
264 | signed_engine(cct, | |
1e59de90 TL |
265 | driver, |
266 | static_cast<rgw::auth::TokenExtractor*>(&auth_token_extractor), | |
7c673cae | 267 | static_cast<rgw::auth::LocalApplier::Factory*>(this)), |
7c673cae | 268 | external_engine(cct, |
1e59de90 TL |
269 | driver, |
270 | static_cast<rgw::auth::TokenExtractor*>(&auth_token_extractor), | |
7c673cae FG |
271 | static_cast<rgw::auth::LocalApplier::Factory*>(this)), |
272 | anon_engine(cct, | |
f91f0fd5 | 273 | static_cast<SwiftAnonymousApplier::Factory*>(this), |
1e59de90 | 274 | static_cast<rgw::auth::TokenExtractor*>(&auth_token_extractor)) { |
7c673cae FG |
275 | /* When the constructor's body is being executed, all member engines |
276 | * should be initialized. Thus, we can safely add them. */ | |
277 | using Control = rgw::auth::Strategy::Control; | |
278 | ||
279 | add_engine(Control::SUFFICIENT, tempurl_engine); | |
280 | add_engine(Control::SUFFICIENT, signed_engine); | |
281 | ||
282 | /* The auth strategy is responsible for deciding whether a parcular | |
283 | * engine is disabled or not. */ | |
284 | if (! cct->_conf->rgw_keystone_url.empty()) { | |
3efd9988 | 285 | keystone_engine.emplace(cct, |
1e59de90 TL |
286 | static_cast<rgw::auth::TokenExtractor*>(&auth_token_extractor), |
287 | static_cast<rgw::auth::TokenExtractor*>(&service_token_extractor), | |
3efd9988 FG |
288 | static_cast<rgw::auth::RemoteApplier::Factory*>(this), |
289 | keystone_config_t::get_instance(), | |
290 | keystone_cache_t::get_instance<keystone_config_t>()); | |
291 | ||
292 | add_engine(Control::SUFFICIENT, *keystone_engine); | |
7c673cae FG |
293 | } |
294 | if (! cct->_conf->rgw_swift_auth_url.empty()) { | |
295 | add_engine(Control::SUFFICIENT, external_engine); | |
296 | } | |
297 | ||
298 | add_engine(Control::SUFFICIENT, anon_engine); | |
299 | } | |
300 | ||
301 | const char* get_name() const noexcept override { | |
302 | return "rgw::auth::swift::DefaultStrategy"; | |
303 | } | |
304 | }; | |
305 | ||
306 | } /* namespace swift */ | |
307 | } /* namespace auth */ | |
308 | } /* namespace rgw */ | |
309 | ||
310 | ||
311 | class RGW_SWIFT_Auth_Get : public RGWOp { | |
312 | public: | |
313 | RGW_SWIFT_Auth_Get() {} | |
314 | ~RGW_SWIFT_Auth_Get() override {} | |
315 | ||
f67539c2 TL |
316 | int verify_permission(optional_yield) override { return 0; } |
317 | void execute(optional_yield y) override; | |
11fdf7f2 TL |
318 | const char* name() const override { return "swift_auth_get"; } |
319 | dmc::client_id dmclock_client() override { return dmc::client_id::auth; } | |
7c673cae FG |
320 | }; |
321 | ||
322 | class RGWHandler_SWIFT_Auth : public RGWHandler_REST { | |
323 | public: | |
324 | RGWHandler_SWIFT_Auth() {} | |
325 | ~RGWHandler_SWIFT_Auth() override {} | |
326 | RGWOp *op_get() override; | |
327 | ||
1e59de90 | 328 | int init(rgw::sal::Driver* driver, req_state *state, rgw::io::BasicClient *cio) override; |
f67539c2 TL |
329 | int authorize(const DoutPrefixProvider *dpp, optional_yield y) override; |
330 | int postauth_init(optional_yield) override { return 0; } | |
331 | int read_permissions(RGWOp *op, optional_yield) override { return 0; } | |
7c673cae FG |
332 | |
333 | virtual RGWAccessControlPolicy *alloc_policy() { return NULL; } | |
334 | virtual void free_policy(RGWAccessControlPolicy *policy) {} | |
335 | }; | |
336 | ||
337 | class RGWRESTMgr_SWIFT_Auth : public RGWRESTMgr { | |
338 | public: | |
339 | RGWRESTMgr_SWIFT_Auth() = default; | |
340 | ~RGWRESTMgr_SWIFT_Auth() override = default; | |
341 | ||
1e59de90 | 342 | RGWRESTMgr *get_resource_mgr(req_state* const s, |
7c673cae FG |
343 | const std::string& uri, |
344 | std::string* const out_uri) override { | |
345 | return this; | |
346 | } | |
347 | ||
1e59de90 TL |
348 | RGWHandler_REST* get_handler(rgw::sal::Driver* driver, |
349 | req_state*, | |
7c673cae FG |
350 | const rgw::auth::StrategyRegistry&, |
351 | const std::string&) override { | |
352 | return new RGWHandler_SWIFT_Auth; | |
353 | } | |
354 | }; |