]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_role.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / rgw / rgw_role.cc
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
11fdf7f2 3
7c673cae
FG
4#include <errno.h>
5#include <ctime>
11fdf7f2 6#include <regex>
39ae355f 7#include <boost/algorithm/string/replace.hpp>
31f18b77 8
7c673cae
FG
9#include "common/errno.h"
10#include "common/Formatter.h"
11#include "common/ceph_json.h"
12#include "common/ceph_time.h"
13#include "rgw_rados.h"
11fdf7f2 14#include "rgw_zone.h"
7c673cae
FG
15
16#include "include/types.h"
17#include "rgw_string.h"
18
19#include "rgw_common.h"
20#include "rgw_tools.h"
21#include "rgw_role.h"
22
11fdf7f2
TL
23#include "services/svc_zone.h"
24#include "services/svc_sys_obj.h"
39ae355f
TL
25#include "services/svc_meta_be_sobj.h"
26#include "services/svc_meta.h"
27#include "services/svc_role_rados.h"
11fdf7f2 28
7c673cae
FG
29#define dout_subsys ceph_subsys_rgw
30
20effc67
TL
31using namespace std;
32
33namespace rgw { namespace sal {
7c673cae
FG
34
35const string RGWRole::role_name_oid_prefix = "role_names.";
36const string RGWRole::role_oid_prefix = "roles.";
37const string RGWRole::role_path_oid_prefix = "role_paths.";
38const string RGWRole::role_arn_prefix = "arn:aws:iam::";
39
39ae355f
TL
40void RGWRoleInfo::dump(Formatter *f) const
41{
42 encode_json("RoleId", id , f);
43 std::string role_name;
44 if (tenant.empty()) {
45 role_name = name;
46 } else {
47 role_name = tenant + '$' + name;
48 }
49 encode_json("RoleName", role_name , f);
50 encode_json("Path", path, f);
51 encode_json("Arn", arn, f);
52 encode_json("CreateDate", creation_date, f);
53 encode_json("MaxSessionDuration", max_session_duration, f);
54 encode_json("AssumeRolePolicyDocument", trust_policy, f);
55 if (!perm_policy_map.empty()) {
56 f->open_array_section("PermissionPolicies");
57 for (const auto& it : perm_policy_map) {
58 f->open_object_section("Policy");
59 encode_json("PolicyName", it.first, f);
60 encode_json("PolicyValue", it.second, f);
61 f->close_section();
62 }
63 f->close_section();
64 }
65 if (!tags.empty()) {
66 f->open_array_section("Tags");
67 for (const auto& it : tags) {
68 f->open_object_section("Tag");
69 encode_json("Key", it.first, f);
70 encode_json("Value", it.second, f);
71 f->close_section();
72 }
73 f->close_section();
74 }
75}
76
77void RGWRoleInfo::decode_json(JSONObj *obj)
78{
79 JSONDecoder::decode_json("RoleId", id, obj);
80 JSONDecoder::decode_json("RoleName", name, obj);
81 JSONDecoder::decode_json("Path", path, obj);
82 JSONDecoder::decode_json("Arn", arn, obj);
83 JSONDecoder::decode_json("CreateDate", creation_date, obj);
84 JSONDecoder::decode_json("MaxSessionDuration", max_session_duration, obj);
85 JSONDecoder::decode_json("AssumeRolePolicyDocument", trust_policy, obj);
86
87 auto tags_iter = obj->find_first("Tags");
88 if (!tags_iter.end()) {
89 JSONObj* tags_json = *tags_iter;
90 auto iter = tags_json->find_first();
91
92 for (; !iter.end(); ++iter) {
93 std::string key, val;
94 JSONDecoder::decode_json("Key", key, *iter);
95 JSONDecoder::decode_json("Value", val, *iter);
96 this->tags.emplace(key, val);
97 }
98 }
99
100 auto perm_policy_iter = obj->find_first("PermissionPolicies");
101 if (!perm_policy_iter.end()) {
102 JSONObj* perm_policies = *perm_policy_iter;
103 auto iter = perm_policies->find_first();
104
105 for (; !iter.end(); ++iter) {
106 std::string policy_name, policy_val;
107 JSONDecoder::decode_json("PolicyName", policy_name, *iter);
108 JSONDecoder::decode_json("PolicyValue", policy_val, *iter);
109 this->perm_policy_map.emplace(policy_name, policy_val);
110 }
111 }
112
113 if (auto pos = name.find('$'); pos != std::string::npos) {
114 tenant = name.substr(0, pos);
115 name = name.substr(pos+1);
116 }
117}
118
119RGWRole::RGWRole(std::string name,
120 std::string tenant,
121 std::string path,
122 std::string trust_policy,
123 std::string max_session_duration_str,
124 std::multimap<std::string,std::string> tags)
125{
126 info.name = std::move(name);
127 info.path = std::move(path);
128 info.trust_policy = std::move(trust_policy);
129 info.tenant = std::move(tenant);
130 info.tags = std::move(tags);
131 if (this->info.path.empty())
132 this->info.path = "/";
133 extract_name_tenant(this->info.name);
134 if (max_session_duration_str.empty()) {
135 info.max_session_duration = SESSION_DURATION_MIN;
136 } else {
137 info.max_session_duration = std::stoull(max_session_duration_str);
138 }
139 info.mtime = real_time();
140}
141
142RGWRole::RGWRole(std::string id)
143{
144 info.id = std::move(id);
145}
146
b3b6e05e 147int RGWRole::get(const DoutPrefixProvider *dpp, optional_yield y)
7c673cae 148{
b3b6e05e 149 int ret = read_name(dpp, y);
7c673cae
FG
150 if (ret < 0) {
151 return ret;
152 }
153
b3b6e05e 154 ret = read_info(dpp, y);
7c673cae
FG
155 if (ret < 0) {
156 return ret;
157 }
158
159 return 0;
160}
161
b3b6e05e 162int RGWRole::get_by_id(const DoutPrefixProvider *dpp, optional_yield y)
31f18b77 163{
b3b6e05e 164 int ret = read_info(dpp, y);
31f18b77
FG
165 if (ret < 0) {
166 return ret;
167 }
168
169 return 0;
170}
171
39ae355f
TL
172void RGWRole::dump(Formatter *f) const
173{
174 info.dump(f);
175}
176
177void RGWRole::decode_json(JSONObj *obj)
178{
179 info.decode_json(obj);
180}
181
182bool RGWRole::validate_input(const DoutPrefixProvider* dpp)
183{
184 if (info.name.length() > MAX_ROLE_NAME_LEN) {
185 ldpp_dout(dpp, 0) << "ERROR: Invalid name length " << dendl;
186 return false;
187 }
188
189 if (info.path.length() > MAX_PATH_NAME_LEN) {
190 ldpp_dout(dpp, 0) << "ERROR: Invalid path length " << dendl;
191 return false;
192 }
193
194 std::regex regex_name("[A-Za-z0-9:=,.@-]+");
195 if (! std::regex_match(info.name, regex_name)) {
196 ldpp_dout(dpp, 0) << "ERROR: Invalid chars in name " << dendl;
197 return false;
198 }
199
200 std::regex regex_path("(/[!-~]+/)|(/)");
201 if (! std::regex_match(info.path,regex_path)) {
202 ldpp_dout(dpp, 0) << "ERROR: Invalid chars in path " << dendl;
203 return false;
204 }
205
206 if (info.max_session_duration < SESSION_DURATION_MIN ||
207 info.max_session_duration > SESSION_DURATION_MAX) {
208 ldpp_dout(dpp, 0) << "ERROR: Invalid session duration, should be between 3600 and 43200 seconds " << dendl;
209 return false;
210 }
211 return true;
212}
213
214void RGWRole::extract_name_tenant(const std::string& str) {
215 if (auto pos = str.find('$');
216 pos != std::string::npos) {
217 info.tenant = str.substr(0, pos);
218 info.name = str.substr(pos+1);
219 }
220}
221
b3b6e05e 222int RGWRole::update(const DoutPrefixProvider *dpp, optional_yield y)
7c673cae 223{
b3b6e05e 224 int ret = store_info(dpp, false, y);
7c673cae 225 if (ret < 0) {
20effc67 226 ldpp_dout(dpp, 0) << "ERROR: storing info in Role pool: "
39ae355f 227 << info.id << ": " << cpp_strerror(-ret) << dendl;
7c673cae
FG
228 return ret;
229 }
230
231 return 0;
232}
233
234void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy)
235{
39ae355f 236 info.perm_policy_map[policy_name] = perm_policy;
7c673cae
FG
237}
238
239vector<string> RGWRole::get_role_policy_names()
240{
241 vector<string> policy_names;
39ae355f 242 for (const auto& it : info.perm_policy_map)
7c673cae
FG
243 {
244 policy_names.push_back(std::move(it.first));
245 }
246
247 return policy_names;
248}
249
20effc67 250int RGWRole::get_role_policy(const DoutPrefixProvider* dpp, const string& policy_name, string& perm_policy)
7c673cae 251{
39ae355f
TL
252 const auto it = info.perm_policy_map.find(policy_name);
253 if (it == info.perm_policy_map.end()) {
20effc67 254 ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
92f5a8d4 255 return -ENOENT;
7c673cae
FG
256 } else {
257 perm_policy = it->second;
258 }
259 return 0;
260}
261
20effc67 262int RGWRole::delete_policy(const DoutPrefixProvider* dpp, const string& policy_name)
7c673cae 263{
39ae355f
TL
264 const auto& it = info.perm_policy_map.find(policy_name);
265 if (it == info.perm_policy_map.end()) {
20effc67 266 ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
7c673cae
FG
267 return -ENOENT;
268 } else {
39ae355f 269 info.perm_policy_map.erase(it);
7c673cae
FG
270 }
271 return 0;
272}
273
7c673cae
FG
274void RGWRole::update_trust_policy(string& trust_policy)
275{
39ae355f 276 this->info.trust_policy = trust_policy;
7c673cae
FG
277}
278
20effc67 279int RGWRole::set_tags(const DoutPrefixProvider* dpp, const multimap<string,string>& tags_map)
7c673cae 280{
20effc67 281 for (auto& it : tags_map) {
39ae355f 282 this->info.tags.emplace(it.first, it.second);
7c673cae 283 }
39ae355f 284 if (this->info.tags.size() > 50) {
20effc67
TL
285 ldpp_dout(dpp, 0) << "No. of tags is greater than 50" << dendl;
286 return -EINVAL;
287 }
288 return 0;
289}
7c673cae 290
20effc67
TL
291boost::optional<multimap<string,string>> RGWRole::get_tags()
292{
39ae355f 293 if(this->info.tags.empty()) {
20effc67 294 return boost::none;
7c673cae 295 }
39ae355f 296 return this->info.tags;
20effc67 297}
7c673cae 298
20effc67
TL
299void RGWRole::erase_tags(const vector<string>& tagKeys)
300{
301 for (auto& it : tagKeys) {
39ae355f 302 this->info.tags.erase(it);
20effc67 303 }
7c673cae
FG
304}
305
306const string& RGWRole::get_names_oid_prefix()
307{
308 return role_name_oid_prefix;
309}
310
311const string& RGWRole::get_info_oid_prefix()
312{
313 return role_oid_prefix;
314}
315
316const string& RGWRole::get_path_oid_prefix()
317{
318 return role_path_oid_prefix;
319}
20effc67 320
39ae355f
TL
321RGWRoleMetadataHandler::RGWRoleMetadataHandler(Store* store,
322 RGWSI_Role_RADOS *role_svc)
323{
324 this->store = store;
325 base_init(role_svc->ctx(), role_svc->get_be_handler());
326}
327
328RGWMetadataObject *RGWRoleMetadataHandler::get_meta_obj(JSONObj *jo,
329 const obj_version& objv,
330 const ceph::real_time& mtime)
331{
332 RGWRoleInfo info;
333
334 try {
335 info.decode_json(jo);
336 } catch (JSONDecoder:: err& e) {
337 return nullptr;
338 }
339
340 return new RGWRoleMetadataObject(info, objv, mtime, store);
341}
342
343int RGWRoleMetadataHandler::do_get(RGWSI_MetaBackend_Handler::Op *op,
344 std::string& entry,
345 RGWMetadataObject **obj,
346 optional_yield y,
347 const DoutPrefixProvider *dpp)
348{
349 std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(entry);
350 int ret = role->read_info(dpp, y);
351 if (ret < 0) {
352 return ret;
353 }
354
355 RGWObjVersionTracker objv_tracker = role->get_objv_tracker();
356 real_time mtime = role->get_mtime();
357
358 RGWRoleInfo info = role->get_info();
359 RGWRoleMetadataObject *rdo = new RGWRoleMetadataObject(info, objv_tracker.read_version,
360 mtime, store);
361 *obj = rdo;
362
363 return 0;
364}
365
366int RGWRoleMetadataHandler::do_remove(RGWSI_MetaBackend_Handler::Op *op,
367 std::string& entry,
368 RGWObjVersionTracker& objv_tracker,
369 optional_yield y,
370 const DoutPrefixProvider *dpp)
371{
372 std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(entry);
373 int ret = role->read_info(dpp, y);
374 if (ret < 0) {
375 return ret == -ENOENT? 0 : ret;
376 }
377
378 return role->delete_obj(dpp, y);
379}
380
381class RGWMetadataHandlerPut_Role : public RGWMetadataHandlerPut_SObj
382{
383 RGWRoleMetadataHandler *rhandler;
384 RGWRoleMetadataObject *mdo;
385public:
386 RGWMetadataHandlerPut_Role(RGWRoleMetadataHandler *handler,
387 RGWSI_MetaBackend_Handler::Op *op,
388 std::string& entry,
389 RGWMetadataObject *obj,
390 RGWObjVersionTracker& objv_tracker,
391 optional_yield y,
392 RGWMDLogSyncType type,
393 bool from_remote_zone) :
394 RGWMetadataHandlerPut_SObj(handler, op, entry, obj, objv_tracker, y, type, from_remote_zone),
395 rhandler(handler) {
396 mdo = static_cast<RGWRoleMetadataObject*>(obj);
397 }
398
399 int put_checked(const DoutPrefixProvider *dpp) override {
400 auto& info = mdo->get_role_info();
401 auto mtime = mdo->get_mtime();
402 auto* store = mdo->get_store();
403 info.mtime = mtime;
404 std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(info);
405 int ret = role->create(dpp, true, info.id, y);
406 if (ret == -EEXIST) {
407 ret = role->update(dpp, y);
408 }
409
410 return ret < 0 ? ret : STATUS_APPLIED;
411 }
412};
413
414int RGWRoleMetadataHandler::do_put(RGWSI_MetaBackend_Handler::Op *op,
415 std::string& entry,
416 RGWMetadataObject *obj,
417 RGWObjVersionTracker& objv_tracker,
418 optional_yield y,
419 const DoutPrefixProvider *dpp,
420 RGWMDLogSyncType type,
421 bool from_remote_zone)
422{
423 RGWMetadataHandlerPut_Role put_op(this, op , entry, obj, objv_tracker, y, type, from_remote_zone);
424 return do_put_operate(&put_op, dpp);
425}
426
20effc67 427} } // namespace rgw::sal