]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_role.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rgw / rgw_role.cc
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 }