]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/services/svc_cls.cc
import ceph pacific 16.2.5
[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
18static string log_lock_name = "rgw_log_lock";
19
b3b6e05e 20int 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 31int 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 46int 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 57int 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
76void 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 100int 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
121int 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 145int 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 163int 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 181int 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 199int 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 228int 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
257void 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 266int 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
273int 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
295int 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
320int 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
354int 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
379int 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
401int 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
431int 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
457int 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