aws_recon 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12b30d8e1939333bd6a2f94ba0bfa5a8b9aa381e0330546425158360cda8e099
4
- data.tar.gz: dea36844f6fc06403b563fd0dc6938d222c0dc8757b7b88c0cdd03e0b5df79e5
3
+ metadata.gz: 9647cee32c4df1624a99cf180258f43e664e7ee62b8ceee5fe00b8d6b31a2803
4
+ data.tar.gz: aca9a6383263ca7add32682df25a633ad9db031a50d2f38f319f903b6dd75c45
5
5
  SHA512:
6
- metadata.gz: 50fa5ec78c7bbedc8f89321cbd0a679945e2509a2ba8d51c0fd6e95d15a3e7cdf29db051f0b9816d85bf49af0d7375e2f8ada6796b7c9a4ddb3b403ebda4b598
7
- data.tar.gz: d1d1cb453321a8dcb669839b3e9597af0a11882863c15f9a44c23f6dda77efaa0c302ed3208032c12a12f97b09f9eff0776f4346e579b588ab10c1ba4d2b713e
6
+ metadata.gz: 426acf5937d26974c7a7c5bc26e84487fe8b76cc28bf0f51a7302d05897356e7007b877e26a47cc3af7b54044ac45bec23b409b1b66bef0336aaa1216d340437
7
+ data.tar.gz: 790fd25c65d4fe49c2e3857f65cddb590ecfe9f481b923bcdf8def9007ddf1ccb0b16f616164e7472b43a75eebe77698146d3d2e46204af1085b276afedf2099
data/.rubocop.yml CHANGED
@@ -12,7 +12,6 @@ Layout/LineLength:
12
12
  Max: 100
13
13
  Style/FrozenStringLiteralComment:
14
14
  EnforcedStyle: always_true
15
- Safe: true
16
15
  SafeAutoCorrect: true
17
16
  Style/ClassAndModuleChildren:
18
17
  Enabled: false
@@ -34,9 +34,9 @@ module AwsRecon
34
34
  # formatter
35
35
  @formatter = Formatter.new
36
36
 
37
- unless @options.stream_output
38
- puts "\nStarting collection with #{@options.threads} threads...\n"
39
- end
37
+ return unless @options.stream_output
38
+
39
+ puts "\nStarting collection with #{@options.threads} threads...\n"
40
40
  end
41
41
 
42
42
  #
@@ -72,7 +72,7 @@ module AwsRecon
72
72
  #
73
73
  # global services
74
74
  #
75
- @aws_services.map { |x| OpenStruct.new(x) }.filter { |s| s.global }.each do |service|
75
+ @aws_services.map { |x| OpenStruct.new(x) }.filter(&:global).each do |service|
76
76
  # user included this service in the args
77
77
  next unless @services.include?(service.name)
78
78
 
@@ -104,14 +104,45 @@ module AwsRecon
104
104
 
105
105
  puts "\nStopped early after \x1b[32m#{elapsed.to_i}\x1b[0m seconds.\n"
106
106
  ensure
107
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @starting
108
+
109
+ puts "\nFinished in \x1b[32m#{elapsed.to_i}\x1b[0m seconds.\n\n"
110
+
107
111
  # write output file
108
112
  if @options.output_file
109
- elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @starting
110
-
111
- puts "\nFinished in \x1b[32m#{elapsed.to_i}\x1b[0m seconds. Saving resources to \x1b[32m#{@options.output_file}\x1b[0m.\n\n"
113
+ puts "Saving resources to \x1b[32m#{@options.output_file}\x1b[0m.\n\n"
112
114
 
113
115
  File.write(@options.output_file, @resources.to_json)
114
116
  end
117
+
118
+ # write output file to S3 bucket
119
+ if @options.s3
120
+ t = Time.now.utc
121
+
122
+ s3_full_object_path = "AWSRecon/#{t.year}/#{t.month}/#{t.day}/#{@account_id}_aws_recon_#{t.to_i}.json.gz"
123
+
124
+ begin
125
+ # get bucket name (and region if not us-east-1)
126
+ s3_bucket, s3_region = @options.s3.split(':')
127
+
128
+ # build IO object and gzip it
129
+ io = StringIO.new
130
+ gzip_data = Zlib::GzipWriter.new(io)
131
+ gzip_data.write(@resources.to_json)
132
+ gzip_data.close
133
+
134
+ # send it to S3
135
+ s3_client = Aws::S3::Client.new(region: s3_region || 'us-east-1')
136
+ s3_resource = Aws::S3::Resource.new(client: s3_client)
137
+ obj = s3_resource.bucket(s3_bucket).object(s3_full_object_path)
138
+ obj.put(body: io.string)
139
+
140
+ puts "Saving resources to S3 \x1b[32ms3://#{s3_bucket}/#{s3_full_object_path}\x1b[0m\n\n"
141
+ rescue Aws::S3::Errors::ServiceError => e
142
+ puts "\x1b[35mError!\x1b[0m - could not save output S3 bucket\n\n"
143
+ puts "#{e.message} - #{e.code}\n"
144
+ end
145
+ end
115
146
  end
116
147
  end
117
148
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # require all collectors
2
- Dir[File.join(__dir__, 'collectors', '*.rb')].each { |file| require file }
4
+ Dir[File.join(__dir__, 'collectors', '*.rb')].sort.each { |file| require file }
@@ -6,6 +6,7 @@
6
6
  class Parser
7
7
  DEFAULT_CONFIG_FILE = nil
8
8
  DEFAULT_OUTPUT_FILE = File.expand_path(File.join(Dir.pwd, 'output.json')).freeze
9
+ DEFAULT_S3_PATH = nil
9
10
  SERVICES_CONFIG_FILE = File.join(File.dirname(__FILE__), 'services.yaml').freeze
10
11
  DEFAULT_FORMAT = 'aws'
11
12
  DEFAULT_THREADS = 8
@@ -15,6 +16,7 @@ class Parser
15
16
  :regions,
16
17
  :services,
17
18
  :config_file,
19
+ :s3,
18
20
  :output_file,
19
21
  :output_format,
20
22
  :threads,
@@ -43,6 +45,7 @@ class Parser
43
45
  aws_regions,
44
46
  aws_services.map { |service| service[:name] },
45
47
  DEFAULT_CONFIG_FILE,
48
+ DEFAULT_S3_PATH,
46
49
  DEFAULT_OUTPUT_FILE,
47
50
  DEFAULT_FORMAT,
48
51
  DEFAULT_THREADS,
@@ -93,6 +96,11 @@ class Parser
93
96
  args.config_file = config
94
97
  end
95
98
 
99
+ # write output file to S3 bucket
100
+ opts.on('-b', '--s3-bucket [BUCKET:REGION]', 'Write output file to S3 bucket (default: \'\')') do |bucket_with_region|
101
+ args.s3 = bucket_with_region
102
+ end
103
+
96
104
  # output file
97
105
  opts.on('-o', '--output [OUTPUT]', 'Specify output file (default: output.json)') do |output|
98
106
  args.output_file = File.expand_path(File.join(Dir.pwd, output))
@@ -1,3 +1,3 @@
1
1
  module AwsRecon
2
- VERSION = "0.3.5"
2
+ VERSION = "0.4.0"
3
3
  end
data/readme.md CHANGED
@@ -5,9 +5,9 @@
5
5
 
6
6
  A multi-threaded AWS inventory collection tool.
7
7
 
8
- The [creators](https://darkbit.io) of this tool have a recurring need to be able to efficiently collect a large amount of AWS resource attributes and metadata to help clients understand their cloud security posture.
8
+ This tool was created to facilitate efficient collection of a large amount of AWS resource attributes and metadata. It aims to collect nearly everything that is relevant to the security configuration and posture of an AWS environment.
9
9
 
10
- Existing tools (e.g. [AWS Config](https://aws.amazon.com/config)) that do some form of resource collection lack the coverage and specificity we needed. We also needed a tool that produced consistent output that was easily consumed by other tools/systems.
10
+ Existing tools (e.g. [AWS Config](https://aws.amazon.com/config)) that do some form of resource collection lack the coverage and specificity to accurately measure security posture (e.g. detailed attribute data and full policy documents).
11
11
 
12
12
  Enter AWS Recon, multi-threaded AWS inventory collection tool written in plain Ruby. Though Python tends to dominate the AWS tooling landscape, the [Ruby SDK](https://aws.amazon.com/sdk-for-ruby/) has a few convenient advantages over the [other](https://aws.amazon.com/sdk-for-node-js/) [AWS](https://aws.amazon.com/sdk-for-python/) [SDKs](https://aws.amazon.com/sdk-for-go/) we tested. Specifically, easy handling of automatic retries, paging of large responses, and - with some help - threading huge numbers of requests.
13
13
 
@@ -15,7 +15,7 @@ Enter AWS Recon, multi-threaded AWS inventory collection tool written in plain R
15
15
 
16
16
  - More complete resource coverage than available tools (especially for ECS & EKS)
17
17
  - More granular resource detail, including nested related resources in the output
18
- - Flexible output (console, JSON lines, plain JSON, file, standard out)
18
+ - Flexible output (console, JSON lines, plain JSON, file, S3 bucket, and standard out)
19
19
  - Efficient (multi-threaded, rate limited, automatic retries, and automatic result paging)
20
20
  - Easy to maintain and extend
21
21
 
@@ -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.3.0.gem
57
+ Fetching aws_recon-0.4.0.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.3.0
63
+ Successfully installed aws_recon-0.4.0
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.3.0
75
+ Using aws_recon 0.4.0
76
76
  ```
77
77
 
78
78
  ## Usage
@@ -158,13 +158,37 @@ Finished in 46 seconds. Saving resources to output.json.
158
158
  #### Example command line options
159
159
 
160
160
  ```
161
+ # collect S3 and EC2 global resources, as well as us-east-1 and us-east-2
162
+
161
163
  $ AWS_PROFILE=<profile> aws_recon -s S3,EC2 -r global,us-east-1,us-east-2
162
164
  ```
163
165
 
164
166
  ```
167
+ # collect S3 and EC2 global resources, as well as us-east-1 and us-east-2
168
+
165
169
  $ AWS_PROFILE=<profile> aws_recon --services S3,EC2 --regions global,us-east-1,us-east-2
166
170
  ```
167
171
 
172
+ ```
173
+ # save output to S3 bucket
174
+
175
+ $ AWS_PROFILE=<profile> aws_recon \
176
+ --services S3,EC2 \
177
+ --regions global,us-east-1,us-east-2 \
178
+ --verbose \
179
+ --s3-bucket my-recon-bucket
180
+ ```
181
+
182
+ ```
183
+ # save output to S3 bucket with a home region other than us-east-1
184
+
185
+ $ AWS_PROFILE=<profile> aws_recon \
186
+ --services S3,EC2 \
187
+ --regions global,us-east-1,us-east-2 \
188
+ --verbose \
189
+ --s3-bucket my-recon-bucket:us-west-2
190
+ ```
191
+
168
192
  Example [OpenCSPM](https://github.com/OpenCSPM/opencspm) formatted (NDJSON) output.
169
193
 
170
194
  ```
@@ -225,7 +249,7 @@ Most users will want to limit collection to relevant services and regions. Runni
225
249
  ```
226
250
  $ aws_recon -h
227
251
 
228
- AWS Recon - AWS Inventory Collector (0.3.0)
252
+ AWS Recon - AWS Inventory Collector (0.4.0)
229
253
 
230
254
  Usage: aws_recon [options]
231
255
  -r, --regions [REGIONS] Regions to scan, separated by comma (default: all)
@@ -233,6 +257,7 @@ Usage: aws_recon [options]
233
257
  -s, --services [SERVICES] Services to scan, separated by comma (default: all)
234
258
  -x, --not-services [SERVICES] Services to skip, separated by comma (default: none)
235
259
  -c, --config [CONFIG] Specify config file for services & regions (e.g. config.yaml)
260
+ -b, --s3-bucket [BUCKET:REGION] Write output file to S3 bucket (default: '')
236
261
  -o, --output [OUTPUT] Specify output file (default: output.json)
237
262
  -f, --format [FORMAT] Specify output format (default: aws)
238
263
  -t, --threads [THREADS] Specify max threads (default: 8, max: 128)
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.3.5
4
+ version: 0.4.0
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-03-25 00:00:00.000000000 Z
12
+ date: 2021-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk