]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_arn.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_arn.cc
CommitLineData
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
8using namespace std;
9
eafe8130
TL
10namespace rgw {
11
12namespace {
13boost::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
30boost::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}
126ARN::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
137ARN::ARN(const rgw_bucket& b)
138 : partition(Partition::aws),
139 service(Service::s3),
140 region(),
141 account(b.tenant),
142 resource(b.name) { }
143
144ARN::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
154ARN::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
165boost::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
189std::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
302bool 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}
309bool 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.
319bool 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
346boost::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
368std::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