1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 #include "rgw_common.h"
13 boost::optional
<Partition
> to_partition(const smatch::value_type
& p
,
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
;
30 boost::optional
<Service
> to_service(const smatch::value_type
& s
,
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
}};
114 if (wildcards
&& s
== "*") {
115 return Service::wildcard
;
118 auto i
= services
.find(s
);
119 if (i
== services
.end()) {
126 ARN::ARN(const rgw_obj
& o
)
127 : partition(Partition::aws
),
128 service(Service::s3
),
130 account(o
.bucket
.tenant
),
131 resource(o
.bucket
.name
)
133 resource
.push_back('/');
134 resource
.append(o
.key
.name
);
137 ARN::ARN(const rgw_bucket
& b
)
138 : partition(Partition::aws
),
139 service(Service::s3
),
144 ARN::ARN(const rgw_bucket
& b
, const std::string
& o
)
145 : partition(Partition::aws
),
146 service(Service::s3
),
150 resource
.push_back('/');
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
),
161 resource
.push_back('/');
162 resource
.append(resource_name
);
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
);
176 if ((s
== "*") && wildcards
) {
177 return ARN(Partition::wildcard
, Service::wildcard
, "*", "*", "*");
178 } else if (regex_match(s
, match
, wildcards
? rx_wild
: rx_no_wild
) &&
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]);
189 std::string
ARN::to_string() const {
190 std::string s
{"arn:"};
192 if (partition
== Partition::aws
) {
194 } else if (partition
== Partition::aws_cn
) {
196 } else if (partition
== Partition::aws_us_gov
) {
197 s
.append("aws-us-gov:");
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" }};
283 auto i
= services
.find(service
);
284 if (i
!= services
.end()) {
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
));
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
));
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
)) {
326 if ((candidate
.service
== Service::wildcard
) ||
327 (service
!= candidate
.service
&& service
!= Service::wildcard
)) {
331 if (!match_policy(region
, candidate
.region
, MATCH_POLICY_ARN
)) {
335 if (!match_policy(account
, candidate
.account
, MATCH_POLICY_ARN
)) {
339 if (!match_policy(resource
, candidate
.resource
, MATCH_POLICY_RESOURCE
)) {
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
);
351 if (!regex_match(s
, match
, rx
)) {
354 if (match
[2].str().empty() && match
[3].str().empty()) {
355 // only resource exist
356 return rgw::ARNResource("", match
[1], "");
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]);
368 std::string
ARNResource::to_string() const {
371 if (!resource_type
.empty()) {
372 s
.append(resource_type
);