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"
11 boost::optional
<Partition
> to_partition(const smatch::value_type
& p
,
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
;
28 boost::optional
<Service
> to_service(const smatch::value_type
& s
,
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
}};
112 if (wildcards
&& s
== "*") {
113 return Service::wildcard
;
116 auto i
= services
.find(s
);
117 if (i
== services
.end()) {
124 ARN::ARN(const rgw_obj
& o
)
125 : partition(Partition::aws
),
126 service(Service::s3
),
128 account(o
.bucket
.tenant
),
129 resource(o
.bucket
.name
)
131 resource
.push_back('/');
132 resource
.append(o
.key
.name
);
135 ARN::ARN(const rgw_bucket
& b
)
136 : partition(Partition::aws
),
137 service(Service::s3
),
142 ARN::ARN(const rgw_bucket
& b
, const std::string
& o
)
143 : partition(Partition::aws
),
144 service(Service::s3
),
148 resource
.push_back('/');
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
),
159 resource
.push_back('/');
160 resource
.append(resource_name
);
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
);
174 if ((s
== "*") && wildcards
) {
175 return ARN(Partition::wildcard
, Service::wildcard
, "*", "*", "*");
176 } else if (regex_match(s
, match
, wildcards
? rx_wild
: rx_no_wild
) &&
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]);
187 std::string
ARN::to_string() const {
188 std::string s
{"arn:"};
190 if (partition
== Partition::aws
) {
192 } else if (partition
== Partition::aws_cn
) {
194 } else if (partition
== Partition::aws_us_gov
) {
195 s
.append("aws-us-gov:");
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" }};
281 auto i
= services
.find(service
);
282 if (i
!= services
.end()) {
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
));
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
));
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
)) {
324 if ((candidate
.service
== Service::wildcard
) ||
325 (service
!= candidate
.service
&& service
!= Service::wildcard
)) {
329 if (!match_policy(region
, candidate
.region
, MATCH_POLICY_ARN
)) {
333 if (!match_policy(account
, candidate
.account
, MATCH_POLICY_ARN
)) {
337 if (!match_policy(resource
, candidate
.resource
, MATCH_POLICY_RESOURCE
)) {
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
);
349 if (!regex_match(s
, match
, rx
)) {
352 if (match
[2].str().empty() && match
[3].str().empty()) {
353 // only resource exist
354 return rgw::ARNResource("", match
[1], "");
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]);
366 std::string
ARNResource::to_string() const {
369 if (!resource_type
.empty()) {
370 s
.append(resource_type
);