]>
Commit | Line | Data |
---|---|---|
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 |
13 | bool 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 | ||
35 | bool subscription_has_endpoint_secret(const rgw_pubsub_sub_config& sub) { | |
36 | return sub.dest.stored_secret; | |
37 | } | |
38 | ||
39 | bool topic_has_endpoint_secret(const rgw_pubsub_topic_subs& topic) { | |
40 | return topic.topic.dest.stored_secret; | |
41 | } | |
42 | ||
f67539c2 | 43 | bool 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 | |
50 | void 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 |
65 | void 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 | 82 | void 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 | 101 | void 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 | 115 | void 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 | 130 | void 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 | 150 | void 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 | 165 | void 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 | 180 | void 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 | 201 | int 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 | 223 | int 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 | 242 | int 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 |