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