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