aws_recon 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +12 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +1000 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +10 -0
- data/aws_recon.gemspec +36 -0
- data/bin/aws_recon +5 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/aws_recon.rb +19 -0
- data/lib/aws_recon/aws_recon.rb +115 -0
- data/lib/aws_recon/collectors/acm.rb +32 -0
- data/lib/aws_recon/collectors/apigateway.rb +50 -0
- data/lib/aws_recon/collectors/apigatewayv2.rb +37 -0
- data/lib/aws_recon/collectors/athena.rb +28 -0
- data/lib/aws_recon/collectors/autoscaling.rb +35 -0
- data/lib/aws_recon/collectors/cloudformation.rb +29 -0
- data/lib/aws_recon/collectors/cloudfront.rb +28 -0
- data/lib/aws_recon/collectors/cloudtrail.rb +33 -0
- data/lib/aws_recon/collectors/cloudwatch.rb +33 -0
- data/lib/aws_recon/collectors/cloudwatchlogs.rb +36 -0
- data/lib/aws_recon/collectors/codebuild.rb +29 -0
- data/lib/aws_recon/collectors/codepipeline.rb +27 -0
- data/lib/aws_recon/collectors/collectors.rb +2 -0
- data/lib/aws_recon/collectors/configservice.rb +80 -0
- data/lib/aws_recon/collectors/directconnect.rb +25 -0
- data/lib/aws_recon/collectors/directyservice.rb +27 -0
- data/lib/aws_recon/collectors/dms.rb +25 -0
- data/lib/aws_recon/collectors/dynamodb.rb +26 -0
- data/lib/aws_recon/collectors/ec2.rb +257 -0
- data/lib/aws_recon/collectors/ecr.rb +39 -0
- data/lib/aws_recon/collectors/ecs.rb +40 -0
- data/lib/aws_recon/collectors/efs.rb +25 -0
- data/lib/aws_recon/collectors/eks.rb +36 -0
- data/lib/aws_recon/collectors/elasticloadbalancing.rb +41 -0
- data/lib/aws_recon/collectors/elasticloadbalancingv2.rb +63 -0
- data/lib/aws_recon/collectors/elasticsearch.rb +27 -0
- data/lib/aws_recon/collectors/firehose.rb +29 -0
- data/lib/aws_recon/collectors/guardduty.rb +33 -0
- data/lib/aws_recon/collectors/iam.rb +136 -0
- data/lib/aws_recon/collectors/kafka.rb +27 -0
- data/lib/aws_recon/collectors/kinesis.rb +26 -0
- data/lib/aws_recon/collectors/kms.rb +71 -0
- data/lib/aws_recon/collectors/lambda.rb +42 -0
- data/lib/aws_recon/collectors/lightsail.rb +38 -0
- data/lib/aws_recon/collectors/organizations.rb +36 -0
- data/lib/aws_recon/collectors/rds.rb +81 -0
- data/lib/aws_recon/collectors/redshift.rb +40 -0
- data/lib/aws_recon/collectors/route53.rb +28 -0
- data/lib/aws_recon/collectors/route53domains.rb +25 -0
- data/lib/aws_recon/collectors/s3.rb +80 -0
- data/lib/aws_recon/collectors/sagemaker.rb +25 -0
- data/lib/aws_recon/collectors/servicequotas.rb +44 -0
- data/lib/aws_recon/collectors/ses.rb +28 -0
- data/lib/aws_recon/collectors/shield.rb +67 -0
- data/lib/aws_recon/collectors/sns.rb +38 -0
- data/lib/aws_recon/collectors/sqs.rb +28 -0
- data/lib/aws_recon/collectors/ssm.rb +41 -0
- data/lib/aws_recon/collectors/support.rb +43 -0
- data/lib/aws_recon/collectors/transfer.rb +24 -0
- data/lib/aws_recon/collectors/wafv2.rb +49 -0
- data/lib/aws_recon/collectors/workspaces.rb +24 -0
- data/lib/aws_recon/collectors/xray.rb +19 -0
- data/lib/aws_recon/lib/formatter.rb +32 -0
- data/lib/aws_recon/lib/mapper.rb +69 -0
- data/lib/aws_recon/options.rb +141 -0
- data/lib/aws_recon/services.yaml +134 -0
- data/lib/aws_recon/version.rb +3 -0
- data/readme.md +226 -0
- data/readme_gem.md +39 -0
- metadata +245 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
class Kafka < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
# TODO: test live
|
6
|
+
#
|
7
|
+
def collect
|
8
|
+
resources = []
|
9
|
+
|
10
|
+
#
|
11
|
+
# list_clusters
|
12
|
+
#
|
13
|
+
@client.list_clusters.each_with_index do |response, page|
|
14
|
+
log(response.context.operation_name, page)
|
15
|
+
|
16
|
+
response.cluster_info_list.each do |cluster|
|
17
|
+
struct = OpenStruct.new(cluster.to_h)
|
18
|
+
struct.type = 'cluster'
|
19
|
+
struct.arn = cluster.cluster_arn
|
20
|
+
|
21
|
+
resources.push(struct.to_h)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
resources
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Kinesis < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# list_streams
|
10
|
+
#
|
11
|
+
@client.list_streams.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
# describe_stream
|
15
|
+
response.stream_names.each do |stream|
|
16
|
+
struct = OpenStruct.new(@client.describe_stream({ stream_name: stream }).stream_description.to_h)
|
17
|
+
struct.type = 'stream'
|
18
|
+
struct.arn = struct.stream_arn
|
19
|
+
|
20
|
+
resources.push(struct.to_h)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
resources
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class KMS < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# list_keys
|
10
|
+
#
|
11
|
+
@client.list_keys.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
# describe_key
|
15
|
+
response.keys.each do |key|
|
16
|
+
log(response.context.operation_name, 'describe_key', page)
|
17
|
+
struct = OpenStruct.new(@client
|
18
|
+
.describe_key({ key_id: key.key_id })
|
19
|
+
.key_metadata.to_h)
|
20
|
+
struct.type = 'key'
|
21
|
+
struct.grants = []
|
22
|
+
|
23
|
+
# get_key_rotation_status
|
24
|
+
log(response.context.operation_name, 'get_key_rotation_status')
|
25
|
+
# The default master key rotation status can't be queried
|
26
|
+
begin
|
27
|
+
struct.rotation_enabled = @client
|
28
|
+
.get_key_rotation_status({ key_id: key.key_id })
|
29
|
+
.key_rotation_enabled
|
30
|
+
rescue Aws::KMS::Errors::ServiceError => e
|
31
|
+
log_error(e.code)
|
32
|
+
raise e unless suppressed_errors.include?(e.code)
|
33
|
+
end
|
34
|
+
|
35
|
+
# list_grants
|
36
|
+
@client.list_grants({ key_id: key.key_id }).each_with_index do |response, page|
|
37
|
+
log(response.context.operation_name, 'list_grants', page)
|
38
|
+
|
39
|
+
response.grants.each do |grant|
|
40
|
+
struct.grants.push(grant.to_h)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# get_key_policy - 'default' is the only valid policy
|
45
|
+
log(response.context.operation_name, 'get_key_policy')
|
46
|
+
struct.policy = @client
|
47
|
+
.get_key_policy({ key_id: key.key_id, policy_name: 'default' })
|
48
|
+
.policy
|
49
|
+
|
50
|
+
# list_aliases
|
51
|
+
log(response.context.operation_name, 'list_aliases')
|
52
|
+
struct.aliases = @client
|
53
|
+
.list_aliases({ key_id: key.key_id })
|
54
|
+
.aliases.map(&:to_h)
|
55
|
+
|
56
|
+
resources.push(struct.to_h)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
resources
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# not an error
|
66
|
+
def suppressed_errors
|
67
|
+
%w[
|
68
|
+
AccessDeniedException
|
69
|
+
]
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Lambda < Mapper
|
2
|
+
def collect
|
3
|
+
service = self.class.to_s.downcase
|
4
|
+
resources = []
|
5
|
+
|
6
|
+
#
|
7
|
+
# list_functions
|
8
|
+
#
|
9
|
+
@client.list_functions.each_with_index do |response, page|
|
10
|
+
log(response.context.operation_name, page)
|
11
|
+
|
12
|
+
response.functions.each do |function|
|
13
|
+
struct = OpenStruct.new(function)
|
14
|
+
struct.type = 'function'
|
15
|
+
struct.arn = function.function_arn
|
16
|
+
|
17
|
+
resources.push(struct.to_h)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# list_layers
|
23
|
+
#
|
24
|
+
@client.list_layers.each_with_index do |response, page|
|
25
|
+
log(response.context.operation_name, page)
|
26
|
+
|
27
|
+
response.layers.each do |layer|
|
28
|
+
struct = OpenStruct.new(layer)
|
29
|
+
struct.type = 'layer'
|
30
|
+
struct.arn = layer.layer_arn
|
31
|
+
|
32
|
+
# list_layer_versions
|
33
|
+
struct.versions = @client.list_layer_versions({ layer_name: layer.layer_name }).layer_versions.map(&:to_h)
|
34
|
+
log(response.context.operation_name, 'list_layer_versions')
|
35
|
+
|
36
|
+
resources.push(struct.to_h)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
resources
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Lightsail < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# get_instances
|
10
|
+
#
|
11
|
+
@client.get_instances.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
response.instances.each do |instance|
|
15
|
+
struct = OpenStruct.new(instance.to_h)
|
16
|
+
struct.type = 'instance'
|
17
|
+
|
18
|
+
resources.push(struct.to_h)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# get_load_balancers
|
24
|
+
#
|
25
|
+
@client.get_load_balancers.each_with_index do |response, page|
|
26
|
+
log(response.context.operation_name, page)
|
27
|
+
|
28
|
+
response.load_balancers.each do |load_balancer|
|
29
|
+
struct = OpenStruct.new(load_balancer.to_h)
|
30
|
+
struct.type = 'load_balancer'
|
31
|
+
|
32
|
+
resources.push(struct.to_h)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
resources
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Organizations < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# describe_organization
|
10
|
+
#
|
11
|
+
@client.describe_organization.each do |response|
|
12
|
+
log(response.context.operation_name)
|
13
|
+
|
14
|
+
struct = OpenStruct.new(response.organization.to_h)
|
15
|
+
struct.type = 'organization'
|
16
|
+
|
17
|
+
resources.push(struct.to_h)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# list_handshakes_for_account
|
22
|
+
#
|
23
|
+
@client.list_handshakes_for_account.each_with_index do |response, page|
|
24
|
+
log(response.context.operation_name, page)
|
25
|
+
|
26
|
+
response.handshakes.each do |handshake|
|
27
|
+
struct = OpenStruct.new(handshake.to_h)
|
28
|
+
struct.type = 'handshake'
|
29
|
+
|
30
|
+
resources.push(struct.to_h)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
resources
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class RDS < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
# describe_db_engine_versions is skipped with @options.skip_slow
|
6
|
+
#
|
7
|
+
def collect
|
8
|
+
resources = []
|
9
|
+
|
10
|
+
#
|
11
|
+
# describe_db_clusters
|
12
|
+
#
|
13
|
+
@client.describe_db_clusters.each_with_index do |response, page|
|
14
|
+
log(response.context.operation_name, page)
|
15
|
+
|
16
|
+
response.db_clusters.each do |cluster|
|
17
|
+
log(response.context.operation_name, cluster.db_cluster_identifier)
|
18
|
+
|
19
|
+
struct = OpenStruct.new(cluster.to_h)
|
20
|
+
struct.type = 'db_cluster'
|
21
|
+
struct.arn = cluster.db_cluster_arn
|
22
|
+
|
23
|
+
resources.push(struct.to_h)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# describe_db_instances
|
29
|
+
#
|
30
|
+
@client.describe_db_instances.each_with_index do |response, page|
|
31
|
+
log(response.context.operation_name, page)
|
32
|
+
|
33
|
+
response.db_instances.each do |instance|
|
34
|
+
log(response.context.operation_name, instance.db_instance_identifier)
|
35
|
+
|
36
|
+
struct = OpenStruct.new(instance.to_h)
|
37
|
+
struct.type = 'db_instance'
|
38
|
+
struct.arn = instance.db_instance_arn
|
39
|
+
struct.parent_id = instance.db_cluster_identifier
|
40
|
+
|
41
|
+
resources.push(struct.to_h)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# describe_db_snapshots
|
47
|
+
#
|
48
|
+
@client.describe_db_snapshots.each_with_index do |response, page|
|
49
|
+
log(response.context.operation_name, page)
|
50
|
+
|
51
|
+
response.db_snapshots.each do |snapshot|
|
52
|
+
log(response.context.operation_name, snapshot.db_snapshot_identifier)
|
53
|
+
|
54
|
+
struct = OpenStruct.new(snapshot.to_h)
|
55
|
+
struct.type = 'db_snapshot'
|
56
|
+
struct.arn = snapshot.db_snapshot_arn
|
57
|
+
struct.parent_id = snapshot.db_instance_identifier
|
58
|
+
|
59
|
+
resources.push(struct.to_h)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# describe_db_engine_versions
|
65
|
+
#
|
66
|
+
unless @options.skip_slow
|
67
|
+
@client.describe_db_engine_versions.each_with_index do |response, page|
|
68
|
+
log(response.context.operation_name, page)
|
69
|
+
|
70
|
+
response.db_engine_versions.each do |version|
|
71
|
+
struct = OpenStruct.new(version.to_h)
|
72
|
+
struct.type = 'db_engine_version'
|
73
|
+
|
74
|
+
resources.push(struct.to_h)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
resources
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Redshift < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# describe_clusters
|
10
|
+
#
|
11
|
+
@client.describe_clusters.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
response.clusters.each do |cluster|
|
15
|
+
struct = OpenStruct.new(cluster.to_h)
|
16
|
+
struct.type = 'cluster'
|
17
|
+
struct.arn = cluster.cluster_identifier
|
18
|
+
|
19
|
+
resources.push(struct.to_h)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# describe_cluster_subnet_groups
|
25
|
+
#
|
26
|
+
@client.describe_cluster_subnet_groups.each_with_index do |response, page|
|
27
|
+
log(response.context.operation_name, page)
|
28
|
+
|
29
|
+
response.cluster_subnet_groups.each do |group|
|
30
|
+
struct = OpenStruct.new(group.to_h)
|
31
|
+
struct.type = 'subnet_group'
|
32
|
+
struct.arn = group.cluster_subnet_group_name
|
33
|
+
|
34
|
+
resources.push(struct.to_h)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
resources
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Route53 < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# list_hosted_zones
|
10
|
+
#
|
11
|
+
@client.list_hosted_zones.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
response.hosted_zones.each do |zone|
|
15
|
+
struct = OpenStruct.new(zone.to_h)
|
16
|
+
struct.type = 'zone'
|
17
|
+
struct.arn = zone.id
|
18
|
+
struct.logging_config = @client
|
19
|
+
.list_query_logging_configs({ hosted_zone_id: zone.id })
|
20
|
+
.query_logging_configs.first.to_h
|
21
|
+
|
22
|
+
resources.push(struct.to_h)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
resources
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Route53Domains < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
def collect
|
6
|
+
resources = []
|
7
|
+
|
8
|
+
#
|
9
|
+
# list_domains
|
10
|
+
#
|
11
|
+
@client.list_domains.each_with_index do |response, page|
|
12
|
+
log(response.context.operation_name, page)
|
13
|
+
|
14
|
+
response.domains.each do |domain|
|
15
|
+
struct = OpenStruct.new(domain.to_h)
|
16
|
+
struct.type = 'domain'
|
17
|
+
struct.arn = "arn:aws:#{@service}:#{@region}::domain/#{domain.domain_name}"
|
18
|
+
|
19
|
+
resources.push(struct.to_h)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
resources
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class S3 < Mapper
|
2
|
+
#
|
3
|
+
# Returns an array of resources.
|
4
|
+
#
|
5
|
+
# Since S3 is a global service, the bucket operation calls
|
6
|
+
# can be parallelized.
|
7
|
+
#
|
8
|
+
def collect
|
9
|
+
resources = []
|
10
|
+
|
11
|
+
#
|
12
|
+
# list_buckets
|
13
|
+
#
|
14
|
+
@client.list_buckets.each_with_index do |response, page|
|
15
|
+
log(response.context.operation_name, page)
|
16
|
+
|
17
|
+
Parallel.map(response.buckets.each, in_threads: @options.threads) do |bucket|
|
18
|
+
# use shared client instance
|
19
|
+
client = @client
|
20
|
+
@thread = Parallel.worker_number
|
21
|
+
log(response.context.operation_name, bucket.name)
|
22
|
+
|
23
|
+
struct = OpenStruct.new(bucket)
|
24
|
+
struct.type = 'bucket'
|
25
|
+
struct.arn = "arn:aws:s3:::#{bucket.name}"
|
26
|
+
|
27
|
+
# check bucket region constraint
|
28
|
+
location = @client.get_bucket_location({ bucket: bucket.name }).location_constraint
|
29
|
+
|
30
|
+
# reset client if needed
|
31
|
+
unless location.empty?
|
32
|
+
client = Aws::S3::Client.new({ region: location })
|
33
|
+
end
|
34
|
+
|
35
|
+
operations = [
|
36
|
+
{ func: 'get_bucket_acl', key: 'acl', field: nil },
|
37
|
+
{ func: 'get_bucket_encryption', key: 'encryption', field: 'server_side_encryption_configuration' },
|
38
|
+
{ func: 'get_bucket_policy', key: 'policy', field: 'policy' },
|
39
|
+
{ func: 'get_bucket_policy_status', key: 'public', field: 'policy_status' },
|
40
|
+
{ func: 'get_bucket_tagging', key: 'tagging', field: nil },
|
41
|
+
{ func: 'get_bucket_logging', key: 'logging', field: 'logging_enabled' },
|
42
|
+
{ func: 'get_bucket_versioning', key: 'versioning', field: nil },
|
43
|
+
{ func: 'get_bucket_website', key: 'website', field: nil }
|
44
|
+
]
|
45
|
+
|
46
|
+
operations.each do |operation|
|
47
|
+
op = OpenStruct.new(operation)
|
48
|
+
|
49
|
+
resp = client.send(op.func, { bucket: bucket.name })
|
50
|
+
|
51
|
+
struct[op.key] = if op.key == 'policy'
|
52
|
+
resp.policy.string
|
53
|
+
else
|
54
|
+
op.field ? resp.send(op.field).to_h : resp.to_h
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue Aws::S3::Errors::ServiceError => e
|
58
|
+
raise e unless suppressed_errors.include?(e.code)
|
59
|
+
end
|
60
|
+
|
61
|
+
resources.push(struct.to_h)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
resources
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# not an error
|
71
|
+
def suppressed_errors
|
72
|
+
%w[
|
73
|
+
AccessDenied
|
74
|
+
ServerSideEncryptionConfigurationNotFoundError
|
75
|
+
NoSuchBucketPolicy
|
76
|
+
NoSuchTagSet
|
77
|
+
NoSuchWebsiteConfiguration
|
78
|
+
]
|
79
|
+
end
|
80
|
+
end
|