]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/services/svc_cls.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / services / svc_cls.cc
CommitLineData
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
18using namespace std;
19
9f95a23c
TL
20static string log_lock_name = "rgw_log_lock";
21
b3b6e05e 22int 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 33int 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 48int 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 59int 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
78void 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 102int 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
123int 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 147int 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 165int 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 183int 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 201int 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 230int 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
259void 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 268int 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
275int 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
297int 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
322int 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
356int 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
381int 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
403int 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
433int 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
459int 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