]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #include <errno.h> |
2 | #include <ctime> | |
3 | ||
4 | #include "common/errno.h" | |
5 | #include "common/Formatter.h" | |
6 | #include "common/ceph_json.h" | |
7 | #include "common/ceph_time.h" | |
8 | #include "rgw_rados.h" | |
9 | ||
10 | #include "include/types.h" | |
11 | #include "rgw_string.h" | |
12 | ||
13 | #include "rgw_common.h" | |
14 | #include "rgw_tools.h" | |
15 | #include "rgw_role.h" | |
16 | ||
17 | #define dout_subsys ceph_subsys_rgw | |
18 | ||
19 | using namespace std; | |
20 | ||
21 | const string RGWRole::role_name_oid_prefix = "role_names."; | |
22 | const string RGWRole::role_oid_prefix = "roles."; | |
23 | const string RGWRole::role_path_oid_prefix = "role_paths."; | |
24 | const string RGWRole::role_arn_prefix = "arn:aws:iam::"; | |
25 | ||
26 | int RGWRole::store_info(bool exclusive) | |
27 | { | |
28 | string oid = get_info_oid_prefix() + id; | |
29 | ||
30 | bufferlist bl; | |
31 | ::encode(*this, bl); | |
32 | return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, | |
33 | bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL); | |
34 | } | |
35 | ||
36 | int RGWRole::store_name(bool exclusive) | |
37 | { | |
38 | RGWNameToId nameToId; | |
39 | nameToId.obj_id = id; | |
40 | ||
41 | string oid = get_names_oid_prefix() + name; | |
42 | ||
43 | bufferlist bl; | |
44 | ::encode(nameToId, bl); | |
45 | return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, | |
46 | bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL); | |
47 | } | |
48 | ||
49 | int RGWRole::store_path(bool exclusive) | |
50 | { | |
51 | string oid = get_path_oid_prefix() + path + get_info_oid_prefix() + id; | |
52 | ||
53 | return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, | |
54 | NULL, 0, exclusive, NULL, real_time(), NULL); | |
55 | } | |
56 | ||
57 | int RGWRole::create(bool exclusive) | |
58 | { | |
59 | int ret; | |
60 | ||
61 | /* check to see the name is not used */ | |
62 | ret = read_id(name, id); | |
63 | if (exclusive && ret == 0) { | |
64 | ldout(cct, 0) << "ERROR: name " << name << " already in use for role id " | |
65 | << id << dendl; | |
66 | return -EEXIST; | |
67 | } else if ( ret < 0 && ret != -ENOENT) { | |
68 | ldout(cct, 0) << "failed reading role id " << id << ": " | |
69 | << cpp_strerror(-ret) << dendl; | |
70 | return ret; | |
71 | } | |
72 | ||
73 | /* create unique id */ | |
74 | uuid_d new_uuid; | |
75 | char uuid_str[37]; | |
76 | new_uuid.generate_random(); | |
77 | new_uuid.print(uuid_str); | |
78 | id = uuid_str; | |
79 | ||
80 | //arn | |
81 | arn = role_arn_prefix + uid + ":role" + path + name; | |
82 | ||
83 | // Creation time | |
84 | real_clock::time_point t = real_clock::now(); | |
85 | ||
86 | struct timeval tv; | |
87 | real_clock::to_timeval(t, tv); | |
88 | ||
89 | char buf[30]; | |
90 | struct tm result; | |
91 | gmtime_r(&tv.tv_sec, &result); | |
92 | strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result); | |
93 | sprintf(buf + strlen(buf),".%dZ",(int)tv.tv_usec/1000); | |
94 | creation_date.assign(buf, strlen(buf)); | |
95 | ||
96 | auto& pool = store->get_zone_params().roles_pool; | |
97 | ret = store_info(exclusive); | |
98 | if (ret < 0) { | |
99 | ldout(cct, 0) << "ERROR: storing role info in pool: " << pool.name << ": " | |
100 | << id << ": " << cpp_strerror(-ret) << dendl; | |
101 | return ret; | |
102 | } | |
103 | ||
104 | ret = store_name(exclusive); | |
105 | if (ret < 0) { | |
106 | ldout(cct, 0) << "ERROR: storing role name in pool: " << pool.name << ": " | |
107 | << name << ": " << cpp_strerror(-ret) << dendl; | |
108 | ||
109 | //Delete the role info that was stored in the previous call | |
110 | string oid = get_info_oid_prefix() + id; | |
111 | int info_ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
112 | if (info_ret < 0) { | |
113 | ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " | |
114 | << id << ": " << cpp_strerror(-info_ret) << dendl; | |
115 | } | |
116 | return ret; | |
117 | } | |
118 | ||
119 | ret = store_path(exclusive); | |
120 | if (ret < 0) { | |
121 | ldout(cct, 0) << "ERROR: storing role path in pool: " << pool.name << ": " | |
122 | << path << ": " << cpp_strerror(-ret) << dendl; | |
123 | //Delete the role info that was stored in the previous call | |
124 | string oid = get_info_oid_prefix() + id; | |
125 | int info_ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
126 | if (info_ret < 0) { | |
127 | ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " | |
128 | << id << ": " << cpp_strerror(-info_ret) << dendl; | |
129 | } | |
130 | //Delete role name that was stored in previous call | |
131 | oid = get_names_oid_prefix() + name; | |
132 | int name_ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
133 | if (name_ret < 0) { | |
134 | ldout(cct, 0) << "ERROR: cleanup of role name from pool: " << pool.name << ": " | |
135 | << name << ": " << cpp_strerror(-name_ret) << dendl; | |
136 | } | |
137 | return ret; | |
138 | } | |
139 | return 0; | |
140 | } | |
141 | ||
142 | int RGWRole::delete_obj() | |
143 | { | |
144 | auto& pool = store->get_zone_params().roles_pool; | |
145 | ||
146 | int ret = read_name(); | |
147 | if (ret < 0) { | |
148 | return ret; | |
149 | } | |
150 | ||
151 | ret = read_info(); | |
152 | if (ret < 0) { | |
153 | return ret; | |
154 | } | |
155 | ||
156 | if (! perm_policy_map.empty()) { | |
157 | return -ERR_DELETE_CONFLICT; | |
158 | } | |
159 | ||
160 | // Delete id | |
161 | string oid = get_info_oid_prefix() + id; | |
162 | ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
163 | if (ret < 0) { | |
164 | ldout(cct, 0) << "ERROR: deleting role id from pool: " << pool.name << ": " | |
165 | << id << ": " << cpp_strerror(-ret) << dendl; | |
166 | } | |
167 | ||
168 | // Delete name | |
169 | oid = get_names_oid_prefix() + name; | |
170 | ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
171 | if (ret < 0) { | |
172 | ldout(cct, 0) << "ERROR: deleting role name from pool: " << pool.name << ": " | |
173 | << name << ": " << cpp_strerror(-ret) << dendl; | |
174 | } | |
175 | ||
176 | // Delete path | |
177 | oid = get_path_oid_prefix() + path + get_info_oid_prefix() + id; | |
178 | ret = rgw_delete_system_obj(store, pool, oid, NULL); | |
179 | if (ret < 0) { | |
180 | ldout(cct, 0) << "ERROR: deleting role path from pool: " << pool.name << ": " | |
181 | << path << ": " << cpp_strerror(-ret) << dendl; | |
182 | } | |
183 | return ret; | |
184 | } | |
185 | ||
186 | int RGWRole::get() | |
187 | { | |
188 | int ret = read_name(); | |
189 | if (ret < 0) { | |
190 | return ret; | |
191 | } | |
192 | ||
193 | ret = read_info(); | |
194 | if (ret < 0) { | |
195 | return ret; | |
196 | } | |
197 | ||
198 | return 0; | |
199 | } | |
200 | ||
201 | int RGWRole::update() | |
202 | { | |
203 | auto& pool = store->get_zone_params().roles_pool; | |
204 | ||
205 | int ret = store_info(false); | |
206 | if (ret < 0) { | |
207 | ldout(cct, 0) << "ERROR: storing info in pool: " << pool.name << ": " | |
208 | << id << ": " << cpp_strerror(-ret) << dendl; | |
209 | return ret; | |
210 | } | |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
215 | void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy) | |
216 | { | |
217 | perm_policy_map[policy_name] = perm_policy; | |
218 | } | |
219 | ||
220 | vector<string> RGWRole::get_role_policy_names() | |
221 | { | |
222 | vector<string> policy_names; | |
223 | for (const auto& it : perm_policy_map) | |
224 | { | |
225 | policy_names.push_back(std::move(it.first)); | |
226 | } | |
227 | ||
228 | return policy_names; | |
229 | } | |
230 | ||
231 | int RGWRole::get_role_policy(const string& policy_name, string& perm_policy) | |
232 | { | |
233 | const auto it = perm_policy_map.find(policy_name); | |
234 | if (it == perm_policy_map.end()) { | |
235 | ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; | |
236 | return -EINVAL; | |
237 | } else { | |
238 | perm_policy = it->second; | |
239 | } | |
240 | return 0; | |
241 | } | |
242 | ||
243 | int RGWRole::delete_policy(const string& policy_name) | |
244 | { | |
245 | const auto& it = perm_policy_map.find(policy_name); | |
246 | if (it == perm_policy_map.end()) { | |
247 | ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; | |
248 | return -ENOENT; | |
249 | } else { | |
250 | perm_policy_map.erase(it); | |
251 | } | |
252 | return 0; | |
253 | } | |
254 | ||
255 | void RGWRole::dump(Formatter *f) const | |
256 | { | |
257 | encode_json("id", id , f); | |
258 | encode_json("name", name , f); | |
259 | encode_json("path", path, f); | |
260 | encode_json("arn", arn, f); | |
261 | encode_json("create_date", creation_date, f); | |
262 | encode_json("assume_role_policy_document", trust_policy, f); | |
263 | } | |
264 | ||
265 | void RGWRole::decode_json(JSONObj *obj) | |
266 | { | |
267 | JSONDecoder::decode_json("id", id, obj); | |
268 | JSONDecoder::decode_json("name", name, obj); | |
269 | JSONDecoder::decode_json("path", path, obj); | |
270 | JSONDecoder::decode_json("arn", arn, obj); | |
271 | JSONDecoder::decode_json("create_date", creation_date, obj); | |
272 | JSONDecoder::decode_json("assume_role_policy_document", trust_policy, obj); | |
273 | } | |
274 | ||
275 | int RGWRole::read_id(const string& role_name, string& role_id) | |
276 | { | |
277 | auto& pool = store->get_zone_params().roles_pool; | |
278 | string oid = get_names_oid_prefix() + role_name; | |
279 | bufferlist bl; | |
280 | RGWObjectCtx obj_ctx(store); | |
281 | ||
282 | int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); | |
283 | if (ret < 0) { | |
284 | return ret; | |
285 | } | |
286 | ||
287 | RGWNameToId nameToId; | |
288 | try { | |
289 | bufferlist::iterator iter = bl.begin(); | |
290 | ::decode(nameToId, iter); | |
291 | } catch (buffer::error& err) { | |
292 | ldout(cct, 0) << "ERROR: failed to decode role from pool: " << pool.name << ": " | |
293 | << role_name << dendl; | |
294 | return -EIO; | |
295 | } | |
296 | role_id = nameToId.obj_id; | |
297 | return 0; | |
298 | } | |
299 | ||
300 | int RGWRole::read_info() | |
301 | { | |
302 | auto& pool = store->get_zone_params().roles_pool; | |
303 | string oid = get_info_oid_prefix() + id; | |
304 | bufferlist bl; | |
305 | RGWObjectCtx obj_ctx(store); | |
306 | ||
307 | int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); | |
308 | if (ret < 0) { | |
309 | ldout(cct, 0) << "ERROR: failed reading role info from pool: " << pool.name << | |
310 | ": " << id << ": " << cpp_strerror(-ret) << dendl; | |
311 | return ret; | |
312 | } | |
313 | ||
314 | try { | |
315 | bufferlist::iterator iter = bl.begin(); | |
316 | ::decode(*this, iter); | |
317 | } catch (buffer::error& err) { | |
318 | ldout(cct, 0) << "ERROR: failed to decode role info from pool: " << pool.name << | |
319 | ": " << id << dendl; | |
320 | return -EIO; | |
321 | } | |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
326 | int RGWRole::read_name() | |
327 | { | |
328 | auto& pool = store->get_zone_params().roles_pool; | |
329 | string oid = get_names_oid_prefix() + name; | |
330 | bufferlist bl; | |
331 | RGWObjectCtx obj_ctx(store); | |
332 | ||
333 | int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); | |
334 | if (ret < 0) { | |
335 | ldout(cct, 0) << "ERROR: failed reading role name from pool: " << pool.name << ": " | |
336 | << name << ": " << cpp_strerror(-ret) << dendl; | |
337 | return ret; | |
338 | } | |
339 | ||
340 | RGWNameToId nameToId; | |
341 | try { | |
342 | bufferlist::iterator iter = bl.begin(); | |
343 | ::decode(nameToId, iter); | |
344 | } catch (buffer::error& err) { | |
345 | ldout(cct, 0) << "ERROR: failed to decode role name from pool: " << pool.name << ": " | |
346 | << name << dendl; | |
347 | return -EIO; | |
348 | } | |
349 | id = nameToId.obj_id; | |
350 | return 0; | |
351 | } | |
352 | ||
353 | void RGWRole::update_trust_policy(string& trust_policy) | |
354 | { | |
355 | this->trust_policy = trust_policy; | |
356 | } | |
357 | ||
358 | int RGWRole::get_roles_by_path_prefix(RGWRados *store, CephContext *cct, const string& path_prefix, vector<RGWRole>& roles) | |
359 | { | |
360 | auto pool = store->get_zone_params().roles_pool; | |
361 | string prefix; | |
362 | ||
363 | // List all roles if path prefix is empty | |
364 | if (! path_prefix.empty()) { | |
365 | prefix = role_path_oid_prefix + path_prefix; | |
366 | } else { | |
367 | prefix = role_path_oid_prefix; | |
368 | } | |
369 | ||
370 | //Get the filtered objects | |
371 | list<string> result; | |
372 | bool is_truncated; | |
373 | RGWListRawObjsCtx ctx; | |
374 | do { | |
375 | list<string> oids; | |
376 | int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); | |
377 | if (r < 0) { | |
378 | ldout(cct, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": " | |
379 | << prefix << ": " << cpp_strerror(-r) << dendl; | |
380 | return r; | |
381 | } | |
382 | for (const auto& iter : oids) { | |
383 | result.push_back(iter.substr(role_path_oid_prefix.size())); | |
384 | } | |
385 | } while (is_truncated); | |
386 | ||
387 | for (const auto& it : result) { | |
388 | //Find the role oid prefix from the end | |
389 | size_t pos = it.rfind(role_oid_prefix); | |
390 | if (pos == string::npos) { | |
391 | continue; | |
392 | } | |
393 | // Split the result into path and info_oid + id | |
394 | string path = it.substr(0, pos); | |
395 | ||
396 | /*Make sure that prefix is part of path (False results could've been returned) | |
397 | because of the role info oid + id appended to the path)*/ | |
398 | if(path_prefix.empty() || path.find(path_prefix) != string::npos) { | |
399 | //Get id from info oid prefix + id | |
400 | string id = it.substr(pos + role_oid_prefix.length()); | |
401 | ||
402 | RGWRole role(cct, store); | |
403 | role.set_id(id); | |
404 | int ret = role.read_info(); | |
405 | if (ret < 0) { | |
406 | return ret; | |
407 | } | |
408 | roles.push_back(std::move(role)); | |
409 | } | |
410 | } | |
411 | ||
412 | return 0; | |
413 | } | |
414 | ||
415 | const string& RGWRole::get_names_oid_prefix() | |
416 | { | |
417 | return role_name_oid_prefix; | |
418 | } | |
419 | ||
420 | const string& RGWRole::get_info_oid_prefix() | |
421 | { | |
422 | return role_oid_prefix; | |
423 | } | |
424 | ||
425 | const string& RGWRole::get_path_oid_prefix() | |
426 | { | |
427 | return role_path_oid_prefix; | |
428 | } |