]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_pubsub_common.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / rgw / rgw_rest_pubsub_common.cc
CommitLineData
eafe8130
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
9f95a23c 4#include "rgw_common.h"
eafe8130
TL
5#include "rgw_rest_pubsub_common.h"
6#include "common/dout.h"
9f95a23c 7#include "rgw_url.h"
f67539c2 8#include "rgw_sal_rados.h"
eafe8130
TL
9
10#define dout_context g_ceph_context
11#define dout_subsys ceph_subsys_rgw
12
9f95a23c
TL
13bool validate_and_update_endpoint_secret(rgw_pubsub_sub_dest& dest, CephContext *cct, const RGWEnv& env) {
14 if (dest.push_endpoint.empty()) {
15 return true;
16 }
17 std::string user;
18 std::string password;
19 if (!rgw::parse_url_userinfo(dest.push_endpoint, user, password)) {
20 ldout(cct, 1) << "endpoint validation error: malformed endpoint URL:" << dest.push_endpoint << dendl;
21 return false;
22 }
23 // this should be verified inside parse_url()
24 ceph_assert(user.empty() == password.empty());
25 if (!user.empty()) {
26 dest.stored_secret = true;
27 if (!rgw_transport_is_secure(cct, env)) {
28 ldout(cct, 1) << "endpoint validation error: sending password over insecure transport" << dendl;
29 return false;
30 }
31 }
32 return true;
33}
34
35bool subscription_has_endpoint_secret(const rgw_pubsub_sub_config& sub) {
36 return sub.dest.stored_secret;
37}
38
39bool topic_has_endpoint_secret(const rgw_pubsub_topic_subs& topic) {
40 return topic.topic.dest.stored_secret;
41}
42
f67539c2 43bool topics_has_endpoint_secret(const rgw_pubsub_topics& topics) {
9f95a23c
TL
44 for (const auto& topic : topics.topics) {
45 if (topic_has_endpoint_secret(topic.second)) return true;
46 }
47 return false;
48}
f67539c2
TL
49
50void RGWPSCreateTopicOp::execute(optional_yield y) {
eafe8130
TL
51 op_ret = get_params();
52 if (op_ret < 0) {
53 return;
54 }
55
f67539c2 56 ps.emplace(store, s->owner.get_id().tenant);
b3b6e05e 57 op_ret = ps->create_topic(this, topic_name, dest, topic_arn, opaque_data, y);
eafe8130 58 if (op_ret < 0) {
b3b6e05e 59 ldpp_dout(this, 1) << "failed to create topic '" << topic_name << "', ret=" << op_ret << dendl;
eafe8130
TL
60 return;
61 }
b3b6e05e 62 ldpp_dout(this, 20) << "successfully created topic '" << topic_name << "'" << dendl;
eafe8130
TL
63}
64
f67539c2
TL
65void RGWPSListTopicsOp::execute(optional_yield y) {
66 ps.emplace(store, s->owner.get_id().tenant);
67 op_ret = ps->get_topics(&result);
9f95a23c
TL
68 // if there are no topics it is not considered an error
69 op_ret = op_ret == -ENOENT ? 0 : op_ret;
eafe8130 70 if (op_ret < 0) {
b3b6e05e 71 ldpp_dout(this, 1) << "failed to get topics, ret=" << op_ret << dendl;
eafe8130
TL
72 return;
73 }
9f95a23c 74 if (topics_has_endpoint_secret(result) && !rgw_transport_is_secure(s->cct, *(s->info.env))) {
b3b6e05e 75 ldpp_dout(this, 1) << "topics contain secret and cannot be sent over insecure transport" << dendl;
9f95a23c
TL
76 op_ret = -EPERM;
77 return;
78 }
b3b6e05e 79 ldpp_dout(this, 20) << "successfully got topics" << dendl;
eafe8130
TL
80}
81
f67539c2 82void RGWPSGetTopicOp::execute(optional_yield y) {
eafe8130
TL
83 op_ret = get_params();
84 if (op_ret < 0) {
85 return;
86 }
f67539c2
TL
87 ps.emplace(store, s->owner.get_id().tenant);
88 op_ret = ps->get_topic(topic_name, &result);
9f95a23c 89 if (topic_has_endpoint_secret(result) && !rgw_transport_is_secure(s->cct, *(s->info.env))) {
b3b6e05e 90 ldpp_dout(this, 1) << "topic '" << topic_name << "' contain secret and cannot be sent over insecure transport" << dendl;
9f95a23c
TL
91 op_ret = -EPERM;
92 return;
93 }
eafe8130 94 if (op_ret < 0) {
b3b6e05e 95 ldpp_dout(this, 1) << "failed to get topic '" << topic_name << "', ret=" << op_ret << dendl;
eafe8130
TL
96 return;
97 }
b3b6e05e 98 ldpp_dout(this, 1) << "successfully got topic '" << topic_name << "'" << dendl;
eafe8130
TL
99}
100
f67539c2 101void RGWPSDeleteTopicOp::execute(optional_yield y) {
eafe8130
TL
102 op_ret = get_params();
103 if (op_ret < 0) {
104 return;
105 }
f67539c2 106 ps.emplace(store, s->owner.get_id().tenant);
b3b6e05e 107 op_ret = ps->remove_topic(this, topic_name, y);
eafe8130 108 if (op_ret < 0) {
b3b6e05e 109 ldpp_dout(this, 1) << "failed to remove topic '" << topic_name << ", ret=" << op_ret << dendl;
eafe8130
TL
110 return;
111 }
b3b6e05e 112 ldpp_dout(this, 1) << "successfully removed topic '" << topic_name << "'" << dendl;
eafe8130
TL
113}
114
f67539c2 115void RGWPSCreateSubOp::execute(optional_yield y) {
eafe8130
TL
116 op_ret = get_params();
117 if (op_ret < 0) {
118 return;
119 }
f67539c2
TL
120 ps.emplace(store, s->owner.get_id().tenant);
121 auto sub = ps->get_sub(sub_name);
b3b6e05e 122 op_ret = sub->subscribe(this, topic_name, dest, y);
eafe8130 123 if (op_ret < 0) {
b3b6e05e 124 ldpp_dout(this, 1) << "failed to create subscription '" << sub_name << "', ret=" << op_ret << dendl;
eafe8130
TL
125 return;
126 }
b3b6e05e 127 ldpp_dout(this, 20) << "successfully created subscription '" << sub_name << "'" << dendl;
eafe8130
TL
128}
129
f67539c2 130void RGWPSGetSubOp::execute(optional_yield y) {
eafe8130
TL
131 op_ret = get_params();
132 if (op_ret < 0) {
133 return;
134 }
f67539c2
TL
135 ps.emplace(store, s->owner.get_id().tenant);
136 auto sub = ps->get_sub(sub_name);
eafe8130 137 op_ret = sub->get_conf(&result);
9f95a23c 138 if (subscription_has_endpoint_secret(result) && !rgw_transport_is_secure(s->cct, *(s->info.env))) {
b3b6e05e 139 ldpp_dout(this, 1) << "subscription '" << sub_name << "' contain secret and cannot be sent over insecure transport" << dendl;
9f95a23c
TL
140 op_ret = -EPERM;
141 return;
142 }
eafe8130 143 if (op_ret < 0) {
b3b6e05e 144 ldpp_dout(this, 1) << "failed to get subscription '" << sub_name << "', ret=" << op_ret << dendl;
eafe8130
TL
145 return;
146 }
b3b6e05e 147 ldpp_dout(this, 20) << "successfully got subscription '" << sub_name << "'" << dendl;
eafe8130
TL
148}
149
f67539c2 150void RGWPSDeleteSubOp::execute(optional_yield y) {
eafe8130
TL
151 op_ret = get_params();
152 if (op_ret < 0) {
153 return;
154 }
f67539c2
TL
155 ps.emplace(store, s->owner.get_id().tenant);
156 auto sub = ps->get_sub(sub_name);
b3b6e05e 157 op_ret = sub->unsubscribe(this, topic_name, y);
eafe8130 158 if (op_ret < 0) {
b3b6e05e 159 ldpp_dout(this, 1) << "failed to remove subscription '" << sub_name << "', ret=" << op_ret << dendl;
eafe8130
TL
160 return;
161 }
b3b6e05e 162 ldpp_dout(this, 20) << "successfully removed subscription '" << sub_name << "'" << dendl;
eafe8130
TL
163}
164
f67539c2 165void RGWPSAckSubEventOp::execute(optional_yield y) {
eafe8130
TL
166 op_ret = get_params();
167 if (op_ret < 0) {
168 return;
169 }
f67539c2
TL
170 ps.emplace(store, s->owner.get_id().tenant);
171 auto sub = ps->get_sub_with_events(sub_name);
b3b6e05e 172 op_ret = sub->remove_event(s, event_id);
eafe8130 173 if (op_ret < 0) {
b3b6e05e 174 ldpp_dout(this, 1) << "failed to ack event on subscription '" << sub_name << "', ret=" << op_ret << dendl;
eafe8130
TL
175 return;
176 }
b3b6e05e 177 ldpp_dout(this, 20) << "successfully acked event on subscription '" << sub_name << "'" << dendl;
eafe8130
TL
178}
179
f67539c2 180void RGWPSPullSubEventsOp::execute(optional_yield y) {
eafe8130
TL
181 op_ret = get_params();
182 if (op_ret < 0) {
183 return;
184 }
f67539c2
TL
185 ps.emplace(store, s->owner.get_id().tenant);
186 sub = ps->get_sub_with_events(sub_name);
eafe8130
TL
187 if (!sub) {
188 op_ret = -ENOENT;
b3b6e05e 189 ldpp_dout(this, 1) << "failed to get subscription '" << sub_name << "' for events, ret=" << op_ret << dendl;
eafe8130
TL
190 return;
191 }
b3b6e05e 192 op_ret = sub->list_events(s, marker, max_entries);
eafe8130 193 if (op_ret < 0) {
b3b6e05e 194 ldpp_dout(this, 1) << "failed to get events from subscription '" << sub_name << "', ret=" << op_ret << dendl;
eafe8130
TL
195 return;
196 }
b3b6e05e 197 ldpp_dout(this, 20) << "successfully got events from subscription '" << sub_name << "'" << dendl;
eafe8130
TL
198}
199
200
f67539c2 201int RGWPSCreateNotifOp::verify_permission(optional_yield y) {
eafe8130
TL
202 int ret = get_params();
203 if (ret < 0) {
204 return ret;
205 }
206
207 const auto& id = s->owner.get_id();
208
9f95a23c 209 ret = store->getRados()->get_bucket_info(store->svc(), id.tenant, bucket_name,
f67539c2 210 bucket_info, nullptr, y, nullptr);
eafe8130 211 if (ret < 0) {
b3b6e05e 212 ldpp_dout(this, 1) << "failed to get bucket info, cannot verify ownership" << dendl;
eafe8130
TL
213 return ret;
214 }
215
216 if (bucket_info.owner != id) {
b3b6e05e 217 ldpp_dout(this, 1) << "user doesn't own bucket, not allowed to create notification" << dendl;
eafe8130
TL
218 return -EPERM;
219 }
220 return 0;
221}
222
f67539c2 223int RGWPSDeleteNotifOp::verify_permission(optional_yield y) {
eafe8130
TL
224 int ret = get_params();
225 if (ret < 0) {
226 return ret;
227 }
228
9f95a23c 229 ret = store->getRados()->get_bucket_info(store->svc(), s->owner.get_id().tenant, bucket_name,
f67539c2 230 bucket_info, nullptr, y, nullptr);
eafe8130
TL
231 if (ret < 0) {
232 return ret;
233 }
234
235 if (bucket_info.owner != s->owner.get_id()) {
b3b6e05e 236 ldpp_dout(this, 1) << "user doesn't own bucket, cannot remove notification" << dendl;
eafe8130
TL
237 return -EPERM;
238 }
239 return 0;
240}
241
f67539c2 242int RGWPSListNotifsOp::verify_permission(optional_yield y) {
eafe8130
TL
243 int ret = get_params();
244 if (ret < 0) {
245 return ret;
246 }
247
9f95a23c 248 ret = store->getRados()->get_bucket_info(store->svc(), s->owner.get_id().tenant, bucket_name,
f67539c2 249 bucket_info, nullptr, y, nullptr);
eafe8130
TL
250 if (ret < 0) {
251 return ret;
252 }
253
254 if (bucket_info.owner != s->owner.get_id()) {
b3b6e05e 255 ldpp_dout(this, 1) << "user doesn't own bucket, cannot get notification list" << dendl;
eafe8130
TL
256 return -EPERM;
257 }
258
259 return 0;
260}
261