]> git.proxmox.com Git - ceph.git/blame_incremental - ceph/src/rgw/services/svc_cls.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / rgw / services / svc_cls.cc
... / ...
CommitLineData
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
20int RGWSI_Cls::do_start(optional_yield y, const DoutPrefixProvider *dpp)
21{
22 int r = mfa.do_start(y, dpp);
23 if (r < 0) {
24 ldpp_dout(dpp, 0) << "ERROR: failed to start mfa service" << dendl;
25 return r;
26 }
27
28 return 0;
29}
30
31int RGWSI_Cls::MFA::get_mfa_obj(const DoutPrefixProvider *dpp, const rgw_user& user, std::optional<RGWSI_RADOS::Obj> *obj)
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));
37 int r = (*obj)->open(dpp);
38 if (r < 0) {
39 ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl;
40 return r;
41 }
42
43 return 0;
44}
45
46int RGWSI_Cls::MFA::get_mfa_ref(const DoutPrefixProvider *dpp, const rgw_user& user, rgw_rados_ref *ref)
47{
48 std::optional<RGWSI_RADOS::Obj> obj;
49 int r = get_mfa_obj(dpp, user, &obj);
50 if (r < 0) {
51 return r;
52 }
53 *ref = obj->get_ref();
54 return 0;
55}
56
57int RGWSI_Cls::MFA::check_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const string& otp_id, const string& pin, optional_yield y)
58{
59 rgw_rados_ref ref;
60 int r = get_mfa_ref(dpp, user, &ref);
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
71 ldpp_dout(dpp, 20) << "OTP check, otp_id=" << otp_id << " result=" << (int)result.result << dendl;
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
100int RGWSI_Cls::MFA::create_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const rados::cls::otp::otp_info_t& config,
101 RGWObjVersionTracker *objv_tracker, const ceph::real_time& mtime, optional_yield y)
102{
103 std::optional<RGWSI_RADOS::Obj> obj;
104 int r = get_mfa_obj(dpp, user, &obj);
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);
112 r = obj->operate(dpp, &op, y);
113 if (r < 0) {
114 ldpp_dout(dpp, 20) << "OTP create, otp_id=" << config.id << " result=" << (int)r << dendl;
115 return r;
116 }
117
118 return 0;
119}
120
121int RGWSI_Cls::MFA::remove_mfa(const DoutPrefixProvider *dpp,
122 const rgw_user& user, const string& id,
123 RGWObjVersionTracker *objv_tracker,
124 const ceph::real_time& mtime,
125 optional_yield y)
126{
127 std::optional<RGWSI_RADOS::Obj> obj;
128 int r = get_mfa_obj(dpp, user, &obj);
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);
136 r = obj->operate(dpp, &op, y);
137 if (r < 0) {
138 ldpp_dout(dpp, 20) << "OTP remove, otp_id=" << id << " result=" << (int)r << dendl;
139 return r;
140 }
141
142 return 0;
143}
144
145int RGWSI_Cls::MFA::get_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, const string& id, rados::cls::otp::otp_info_t *result,
146 optional_yield y)
147{
148 rgw_rados_ref ref;
149
150 int r = get_mfa_ref(dpp, user, &ref);
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
163int RGWSI_Cls::MFA::list_mfa(const DoutPrefixProvider *dpp, const rgw_user& user, list<rados::cls::otp::otp_info_t> *result,
164 optional_yield y)
165{
166 rgw_rados_ref ref;
167
168 int r = get_mfa_ref(dpp, user, &ref);
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
181int RGWSI_Cls::MFA::otp_get_current_time(const DoutPrefixProvider *dpp, const rgw_user& user, ceph::real_time *result,
182 optional_yield y)
183{
184 rgw_rados_ref ref;
185
186 int r = get_mfa_ref(dpp, user, &ref);
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
199int RGWSI_Cls::MFA::set_mfa(const DoutPrefixProvider *dpp, const string& oid, const list<rados::cls::otp::otp_info_t>& entries,
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);
206 int r = obj.open(dpp);
207 if (r < 0) {
208 ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl;
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);
219 r = obj.operate(dpp, &op, y);
220 if (r < 0) {
221 ldpp_dout(dpp, 20) << "OTP set entries.size()=" << entries.size() << " result=" << (int)r << dendl;
222 return r;
223 }
224
225 return 0;
226}
227
228int RGWSI_Cls::MFA::list_mfa(const DoutPrefixProvider *dpp, const string& oid, list<rados::cls::otp::otp_info_t> *result,
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);
234 int r = obj.open(dpp);
235 if (r < 0) {
236 ldpp_dout(dpp, 4) << "failed to open rados context for " << o << dendl;
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
266int RGWSI_Cls::TimeLog::init_obj(const DoutPrefixProvider *dpp, const string& oid, RGWSI_RADOS::Obj& obj)
267{
268 rgw_raw_obj o(zone_svc->get_zone_params().log_pool, oid);
269 obj = rados_svc->obj(o);
270 return obj.open(dpp);
271
272}
273int RGWSI_Cls::TimeLog::add(const DoutPrefixProvider *dpp,
274 const string& oid,
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
283 int r = init_obj(dpp, oid, obj);
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
292 return obj.operate(dpp, &op, y);
293}
294
295int RGWSI_Cls::TimeLog::add(const DoutPrefixProvider *dpp,
296 const string& oid,
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
304 int r = init_obj(dpp, oid, obj);
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) {
313 r = obj.operate(dpp, &op, y);
314 } else {
315 r = obj.aio_operate(completion, &op);
316 }
317 return r;
318}
319
320int RGWSI_Cls::TimeLog::list(const DoutPrefixProvider *dpp,
321 const string& oid,
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
332 int r = init_obj(dpp, oid, obj);
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
347 int ret = obj.operate(dpp, &op, &obl, y);
348 if (ret < 0)
349 return ret;
350
351 return 0;
352}
353
354int RGWSI_Cls::TimeLog::info(const DoutPrefixProvider *dpp,
355 const string& oid,
356 cls_log_header *header,
357 optional_yield y)
358{
359 RGWSI_RADOS::Obj obj;
360
361 int r = init_obj(dpp, oid, obj);
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
372 int ret = obj.operate(dpp, &op, &obl, y);
373 if (ret < 0)
374 return ret;
375
376 return 0;
377}
378
379int RGWSI_Cls::TimeLog::info_async(const DoutPrefixProvider *dpp,
380 RGWSI_RADOS::Obj& obj,
381 const string& oid,
382 cls_log_header *header,
383 librados::AioCompletion *completion)
384{
385 int r = init_obj(dpp, oid, obj);
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
401int RGWSI_Cls::TimeLog::trim(const DoutPrefixProvider *dpp,
402 const string& oid,
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
412 int r = init_obj(dpp, oid, obj);
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) {
424 r = obj.operate(dpp, &op, y);
425 } else {
426 r = obj.aio_operate(completion, &op);
427 }
428 return r;
429}
430
431int RGWSI_Cls::Lock::lock_exclusive(const DoutPrefixProvider *dpp,
432 const rgw_pool& pool,
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);
440 int r = p.open(dpp);
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
457int RGWSI_Cls::Lock::unlock(const DoutPrefixProvider *dpp,
458 const rgw_pool& pool,
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);
465 int r = p.open(dpp);
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