]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_arn.cc
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_arn.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "rgw_arn.h"
5 #include "rgw_common.h"
6 #include <regex>
7
8 namespace rgw {
9
10 namespace {
11 boost::optional<Partition> to_partition(const smatch::value_type& p,
12 bool wildcards) {
13 if (p == "aws") {
14 return Partition::aws;
15 } else if (p == "aws-cn") {
16 return Partition::aws_cn;
17 } else if (p == "aws-us-gov") {
18 return Partition::aws_us_gov;
19 } else if (p == "*" && wildcards) {
20 return Partition::wildcard;
21 } else {
22 return boost::none;
23 }
24
25 ceph_abort();
26 }
27
28 boost::optional<Service> to_service(const smatch::value_type& s,
29 bool wildcards) {
30 static const unordered_map<string, Service> services = {
31 { "acm", Service::acm },
32 { "apigateway", Service::apigateway },
33 { "appstream", Service::appstream },
34 { "artifact", Service::artifact },
35 { "autoscaling", Service::autoscaling },
36 { "aws-marketplace", Service::aws_marketplace },
37 { "aws-marketplace-management",
38 Service::aws_marketplace_management },
39 { "aws-portal", Service::aws_portal },
40 { "cloudformation", Service::cloudformation },
41 { "cloudfront", Service::cloudfront },
42 { "cloudhsm", Service::cloudhsm },
43 { "cloudsearch", Service::cloudsearch },
44 { "cloudtrail", Service::cloudtrail },
45 { "cloudwatch", Service::cloudwatch },
46 { "codebuild", Service::codebuild },
47 { "codecommit", Service::codecommit },
48 { "codedeploy", Service::codedeploy },
49 { "codepipeline", Service::codepipeline },
50 { "cognito-identity", Service::cognito_identity },
51 { "cognito-idp", Service::cognito_idp },
52 { "cognito-sync", Service::cognito_sync },
53 { "config", Service::config },
54 { "datapipeline", Service::datapipeline },
55 { "devicefarm", Service::devicefarm },
56 { "directconnect", Service::directconnect },
57 { "dms", Service::dms },
58 { "ds", Service::ds },
59 { "dynamodb", Service::dynamodb },
60 { "ec2", Service::ec2 },
61 { "ecr", Service::ecr },
62 { "ecs", Service::ecs },
63 { "elasticache", Service::elasticache },
64 { "elasticbeanstalk", Service::elasticbeanstalk },
65 { "elasticfilesystem", Service::elasticfilesystem },
66 { "elasticloadbalancing", Service::elasticloadbalancing },
67 { "elasticmapreduce", Service::elasticmapreduce },
68 { "elastictranscoder", Service::elastictranscoder },
69 { "es", Service::es },
70 { "events", Service::events },
71 { "firehose", Service::firehose },
72 { "gamelift", Service::gamelift },
73 { "glacier", Service::glacier },
74 { "health", Service::health },
75 { "iam", Service::iam },
76 { "importexport", Service::importexport },
77 { "inspector", Service::inspector },
78 { "iot", Service::iot },
79 { "kinesis", Service::kinesis },
80 { "kinesisanalytics", Service::kinesisanalytics },
81 { "kms", Service::kms },
82 { "lambda", Service::lambda },
83 { "lightsail", Service::lightsail },
84 { "logs", Service::logs },
85 { "machinelearning", Service::machinelearning },
86 { "mobileanalytics", Service::mobileanalytics },
87 { "mobilehub", Service::mobilehub },
88 { "opsworks", Service::opsworks },
89 { "opsworks-cm", Service::opsworks_cm },
90 { "polly", Service::polly },
91 { "rds", Service::rds },
92 { "redshift", Service::redshift },
93 { "route53", Service::route53 },
94 { "route53domains", Service::route53domains },
95 { "s3", Service::s3 },
96 { "sdb", Service::sdb },
97 { "servicecatalog", Service::servicecatalog },
98 { "ses", Service::ses },
99 { "sns", Service::sns },
100 { "sqs", Service::sqs },
101 { "ssm", Service::ssm },
102 { "states", Service::states },
103 { "storagegateway", Service::storagegateway },
104 { "sts", Service::sts },
105 { "support", Service::support },
106 { "swf", Service::swf },
107 { "trustedadvisor", Service::trustedadvisor },
108 { "waf", Service::waf },
109 { "workmail", Service::workmail },
110 { "workspaces", Service::workspaces }};
111
112 if (wildcards && s == "*") {
113 return Service::wildcard;
114 }
115
116 auto i = services.find(s);
117 if (i == services.end()) {
118 return boost::none;
119 } else {
120 return i->second;
121 }
122 }
123 }
124 ARN::ARN(const rgw_obj& o)
125 : partition(Partition::aws),
126 service(Service::s3),
127 region(),
128 account(o.bucket.tenant),
129 resource(o.bucket.name)
130 {
131 resource.push_back('/');
132 resource.append(o.key.name);
133 }
134
135 ARN::ARN(const rgw_bucket& b)
136 : partition(Partition::aws),
137 service(Service::s3),
138 region(),
139 account(b.tenant),
140 resource(b.name) { }
141
142 ARN::ARN(const rgw_bucket& b, const std::string& o)
143 : partition(Partition::aws),
144 service(Service::s3),
145 region(),
146 account(b.tenant),
147 resource(b.name) {
148 resource.push_back('/');
149 resource.append(o);
150 }
151
152 ARN::ARN(const std::string& resource_name, const std::string& type, const std::string& tenant, bool has_path)
153 : partition(Partition::aws),
154 service(Service::iam),
155 region(),
156 account(tenant),
157 resource(type) {
158 if (! has_path)
159 resource.push_back('/');
160 resource.append(resource_name);
161 }
162
163 boost::optional<ARN> ARN::parse(const std::string& s, bool wildcards) {
164 static const std::regex rx_wild("arn:([^:]*):([^:]*):([^:]*):([^:]*):([^:]*)",
165 std::regex_constants::ECMAScript |
166 std::regex_constants::optimize);
167 static const std::regex rx_no_wild(
168 "arn:([^:*]*):([^:*]*):([^:*]*):([^:*]*):(.*)",
169 std::regex_constants::ECMAScript |
170 std::regex_constants::optimize);
171
172 smatch match;
173
174 if ((s == "*") && wildcards) {
175 return ARN(Partition::wildcard, Service::wildcard, "*", "*", "*");
176 } else if (regex_match(s, match, wildcards ? rx_wild : rx_no_wild) &&
177 match.size() == 6) {
178 if (auto p = to_partition(match[1], wildcards)) {
179 if (auto s = to_service(match[2], wildcards)) {
180 return ARN(*p, *s, match[3], match[4], match[5]);
181 }
182 }
183 }
184 return boost::none;
185 }
186
187 std::string ARN::to_string() const {
188 std::string s{"arn:"};
189
190 if (partition == Partition::aws) {
191 s.append("aws:");
192 } else if (partition == Partition::aws_cn) {
193 s.append("aws-cn:");
194 } else if (partition == Partition::aws_us_gov) {
195 s.append("aws-us-gov:");
196 } else {
197 s.append("*:");
198 }
199
200 static const std::unordered_map<Service, string> services = {
201 { Service::acm, "acm" },
202 { Service::apigateway, "apigateway" },
203 { Service::appstream, "appstream" },
204 { Service::artifact, "artifact" },
205 { Service::autoscaling, "autoscaling" },
206 { Service::aws_marketplace, "aws-marketplace" },
207 { Service::aws_marketplace_management, "aws-marketplace-management" },
208 { Service::aws_portal, "aws-portal" },
209 { Service::cloudformation, "cloudformation" },
210 { Service::cloudfront, "cloudfront" },
211 { Service::cloudhsm, "cloudhsm" },
212 { Service::cloudsearch, "cloudsearch" },
213 { Service::cloudtrail, "cloudtrail" },
214 { Service::cloudwatch, "cloudwatch" },
215 { Service::codebuild, "codebuild" },
216 { Service::codecommit, "codecommit" },
217 { Service::codedeploy, "codedeploy" },
218 { Service::codepipeline, "codepipeline" },
219 { Service::cognito_identity, "cognito-identity" },
220 { Service::cognito_idp, "cognito-idp" },
221 { Service::cognito_sync, "cognito-sync" },
222 { Service::config, "config" },
223 { Service::datapipeline, "datapipeline" },
224 { Service::devicefarm, "devicefarm" },
225 { Service::directconnect, "directconnect" },
226 { Service::dms, "dms" },
227 { Service::ds, "ds" },
228 { Service::dynamodb, "dynamodb" },
229 { Service::ec2, "ec2" },
230 { Service::ecr, "ecr" },
231 { Service::ecs, "ecs" },
232 { Service::elasticache, "elasticache" },
233 { Service::elasticbeanstalk, "elasticbeanstalk" },
234 { Service::elasticfilesystem, "elasticfilesystem" },
235 { Service::elasticloadbalancing, "elasticloadbalancing" },
236 { Service::elasticmapreduce, "elasticmapreduce" },
237 { Service::elastictranscoder, "elastictranscoder" },
238 { Service::es, "es" },
239 { Service::events, "events" },
240 { Service::firehose, "firehose" },
241 { Service::gamelift, "gamelift" },
242 { Service::glacier, "glacier" },
243 { Service::health, "health" },
244 { Service::iam, "iam" },
245 { Service::importexport, "importexport" },
246 { Service::inspector, "inspector" },
247 { Service::iot, "iot" },
248 { Service::kinesis, "kinesis" },
249 { Service::kinesisanalytics, "kinesisanalytics" },
250 { Service::kms, "kms" },
251 { Service::lambda, "lambda" },
252 { Service::lightsail, "lightsail" },
253 { Service::logs, "logs" },
254 { Service::machinelearning, "machinelearning" },
255 { Service::mobileanalytics, "mobileanalytics" },
256 { Service::mobilehub, "mobilehub" },
257 { Service::opsworks, "opsworks" },
258 { Service::opsworks_cm, "opsworks-cm" },
259 { Service::polly, "polly" },
260 { Service::rds, "rds" },
261 { Service::redshift, "redshift" },
262 { Service::route53, "route53" },
263 { Service::route53domains, "route53domains" },
264 { Service::s3, "s3" },
265 { Service::sdb, "sdb" },
266 { Service::servicecatalog, "servicecatalog" },
267 { Service::ses, "ses" },
268 { Service::sns, "sns" },
269 { Service::sqs, "sqs" },
270 { Service::ssm, "ssm" },
271 { Service::states, "states" },
272 { Service::storagegateway, "storagegateway" },
273 { Service::sts, "sts" },
274 { Service::support, "support" },
275 { Service::swf, "swf" },
276 { Service::trustedadvisor, "trustedadvisor" },
277 { Service::waf, "waf" },
278 { Service::workmail, "workmail" },
279 { Service::workspaces, "workspaces" }};
280
281 auto i = services.find(service);
282 if (i != services.end()) {
283 s.append(i->second);
284 } else {
285 s.push_back('*');
286 }
287 s.push_back(':');
288
289 s.append(region);
290 s.push_back(':');
291
292 s.append(account);
293 s.push_back(':');
294
295 s.append(resource);
296
297 return s;
298 }
299
300 bool operator ==(const ARN& l, const ARN& r) {
301 return ((l.partition == r.partition) &&
302 (l.service == r.service) &&
303 (l.region == r.region) &&
304 (l.account == r.account) &&
305 (l.resource == r.resource));
306 }
307 bool operator <(const ARN& l, const ARN& r) {
308 return ((l.partition < r.partition) ||
309 (l.service < r.service) ||
310 (l.region < r.region) ||
311 (l.account < r.account) ||
312 (l.resource < r.resource));
313 }
314
315 // The candidate is not allowed to have wildcards. The only way to
316 // do that sanely would be to use unification rather than matching.
317 bool ARN::match(const ARN& candidate) const {
318 if ((candidate.partition == Partition::wildcard) ||
319 (partition != candidate.partition && partition
320 != Partition::wildcard)) {
321 return false;
322 }
323
324 if ((candidate.service == Service::wildcard) ||
325 (service != candidate.service && service != Service::wildcard)) {
326 return false;
327 }
328
329 if (!match_policy(region, candidate.region, MATCH_POLICY_ARN)) {
330 return false;
331 }
332
333 if (!match_policy(account, candidate.account, MATCH_POLICY_ARN)) {
334 return false;
335 }
336
337 if (!match_policy(resource, candidate.resource, MATCH_POLICY_RESOURCE)) {
338 return false;
339 }
340
341 return true;
342 }
343
344 boost::optional<ARNResource> ARNResource::parse(const std::string& s) {
345 static const std::regex rx("^([^:/]*)[:/]?([^:/]*)?[:/]?(.*)$",
346 std::regex_constants::ECMAScript |
347 std::regex_constants::optimize);
348 std::smatch match;
349 if (!regex_match(s, match, rx)) {
350 return boost::none;
351 }
352 if (match[2].str().empty() && match[3].str().empty()) {
353 // only resource exist
354 return rgw::ARNResource("", match[1], "");
355 }
356
357 // resource type also exist, and cannot be wildcard
358 if (match[1] != std::string(wildcard)) {
359 // resource type cannot be wildcard
360 return rgw::ARNResource(match[1], match[2], match[3]);
361 }
362
363 return boost::none;
364 }
365
366 std::string ARNResource::to_string() const {
367 std::string s;
368
369 if (!resource_type.empty()) {
370 s.append(resource_type);
371 s.push_back(':');
372
373 s.append(resource);
374 s.push_back(':');
375
376 s.append(qualifier);
377 } else {
378 s.append(resource);
379 }
380
381 return s;
382 }
383
384 }
385