aws_recon 0.4.4 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48ccf03d964fff678dc732fcf74d4dcd9c7c06293845bbb9a4f54e9e1ce61a24
4
- data.tar.gz: 7c39747a7845fe497be052baae41af8ee45014166d97114abb797d5f6c06e5b9
3
+ metadata.gz: 7481b13d21571402935b0ce2b67a7cdaaf3d3fc245b49f5569ab249b00a80769
4
+ data.tar.gz: d755e86dbe27036c6db5aec7a10497f1cf85c4ad64265f673ec10fd1490d9566
5
5
  SHA512:
6
- metadata.gz: 3b6c26ff3b38dd58c63313b70a609e6b08fe6d16762afb9651bbc81d6cef21d7c46e8b11ad73d40caf0e6abbfd877ef5d5f2fde1536425b70a25afe82b7a4a78
7
- data.tar.gz: a74af8ad1b868895d997110a4688bc88266536ad2187c235ba27a0720e3ccce0d18d6959981ab3e82e40bb738944d1402380761f9c3c65ce33cc1649bfddbc4e
6
+ metadata.gz: a97a2b0b84fd34a79be57dac06caefa77231a7098d2ee221e3d6587d57c51aa181aff4aefeb13bfcfd52578b2f30285ce3e1a2f5f70ed8cff6c37d426f2daaa4
7
+ data.tar.gz: 7fdab7b7ddebb23fd28d28721966ff1d29a7b3a07c351e6319d3c6cdeb08fc4788869b8c30e2ea5f38a180bfe4cbf55dda05206a9985e568d0ea564d1c7eb19b
@@ -0,0 +1,17 @@
1
+ name: check-service-regions
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '40 15 * * *'
6
+
7
+ jobs:
8
+ region-check:
9
+ runs-on: ubuntu-20.04
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v2
13
+ with:
14
+ fetch-depth: 1
15
+ - name: Set version tag
16
+ run: |
17
+ cd utils/aws ; ruby check_region_exclusions.rb
data/.solargraph.yml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ include:
3
+ - "**/*.rb"
4
+ exclude:
5
+ - spec/**/*
6
+ - test/**/*
7
+ - vendor/**/*
8
+ - ".bundle/**/*"
9
+ require: []
10
+ domains: []
11
+ reporters:
12
+ - rubocop
13
+ require_paths: []
14
+ plugins: []
15
+ max_files: 5000
@@ -65,6 +65,17 @@ module AwsRecon
65
65
  @resources.concat(collection) if @options.output_file
66
66
  end
67
67
 
68
+ #
69
+ # Format @resources as either
70
+ #
71
+ def formatted_json
72
+ if @options.jsonl
73
+ @resources.map { |r| JSON.generate(r) }.join("\n")
74
+ else
75
+ @resources.to_json
76
+ end
77
+ end
78
+
68
79
  #
69
80
  # main wrapper
70
81
  #
@@ -112,7 +123,7 @@ module AwsRecon
112
123
  if @options.output_file && !@options.s3
113
124
  puts "Saving resources to #{@options.output_file}.\n\n"
114
125
 
115
- File.write(@options.output_file, @resources.to_json)
126
+ File.write(@options.output_file, formatted_json)
116
127
  end
117
128
 
118
129
  # write output file to S3 bucket
@@ -128,7 +139,7 @@ module AwsRecon
128
139
  # build IO object and gzip it
129
140
  io = StringIO.new
130
141
  gzip_data = Zlib::GzipWriter.new(io)
131
- gzip_data.write(@resources.to_json)
142
+ gzip_data.write(formatted_json)
132
143
  gzip_data.close
133
144
 
134
145
  # send it to S3
@@ -18,7 +18,7 @@ class DynamoDB < Mapper
18
18
 
19
19
  struct = OpenStruct.new(response)
20
20
  struct.type = 'limits'
21
- struct.arn = "arn:aws:dynamodb:#{@region}:#{@account}:limits"
21
+ struct.arn = "arn:aws:dynamodb:#{@region}:#{@account}/limits"
22
22
 
23
23
  resources.push(struct.to_h)
24
24
  end
@@ -29,7 +29,7 @@ class EC2 < Mapper
29
29
  struct = OpenStruct.new
30
30
  struct.attributes = response.account_attributes.map(&:to_h)
31
31
  struct.type = 'account'
32
- struct.arn = "arn:aws::#{@account}"
32
+ struct.arn = "arn:aws:ec2::#{@account}:attributes/account_attributes"
33
33
 
34
34
  resources.push(struct.to_h)
35
35
  end
@@ -45,6 +45,7 @@ class EC2 < Mapper
45
45
 
46
46
  struct = OpenStruct.new(response.to_h)
47
47
  struct.type = 'ebs_encryption_settings'
48
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:settings/ebs_encryption_settings"
48
49
 
49
50
  resources.push(struct.to_h)
50
51
  end
@@ -63,7 +64,7 @@ class EC2 < Mapper
63
64
  reservation.instances.each do |instance|
64
65
  struct = OpenStruct.new(instance.to_h)
65
66
  struct.type = 'instance'
66
- struct.arn = instance.instance_id # no true ARN
67
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:instance/#{instance.instance_id}" # no true ARN
67
68
  struct.reservation_id = reservation.reservation_id
68
69
 
69
70
  # collect instance user_data
@@ -95,7 +96,7 @@ class EC2 < Mapper
95
96
  response.vpcs.each do |vpc|
96
97
  struct = OpenStruct.new(vpc.to_h)
97
98
  struct.type = 'vpc'
98
- struct.arn = vpc.vpc_id # no true ARN
99
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:vpc/#{vpc.vpc_id}" # no true ARN
99
100
  struct.flow_logs = @client
100
101
  .describe_flow_logs({ filter: [{ name: 'resource-id', values: [vpc.vpc_id] }] })
101
102
  .flow_logs.first.to_h
@@ -113,7 +114,7 @@ class EC2 < Mapper
113
114
  response.security_groups.each do |security_group|
114
115
  struct = OpenStruct.new(security_group.to_h)
115
116
  struct.type = 'security_group'
116
- struct.arn = security_group.group_id # no true ARN
117
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:security_group/#{security_group.group_id}" # no true ARN
117
118
 
118
119
  resources.push(struct.to_h)
119
120
  end
@@ -128,7 +129,7 @@ class EC2 < Mapper
128
129
  response.network_interfaces.each do |network_interface|
129
130
  struct = OpenStruct.new(network_interface.to_h)
130
131
  struct.type = 'network_interface'
131
- struct.arn = network_interface.network_interface_id # no true ARN
132
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:network_interface/#{network_interface.network_interface_id}" # no true ARN
132
133
 
133
134
  resources.push(struct.to_h)
134
135
  end
@@ -143,7 +144,7 @@ class EC2 < Mapper
143
144
  response.network_acls.each do |network_acl|
144
145
  struct = OpenStruct.new(network_acl.to_h)
145
146
  struct.type = 'network_acl'
146
- struct.arn = network_acl.network_acl_id # no true ARN
147
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:network_acl/#{network_acl.network_acl_id}" # no true ARN
147
148
 
148
149
  resources.push(struct.to_h)
149
150
  end
@@ -173,7 +174,7 @@ class EC2 < Mapper
173
174
  response.addresses.each do |address|
174
175
  struct = OpenStruct.new(address.to_h)
175
176
  struct.type = 'eip_address'
176
- struct.arn = address.allocation_id
177
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:eip_address/#{address.allocation_id}" # no true ARN
177
178
 
178
179
  resources.push(struct.to_h)
179
180
  end
@@ -188,7 +189,7 @@ class EC2 < Mapper
188
189
  response.nat_gateways.each do |gateway|
189
190
  struct = OpenStruct.new(gateway.to_h)
190
191
  struct.type = 'nat_gateway'
191
- struct.arn = gateway.nat_gateway_id # no true ARN
192
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:nat_gateway/#{gateway.nat_gateway_id}" # no true ARN
192
193
 
193
194
  resources.push(struct.to_h)
194
195
  end
@@ -203,7 +204,7 @@ class EC2 < Mapper
203
204
  response.internet_gateways.each do |gateway|
204
205
  struct = OpenStruct.new(gateway.to_h)
205
206
  struct.type = 'internet_gateway'
206
- struct.arn = gateway.internet_gateway_id # no true ARN
207
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:internet_gateway/#{gateway.internet_gateway_id}" # no true ARN
207
208
 
208
209
  resources.push(struct.to_h)
209
210
  end
@@ -218,7 +219,7 @@ class EC2 < Mapper
218
219
  response.route_tables.each do |table|
219
220
  struct = OpenStruct.new(table.to_h)
220
221
  struct.type = 'route_table'
221
- struct.arn = table.route_table_id # no true ARN
222
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:route_table/#{table.route_table_id}" # no true ARN
222
223
 
223
224
  resources.push(struct.to_h)
224
225
  end
@@ -233,7 +234,7 @@ class EC2 < Mapper
233
234
  response.images.each do |image|
234
235
  struct = OpenStruct.new(image.to_h)
235
236
  struct.type = 'image'
236
- struct.arn = image.image_id # no true ARN
237
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:image/#{image.image_id}" # no true ARN
237
238
 
238
239
  resources.push(struct.to_h)
239
240
  end
@@ -248,7 +249,7 @@ class EC2 < Mapper
248
249
  response.snapshots.each do |snapshot|
249
250
  struct = OpenStruct.new(snapshot.to_h)
250
251
  struct.type = 'snapshot'
251
- struct.arn = snapshot.snapshot_id # no true ARN
252
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:snapshot/#{snapshot.snapshot_id}" # no true ARN
252
253
  struct.create_volume_permissions = @client.describe_snapshot_attribute({
253
254
  attribute: 'createVolumePermission',
254
255
  snapshot_id: snapshot.snapshot_id
@@ -267,7 +268,7 @@ class EC2 < Mapper
267
268
  response.flow_logs.each do |flow_log|
268
269
  struct = OpenStruct.new(flow_log.to_h)
269
270
  struct.type = 'flow_log'
270
- struct.arn = flow_log.flow_log_id # no true ARN
271
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:flow_log/#{flow_log.flow_log_id}" # no true ARN
271
272
 
272
273
  resources.push(struct.to_h)
273
274
  end
@@ -282,7 +283,7 @@ class EC2 < Mapper
282
283
  response.volumes.each do |volume|
283
284
  struct = OpenStruct.new(volume.to_h)
284
285
  struct.type = 'volume'
285
- struct.arn = volume.volume_id # no true ARN
286
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:volume/#{volume.volume_id}" # no true ARN
286
287
 
287
288
  resources.push(struct.to_h)
288
289
  end
@@ -297,7 +298,7 @@ class EC2 < Mapper
297
298
  response.vpn_gateways.each do |gateway|
298
299
  struct = OpenStruct.new(gateway.to_h)
299
300
  struct.type = 'vpn_gateway'
300
- struct.arn = gateway.vpn_gateway_id # no true ARN
301
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:vpn_gateway/#{gateway.vpn_gateway_id}" # no true ARN
301
302
 
302
303
  resources.push(struct.to_h)
303
304
  end
@@ -312,7 +313,7 @@ class EC2 < Mapper
312
313
  response.vpc_peering_connections.each do |peer|
313
314
  struct = OpenStruct.new(peer.to_h)
314
315
  struct.type = 'peering_connection'
315
- struct.arn = peer.vpc_peering_connection_id # no true ARN
316
+ struct.arn = "arn:aws:ec2:#{@region}:#{@account}:peering_connection/#{peer.vpc_peering_connection_id}" # no true ARN
316
317
 
317
318
  resources.push(struct.to_h)
318
319
  end
@@ -50,7 +50,7 @@ class IAM < Mapper
50
50
  policy_document: p.policy_document.parse_policy
51
51
  }
52
52
  end
53
- end
53
+ end
54
54
 
55
55
  resources.push(struct.to_h)
56
56
  end
@@ -20,6 +20,7 @@ class Parser
20
20
  :output_file,
21
21
  :output_format,
22
22
  :threads,
23
+ :jsonl,
23
24
  :collect_user_data,
24
25
  :skip_slow,
25
26
  :skip_credential_report,
@@ -35,8 +36,8 @@ class Parser
35
36
  aws_regions = ['global'].concat(Aws::EC2::Client.new.describe_regions.regions.map(&:region_name))
36
37
  end
37
38
  rescue Aws::Errors::ServiceError => e
38
- puts "\nAWS Error: #{e.code}\n\n"
39
- exit
39
+ warn "\nAWS Error: #{e.code}\n\n"
40
+ exit(1)
40
41
  end
41
42
 
42
43
  aws_services = YAML.load(File.read(SERVICES_CONFIG_FILE), symbolize_names: true)
@@ -55,6 +56,7 @@ class Parser
55
56
  false,
56
57
  false,
57
58
  false,
59
+ false,
58
60
  false
59
61
  )
60
62
 
@@ -116,6 +118,11 @@ class Parser
116
118
  args.threads = threads.to_i if (0..Parser::MAX_THREADS).include?(threads.to_i)
117
119
  end
118
120
 
121
+ # output NDJSON/JSONL format
122
+ opts.on('-l', '--json-lines', 'Output NDJSON/JSONL format (default: false)') do
123
+ args.jsonl = true
124
+ end
125
+
119
126
  # collect EC2 instance user data
120
127
  opts.on('-u', '--user-data', 'Collect EC2 instance user data (default: false)') do
121
128
  args.collect_user_data = true
@@ -106,7 +106,7 @@
106
106
  - name: SecretsManager
107
107
  alias: sm
108
108
  - name: SecurityHub
109
- alias: sh
109
+ alias: securityhub
110
110
  excluded_regions:
111
111
  - ap-northeast-3
112
112
  - name: Support
@@ -1,3 +1,3 @@
1
1
  module AwsRecon
2
- VERSION = "0.4.4"
2
+ VERSION = "0.5.2"
3
3
  end
data/readme.md CHANGED
@@ -54,13 +54,13 @@ To run locally, first install the gem:
54
54
 
55
55
  ```
56
56
  $ gem install aws_recon
57
- Fetching aws_recon-0.4.0.gem
57
+ Fetching aws_recon-0.4.5.gem
58
58
  Fetching aws-sdk-3.0.1.gem
59
59
  Fetching parallel-1.20.1.gem
60
60
  ...
61
61
  Successfully installed aws-sdk-3.0.1
62
62
  Successfully installed parallel-1.20.1
63
- Successfully installed aws_recon-0.4.0
63
+ Successfully installed aws_recon-0.4.5
64
64
  ```
65
65
 
66
66
  Or add it to your Gemfile using `bundle`:
@@ -72,7 +72,7 @@ Resolving dependencies...
72
72
  ...
73
73
  Using aws-sdk 3.0.1
74
74
  Using parallel-1.20.1
75
- Using aws_recon 0.4.0
75
+ Using aws_recon 0.4.5
76
76
  ```
77
77
 
78
78
  ## Usage
@@ -249,7 +249,7 @@ Most users will want to limit collection to relevant services and regions. Runni
249
249
  ```
250
250
  $ aws_recon -h
251
251
 
252
- AWS Recon - AWS Inventory Collector (0.4.0)
252
+ AWS Recon - AWS Inventory Collector (0.4.5)
253
253
 
254
254
  Usage: aws_recon [options]
255
255
  -r, --regions [REGIONS] Regions to scan, separated by comma (default: all)
@@ -261,6 +261,7 @@ Usage: aws_recon [options]
261
261
  -o, --output [OUTPUT] Specify output file (default: output.json)
262
262
  -f, --format [FORMAT] Specify output format (default: aws)
263
263
  -t, --threads [THREADS] Specify max threads (default: 8, max: 128)
264
+ -l, --json-lines Output NDJSON/JSONL format (default: false)
264
265
  -u, --user-data Collect EC2 instance user data (default: false)
265
266
  -z, --skip-slow Skip slow operations (default: false)
266
267
  -g, --skip-credential-report Skip generating IAM credential report (default: false)
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Check regional service availability against services.yaml exclusions.
5
+ #
6
+ require 'net/http'
7
+ require 'json'
8
+ require 'yaml'
9
+
10
+ TS = Time.now.to_i
11
+ URL = "https://api.regional-table.region-services.aws.a2z.com/index.json?timestamp=#{TS}000"
12
+
13
+ region_exclusion_mistmatch = nil
14
+
15
+ #
16
+ # load current AWS Recon regions
17
+ #
18
+ recon_services = YAML.safe_load(File.read('../../lib/aws_recon/services.yaml'))
19
+ abort('Errors loading AWS Recon services') unless recon_services.is_a?(Array)
20
+
21
+ #
22
+ # load current AWS regions (non-gov, non-cn)
23
+ #
24
+ regions = YAML.safe_load(File.read('regions.yaml'))
25
+ abort('Errors loading regions') unless regions['Regions']
26
+
27
+ all_regions = regions['Regions'].map { |r| r['RegionName'] }
28
+
29
+ #
30
+ # get service/price list from AWS
31
+ #
32
+ uri = URI(URL)
33
+ res = Net::HTTP.get_response(uri)
34
+ abort('Error loading AWS services from API') unless res.code == '200'
35
+
36
+ map = {}
37
+
38
+ #
39
+ # load service region availability
40
+ #
41
+ data = res.body
42
+ json = JSON.parse(data)
43
+
44
+ # iterate through AWS provided services & regions
45
+ json['prices'].each do |p|
46
+ at = p['attributes']
47
+ service_name = at['aws:serviceName']
48
+ service_id, service_region = p['id'].split(':')
49
+
50
+ # skip this service unless AWS Recon already has exclusions
51
+ next unless recon_services.filter { |s| s['alias'] == service_id }&.length&.positive?
52
+
53
+ if map.key?(service_name)
54
+ map[service_name]['regions'] << service_region
55
+ else
56
+ map[service_name] = {
57
+ 'id' => service_id,
58
+ 'regions' => [service_region]
59
+ }
60
+ end
61
+ end
62
+
63
+ # iterate through the services AWS Recon knows about
64
+ map.sort.each do |k, v|
65
+ service_excluded_regions = all_regions.reject { |r| v['regions'].include?(r) }
66
+
67
+ aws_recon_service = recon_services.filter { |s| s['alias'] == v['id'] }&.first
68
+ aws_recon_service_excluded_regions = aws_recon_service['excluded_regions'] || []
69
+
70
+ # move on if AWS Recon region exclusions match AWS service region exclusions
71
+ next unless service_excluded_regions.sort != aws_recon_service_excluded_regions.sort
72
+
73
+ region_exclusion_mistmatch = true
74
+
75
+ puts "#{k} (#{v['id']})"
76
+
77
+ # determine the direction of the exclusion mismatch
78
+ if (service_excluded_regions - aws_recon_service_excluded_regions).length.positive?
79
+ puts " + missing region exclusion: #{(service_excluded_regions - aws_recon_service_excluded_regions).join(', ')}"
80
+ else
81
+ puts " - unnecessary region exclusion: #{(aws_recon_service_excluded_regions - service_excluded_regions).join(', ')}"
82
+ end
83
+ end
84
+
85
+ # exit code 1 if we have any mismatches
86
+ exit 1 if region_exclusion_mistmatch
@@ -0,0 +1,43 @@
1
+ Regions:
2
+ - Endpoint: ec2.af-south-1.amazonaws.com
3
+ RegionName: af-south-1
4
+ - Endpoint: ec2.eu-north-1.amazonaws.com
5
+ RegionName: eu-north-1
6
+ - Endpoint: ec2.ap-south-1.amazonaws.com
7
+ RegionName: ap-south-1
8
+ - Endpoint: ec2.eu-west-3.amazonaws.com
9
+ RegionName: eu-west-3
10
+ - Endpoint: ec2.eu-west-2.amazonaws.com
11
+ RegionName: eu-west-2
12
+ - Endpoint: ec2.eu-south-1.amazonaws.com
13
+ RegionName: eu-south-1
14
+ - Endpoint: ec2.eu-west-1.amazonaws.com
15
+ RegionName: eu-west-1
16
+ - Endpoint: ec2.ap-northeast-3.amazonaws.com
17
+ RegionName: ap-northeast-3
18
+ - Endpoint: ec2.ap-northeast-2.amazonaws.com
19
+ RegionName: ap-northeast-2
20
+ - Endpoint: ec2.me-south-1.amazonaws.com
21
+ RegionName: me-south-1
22
+ - Endpoint: ec2.ap-northeast-1.amazonaws.com
23
+ RegionName: ap-northeast-1
24
+ - Endpoint: ec2.sa-east-1.amazonaws.com
25
+ RegionName: sa-east-1
26
+ - Endpoint: ec2.ca-central-1.amazonaws.com
27
+ RegionName: ca-central-1
28
+ - Endpoint: ec2.ap-east-1.amazonaws.com
29
+ RegionName: ap-east-1
30
+ - Endpoint: ec2.ap-southeast-1.amazonaws.com
31
+ RegionName: ap-southeast-1
32
+ - Endpoint: ec2.ap-southeast-2.amazonaws.com
33
+ RegionName: ap-southeast-2
34
+ - Endpoint: ec2.eu-central-1.amazonaws.com
35
+ RegionName: eu-central-1
36
+ - Endpoint: ec2.us-east-1.amazonaws.com
37
+ RegionName: us-east-1
38
+ - Endpoint: ec2.us-east-2.amazonaws.com
39
+ RegionName: us-east-2
40
+ - Endpoint: ec2.us-west-1.amazonaws.com
41
+ RegionName: us-west-1
42
+ - Endpoint: ec2.us-west-2.amazonaws.com
43
+ RegionName: us-west-2
@@ -22,6 +22,7 @@ resource "aws_ecs_task_definition" "aws_recon_task" {
22
22
  "--verbose",
23
23
  "--format",
24
24
  "custom",
25
+ "--json-lines",
25
26
  "--s3-bucket",
26
27
  "${aws_s3_bucket.aws_recon.bucket}:${data.aws_region.current.name}",
27
28
  "--regions",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_recon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Larsen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-04-06 00:00:00.000000000 Z
12
+ date: 2021-04-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -163,10 +163,12 @@ extensions: []
163
163
  extra_rdoc_files: []
164
164
  files:
165
165
  - ".github/stale.yml"
166
+ - ".github/workflows/check-aws-regions.yml"
166
167
  - ".github/workflows/docker-build.yml"
167
168
  - ".github/workflows/smoke-test.yml"
168
169
  - ".gitignore"
169
170
  - ".rubocop.yml"
171
+ - ".solargraph.yml"
170
172
  - Dockerfile
171
173
  - Gemfile
172
174
  - LICENSE.txt
@@ -244,6 +246,8 @@ files:
244
246
  - lib/aws_recon/services.yaml
245
247
  - lib/aws_recon/version.rb
246
248
  - readme.md
249
+ - utils/aws/check_region_exclusions.rb
250
+ - utils/aws/regions.yaml
247
251
  - utils/cloudformation/aws-recon-cfn-template.yml
248
252
  - utils/terraform/cloudwatch.tf
249
253
  - utils/terraform/ecs.tf