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