]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab ft=cpp | |
3 | ||
4 | ||
5 | #include "svc_cls.h" | |
6 | #include "svc_rados.h" | |
7 | #include "svc_zone.h" | |
8 | ||
9 | #include "rgw/rgw_zone.h" | |
10 | ||
11 | #include "cls/otp/cls_otp_client.h" | |
12 | #include "cls/log/cls_log_client.h" | |
13 | #include "cls/lock/cls_lock_client.h" | |
14 | ||
15 | ||
16 | #define dout_subsys ceph_subsys_rgw | |
17 | ||
20effc67 TL |
18 | using namespace std; |
19 | ||
9f95a23c TL |
20 | static string log_lock_name = "rgw_log_lock"; |
21 | ||
b3b6e05e | 22 | int RGWSI_Cls::do_start(optional_yield y, const DoutPrefixProvider *dpp) |
9f95a23c | 23 | { |
b3b6e05e | 24 | int r = mfa.do_start(y, dpp); |
9f95a23c | 25 | if (r < 0) { |
b3b6e05e | 26 | ldpp_dout(dpp, 0) << "ERROR: failed to start mfa service" << dendl; |
9f95a23c TL |
27 | return r; |
28 | } | |
29 | ||
30 | return 0; | |
31 | } | |
32 | ||
b3b6e05e | 33 | int RGWSI_Cls::MFA::get_mfa_obj(const DoutPrefixProvider *dpp, const rgw_user& user, std::optional<RGWSI_RADOS::Obj> *obj) |
9f95a23c TL |
34 | { |
35 | string oid = get_mfa_oid(user); | |
36 | rgw_raw_obj o(zone_svc->get_zone_params().otp_pool, oid); | |
37 | ||
38 | obj->emplace(rados_svc->obj(o)); | |
b3b6e05e | 39 | int r = (*obj)->open(dpp); |
9f95a23c | 40 | if (r < 0) { |
b3b6e05e | 41 | ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl; |
9f95a23c TL |
42 | return r; |
43 | } | |
44 | ||
45 | return 0; | |
46 | } | |
47 | ||
b3b6e05e | 48 | int RGWSI_Cls::MFA::get_mfa_ref(const DoutPrefixProvider *dpp, const rgw_user& user, rgw_rados_ref *ref) |
9f95a23c TL |
49 | { |
50 | std::optional<RGWSI_RADOS::Obj> obj; | |
b3b6e05e | 51 | int r = get_mfa_obj(dpp, user, &obj); |
9f95a23c TL |
52 | if (r < 0) { |
53 | return r; | |
54 | } | |
55 | *ref = obj->get_ref(); | |
56 | return 0; | |
57 | } | |
58 | ||
b3b6e05e | 59 | int RGWSI_Cls::MFA::check_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const string& otp_id, const string& pin, optional_yield y) |
9f95a23c TL |
60 | { |
61 | rgw_rados_ref ref; | |
b3b6e05e | 62 | int r = get_mfa_ref(dpp, user, &ref); |
9f95a23c TL |
63 | if (r < 0) { |
64 | return r; | |
65 | } | |
66 | ||
67 | rados::cls::otp::otp_check_t result; | |
68 | ||
69 | r = rados::cls::otp::OTP::check(cct, ref.pool.ioctx(), ref.obj.oid, otp_id, pin, &result); | |
70 | if (r < 0) | |
71 | return r; | |
72 | ||
b3b6e05e | 73 | ldpp_dout(dpp, 20) << "OTP check, otp_id=" << otp_id << " result=" << (int)result.result << dendl; |
9f95a23c TL |
74 | |
75 | return (result.result == rados::cls::otp::OTP_CHECK_SUCCESS ? 0 : -EACCES); | |
76 | } | |
77 | ||
78 | void RGWSI_Cls::MFA::prepare_mfa_write(librados::ObjectWriteOperation *op, | |
79 | RGWObjVersionTracker *objv_tracker, | |
80 | const ceph::real_time& mtime) | |
81 | { | |
82 | RGWObjVersionTracker ot; | |
83 | ||
84 | if (objv_tracker) { | |
85 | ot = *objv_tracker; | |
86 | } | |
87 | ||
88 | if (ot.write_version.tag.empty()) { | |
89 | if (ot.read_version.tag.empty()) { | |
90 | ot.generate_new_write_ver(cct); | |
91 | } else { | |
92 | ot.write_version = ot.read_version; | |
93 | ot.write_version.ver++; | |
94 | } | |
95 | } | |
96 | ||
97 | ot.prepare_op_for_write(op); | |
98 | struct timespec mtime_ts = real_clock::to_timespec(mtime); | |
99 | op->mtime2(&mtime_ts); | |
100 | } | |
101 | ||
b3b6e05e | 102 | int RGWSI_Cls::MFA::create_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const rados::cls::otp::otp_info_t& config, |
9f95a23c TL |
103 | RGWObjVersionTracker *objv_tracker, const ceph::real_time& mtime, optional_yield y) |
104 | { | |
105 | std::optional<RGWSI_RADOS::Obj> obj; | |
b3b6e05e | 106 | int r = get_mfa_obj(dpp, user, &obj); |
9f95a23c TL |
107 | if (r < 0) { |
108 | return r; | |
109 | } | |
110 | ||
111 | librados::ObjectWriteOperation op; | |
112 | prepare_mfa_write(&op, objv_tracker, mtime); | |
113 | rados::cls::otp::OTP::create(&op, config); | |
b3b6e05e | 114 | r = obj->operate(dpp, &op, y); |
9f95a23c | 115 | if (r < 0) { |
b3b6e05e | 116 | ldpp_dout(dpp, 20) << "OTP create, otp_id=" << config.id << " result=" << (int)r << dendl; |
9f95a23c TL |
117 | return r; |
118 | } | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
b3b6e05e TL |
123 | int RGWSI_Cls::MFA::remove_mfa(const DoutPrefixProvider *dpp, |
124 | const rgw_user& user, const string& id, | |
9f95a23c TL |
125 | RGWObjVersionTracker *objv_tracker, |
126 | const ceph::real_time& mtime, | |
127 | optional_yield y) | |
128 | { | |
129 | std::optional<RGWSI_RADOS::Obj> obj; | |
b3b6e05e | 130 | int r = get_mfa_obj(dpp, user, &obj); |
9f95a23c TL |
131 | if (r < 0) { |
132 | return r; | |
133 | } | |
134 | ||
135 | librados::ObjectWriteOperation op; | |
136 | prepare_mfa_write(&op, objv_tracker, mtime); | |
137 | rados::cls::otp::OTP::remove(&op, id); | |
b3b6e05e | 138 | r = obj->operate(dpp, &op, y); |
9f95a23c | 139 | if (r < 0) { |
b3b6e05e | 140 | ldpp_dout(dpp, 20) << "OTP remove, otp_id=" << id << " result=" << (int)r << dendl; |
9f95a23c TL |
141 | return r; |
142 | } | |
143 | ||
144 | return 0; | |
145 | } | |
146 | ||
b3b6e05e | 147 | int RGWSI_Cls::MFA::get_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const string& id, rados::cls::otp::otp_info_t *result, |
9f95a23c TL |
148 | optional_yield y) |
149 | { | |
150 | rgw_rados_ref ref; | |
151 | ||
b3b6e05e | 152 | int r = get_mfa_ref(dpp, user, &ref); |
9f95a23c TL |
153 | if (r < 0) { |
154 | return r; | |
155 | } | |
156 | ||
157 | r = rados::cls::otp::OTP::get(nullptr, ref.pool.ioctx(), ref.obj.oid, id, result); | |
158 | if (r < 0) { | |
159 | return r; | |
160 | } | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
b3b6e05e | 165 | int RGWSI_Cls::MFA::list_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, list<rados::cls::otp::otp_info_t> *result, |
9f95a23c TL |
166 | optional_yield y) |
167 | { | |
168 | rgw_rados_ref ref; | |
169 | ||
b3b6e05e | 170 | int r = get_mfa_ref(dpp, user, &ref); |
9f95a23c TL |
171 | if (r < 0) { |
172 | return r; | |
173 | } | |
174 | ||
175 | r = rados::cls::otp::OTP::get_all(nullptr, ref.pool.ioctx(), ref.obj.oid, result); | |
176 | if (r < 0) { | |
177 | return r; | |
178 | } | |
179 | ||
180 | return 0; | |
181 | } | |
182 | ||
b3b6e05e | 183 | int RGWSI_Cls::MFA::otp_get_current_time(const DoutPrefixProvider *dpp, const rgw_user& user, ceph::real_time *result, |
9f95a23c TL |
184 | optional_yield y) |
185 | { | |
186 | rgw_rados_ref ref; | |
187 | ||
b3b6e05e | 188 | int r = get_mfa_ref(dpp, user, &ref); |
9f95a23c TL |
189 | if (r < 0) { |
190 | return r; | |
191 | } | |
192 | ||
193 | r = rados::cls::otp::OTP::get_current_time(ref.pool.ioctx(), ref.obj.oid, result); | |
194 | if (r < 0) { | |
195 | return r; | |
196 | } | |
197 | ||
198 | return 0; | |
199 | } | |
200 | ||
b3b6e05e | 201 | int RGWSI_Cls::MFA::set_mfa(const DoutPrefixProvider *dpp, const string& oid, const list<rados::cls::otp::otp_info_t>& entries, |
9f95a23c TL |
202 | bool reset_obj, RGWObjVersionTracker *objv_tracker, |
203 | const real_time& mtime, | |
204 | optional_yield y) | |
205 | { | |
206 | rgw_raw_obj o(zone_svc->get_zone_params().otp_pool, oid); | |
207 | auto obj = rados_svc->obj(o); | |
b3b6e05e | 208 | int r = obj.open(dpp); |
9f95a23c | 209 | if (r < 0) { |
b3b6e05e | 210 | ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl; |
9f95a23c TL |
211 | return r; |
212 | } | |
213 | librados::ObjectWriteOperation op; | |
214 | if (reset_obj) { | |
215 | op.remove(); | |
216 | op.set_op_flags2(LIBRADOS_OP_FLAG_FAILOK); | |
217 | op.create(false); | |
218 | } | |
219 | prepare_mfa_write(&op, objv_tracker, mtime); | |
220 | rados::cls::otp::OTP::set(&op, entries); | |
b3b6e05e | 221 | r = obj.operate(dpp, &op, y); |
9f95a23c | 222 | if (r < 0) { |
b3b6e05e | 223 | ldpp_dout(dpp, 20) << "OTP set entries.size()=" << entries.size() << " result=" << (int)r << dendl; |
9f95a23c TL |
224 | return r; |
225 | } | |
226 | ||
227 | return 0; | |
228 | } | |
229 | ||
b3b6e05e | 230 | int RGWSI_Cls::MFA::list_mfa(const DoutPrefixProvider *dpp, const string& oid, list<rados::cls::otp::otp_info_t> *result, |
9f95a23c TL |
231 | RGWObjVersionTracker *objv_tracker, ceph::real_time *pmtime, |
232 | optional_yield y) | |
233 | { | |
234 | rgw_raw_obj o(zone_svc->get_zone_params().otp_pool, oid); | |
235 | auto obj = rados_svc->obj(o); | |
b3b6e05e | 236 | int r = obj.open(dpp); |
9f95a23c | 237 | if (r < 0) { |
b3b6e05e | 238 | ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl; |
9f95a23c TL |
239 | return r; |
240 | } | |
241 | auto& ref = obj.get_ref(); | |
242 | librados::ObjectReadOperation op; | |
243 | struct timespec mtime_ts; | |
244 | if (pmtime) { | |
245 | op.stat2(nullptr, &mtime_ts, nullptr); | |
246 | } | |
247 | objv_tracker->prepare_op_for_read(&op); | |
248 | r = rados::cls::otp::OTP::get_all(&op, ref.pool.ioctx(), ref.obj.oid, result); | |
249 | if (r < 0) { | |
250 | return r; | |
251 | } | |
252 | if (pmtime) { | |
253 | *pmtime = ceph::real_clock::from_timespec(mtime_ts); | |
254 | } | |
255 | ||
256 | return 0; | |
257 | } | |
258 | ||
259 | void RGWSI_Cls::TimeLog::prepare_entry(cls_log_entry& entry, | |
260 | const real_time& ut, | |
261 | const string& section, | |
262 | const string& key, | |
263 | bufferlist& bl) | |
264 | { | |
265 | cls_log_add_prepare_entry(entry, utime_t(ut), section, key, bl); | |
266 | } | |
267 | ||
b3b6e05e | 268 | int RGWSI_Cls::TimeLog::init_obj(const DoutPrefixProvider *dpp, const string& oid, RGWSI_RADOS::Obj& obj) |
9f95a23c TL |
269 | { |
270 | rgw_raw_obj o(zone_svc->get_zone_params().log_pool, oid); | |
271 | obj = rados_svc->obj(o); | |
b3b6e05e | 272 | return obj.open(dpp); |
9f95a23c TL |
273 | |
274 | } | |
b3b6e05e TL |
275 | int RGWSI_Cls::TimeLog::add(const DoutPrefixProvider *dpp, |
276 | const string& oid, | |
9f95a23c TL |
277 | const real_time& ut, |
278 | const string& section, | |
279 | const string& key, | |
280 | bufferlist& bl, | |
281 | optional_yield y) | |
282 | { | |
283 | RGWSI_RADOS::Obj obj; | |
284 | ||
b3b6e05e | 285 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
286 | if (r < 0) { |
287 | return r; | |
288 | } | |
289 | ||
290 | librados::ObjectWriteOperation op; | |
291 | utime_t t(ut); | |
292 | cls_log_add(op, t, section, key, bl); | |
293 | ||
b3b6e05e | 294 | return obj.operate(dpp, &op, y); |
9f95a23c TL |
295 | } |
296 | ||
b3b6e05e TL |
297 | int RGWSI_Cls::TimeLog::add(const DoutPrefixProvider *dpp, |
298 | const string& oid, | |
9f95a23c TL |
299 | std::list<cls_log_entry>& entries, |
300 | librados::AioCompletion *completion, | |
301 | bool monotonic_inc, | |
302 | optional_yield y) | |
303 | { | |
304 | RGWSI_RADOS::Obj obj; | |
305 | ||
b3b6e05e | 306 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
307 | if (r < 0) { |
308 | return r; | |
309 | } | |
310 | ||
311 | librados::ObjectWriteOperation op; | |
312 | cls_log_add(op, entries, monotonic_inc); | |
313 | ||
314 | if (!completion) { | |
b3b6e05e | 315 | r = obj.operate(dpp, &op, y); |
9f95a23c TL |
316 | } else { |
317 | r = obj.aio_operate(completion, &op); | |
318 | } | |
319 | return r; | |
320 | } | |
321 | ||
b3b6e05e TL |
322 | int RGWSI_Cls::TimeLog::list(const DoutPrefixProvider *dpp, |
323 | const string& oid, | |
9f95a23c TL |
324 | const real_time& start_time, |
325 | const real_time& end_time, | |
326 | int max_entries, std::list<cls_log_entry>& entries, | |
327 | const string& marker, | |
328 | string *out_marker, | |
329 | bool *truncated, | |
330 | optional_yield y) | |
331 | { | |
332 | RGWSI_RADOS::Obj obj; | |
333 | ||
b3b6e05e | 334 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
335 | if (r < 0) { |
336 | return r; | |
337 | } | |
338 | ||
339 | librados::ObjectReadOperation op; | |
340 | ||
341 | utime_t st(start_time); | |
342 | utime_t et(end_time); | |
343 | ||
344 | cls_log_list(op, st, et, marker, max_entries, entries, | |
345 | out_marker, truncated); | |
346 | ||
347 | bufferlist obl; | |
348 | ||
b3b6e05e | 349 | int ret = obj.operate(dpp, &op, &obl, y); |
9f95a23c TL |
350 | if (ret < 0) |
351 | return ret; | |
352 | ||
353 | return 0; | |
354 | } | |
355 | ||
b3b6e05e TL |
356 | int RGWSI_Cls::TimeLog::info(const DoutPrefixProvider *dpp, |
357 | const string& oid, | |
9f95a23c TL |
358 | cls_log_header *header, |
359 | optional_yield y) | |
360 | { | |
361 | RGWSI_RADOS::Obj obj; | |
362 | ||
b3b6e05e | 363 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
364 | if (r < 0) { |
365 | return r; | |
366 | } | |
367 | ||
368 | librados::ObjectReadOperation op; | |
369 | ||
370 | cls_log_info(op, header); | |
371 | ||
372 | bufferlist obl; | |
373 | ||
b3b6e05e | 374 | int ret = obj.operate(dpp, &op, &obl, y); |
9f95a23c TL |
375 | if (ret < 0) |
376 | return ret; | |
377 | ||
378 | return 0; | |
379 | } | |
380 | ||
b3b6e05e TL |
381 | int RGWSI_Cls::TimeLog::info_async(const DoutPrefixProvider *dpp, |
382 | RGWSI_RADOS::Obj& obj, | |
9f95a23c TL |
383 | const string& oid, |
384 | cls_log_header *header, | |
385 | librados::AioCompletion *completion) | |
386 | { | |
b3b6e05e | 387 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
388 | if (r < 0) { |
389 | return r; | |
390 | } | |
391 | ||
392 | librados::ObjectReadOperation op; | |
393 | ||
394 | cls_log_info(op, header); | |
395 | ||
396 | int ret = obj.aio_operate(completion, &op, nullptr); | |
397 | if (ret < 0) | |
398 | return ret; | |
399 | ||
400 | return 0; | |
401 | } | |
402 | ||
b3b6e05e TL |
403 | int RGWSI_Cls::TimeLog::trim(const DoutPrefixProvider *dpp, |
404 | const string& oid, | |
9f95a23c TL |
405 | const real_time& start_time, |
406 | const real_time& end_time, | |
407 | const string& from_marker, | |
408 | const string& to_marker, | |
409 | librados::AioCompletion *completion, | |
410 | optional_yield y) | |
411 | { | |
412 | RGWSI_RADOS::Obj obj; | |
413 | ||
b3b6e05e | 414 | int r = init_obj(dpp, oid, obj); |
9f95a23c TL |
415 | if (r < 0) { |
416 | return r; | |
417 | } | |
418 | ||
419 | utime_t st(start_time); | |
420 | utime_t et(end_time); | |
421 | ||
422 | librados::ObjectWriteOperation op; | |
423 | cls_log_trim(op, st, et, from_marker, to_marker); | |
424 | ||
425 | if (!completion) { | |
b3b6e05e | 426 | r = obj.operate(dpp, &op, y); |
9f95a23c TL |
427 | } else { |
428 | r = obj.aio_operate(completion, &op); | |
429 | } | |
430 | return r; | |
431 | } | |
432 | ||
b3b6e05e TL |
433 | int RGWSI_Cls::Lock::lock_exclusive(const DoutPrefixProvider *dpp, |
434 | const rgw_pool& pool, | |
9f95a23c TL |
435 | const string& oid, |
436 | timespan& duration, | |
437 | string& zone_id, | |
438 | string& owner_id, | |
439 | std::optional<string> lock_name) | |
440 | { | |
441 | auto p = rados_svc->pool(pool); | |
b3b6e05e | 442 | int r = p.open(dpp); |
9f95a23c TL |
443 | if (r < 0) { |
444 | return r; | |
445 | } | |
446 | ||
447 | uint64_t msec = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); | |
448 | utime_t ut(msec / 1000, msec % 1000); | |
449 | ||
450 | rados::cls::lock::Lock l(lock_name.value_or(log_lock_name)); | |
451 | l.set_duration(ut); | |
452 | l.set_cookie(owner_id); | |
453 | l.set_tag(zone_id); | |
454 | l.set_may_renew(true); | |
455 | ||
456 | return l.lock_exclusive(&p.ioctx(), oid); | |
457 | } | |
458 | ||
b3b6e05e TL |
459 | int RGWSI_Cls::Lock::unlock(const DoutPrefixProvider *dpp, |
460 | const rgw_pool& pool, | |
9f95a23c TL |
461 | const string& oid, |
462 | string& zone_id, | |
463 | string& owner_id, | |
464 | std::optional<string> lock_name) | |
465 | { | |
466 | auto p = rados_svc->pool(pool); | |
b3b6e05e | 467 | int r = p.open(dpp); |
9f95a23c TL |
468 | if (r < 0) { |
469 | return r; | |
470 | } | |
471 | ||
472 | rados::cls::lock::Lock l(lock_name.value_or(log_lock_name)); | |
473 | l.set_tag(zone_id); | |
474 | l.set_cookie(owner_id); | |
475 | ||
476 | return l.unlock(&p.ioctx(), oid); | |
477 | } | |
478 |