aws_recon 0.2.3 → 0.2.8

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: ac6fae11753e715682d656eba8c922267831fe7324d9a44bd96296543cf9653e
4
- data.tar.gz: 900bf49cc999b1fd9d227067609ad85c3b6a462886156c94e7dfb5d5e1c0a982
3
+ metadata.gz: 939b12091dee8bd4c6b36877a9954ba43372267edda3b4a1d93d3c5695bfde5b
4
+ data.tar.gz: fe6dbac4e8001bd82d21bbcb8b22d904f91e864afff58d12a6f86b54d4789d2c
5
5
  SHA512:
6
- metadata.gz: 6c76cf3f96cbf58501c61861361be27e76cc95e1c60cf83ae141d2e4aa0a4d12efe7ed9b1dae74094fff2a5a157a2d17a49ef37ecc471de7f985156b4228e608
7
- data.tar.gz: 93341c804a9daf7c4f849927ff429a34b72af74acdbe741e324829e938d01aa805550e7a41b0aeeeb68c2dc80ec37e14cb83e7c5ef1f9406c7c94815eca6757e
6
+ metadata.gz: 120629a6ac6f8839b4f5dea1a0e269133ded6e1679f4e3ca3411965e34cf901d851638edda80450423c6de86ba1701cd00d13b9ea7292cb75881189a98cf4238
7
+ data.tar.gz: 3d16a17670a9326d3668e7eb37e9fdf883d5dcce1290b368722fc205d37d0a60b58fe850b21211db435f790b1650a44312ede568db41b03537a5fca679373387
@@ -0,0 +1,17 @@
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 30
3
+ # Number of days of inactivity before a stale issue is closed
4
+ daysUntilClose: 5
5
+ # Issues with these labels will never be considered stale
6
+ exemptLabels:
7
+ - pinned
8
+ - security
9
+ # Label to use when marking an issue as stale
10
+ staleLabel: wontfix
11
+ # Comment to post when marking an issue as stale. Set to `false` to disable
12
+ markComment: >
13
+ This issue has been automatically marked as stale because it has not had
14
+ recent activity. It will be closed if no further activity occurs. Thank you
15
+ for your contributions.
16
+ # Comment to post when closing a stale issue. Set to `false` to disable
17
+ closeComment: false
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  .DS_Store
2
2
  *.json
3
+ Gemfile.lock
3
4
  .rvmrc
4
5
  .ruby-gemset
5
6
  .ruby-version
@@ -0,0 +1,34 @@
1
+ ARG RUBY_VERSION=2.6.6
2
+ FROM ruby:${RUBY_VERSION}-alpine
3
+
4
+ LABEL maintainer="Darkbit <info@darkbit.io>"
5
+
6
+ ARG USER=recon
7
+ ARG GEM=aws_recon
8
+ ARG VERSION=0.2.8
9
+ ARG BUNDLER_VERSION=2.1.4
10
+
11
+ # Install new Bundler version
12
+ RUN rm /usr/local/lib/ruby/gems/*/specifications/default/bundler-*.gemspec && \
13
+ gem uninstall bundler && \
14
+ gem install bundler -v $BUNDLER_VERSION
15
+
16
+ # Install gem
17
+ RUN gem install ${GEM} -v ${VERSION}
18
+
19
+ # Create non-root user
20
+ RUN addgroup -S ${USER} && \
21
+ adduser -S ${USER} \
22
+ -G ${USER} \
23
+ -s /bin/ash \
24
+ -h /${USER}
25
+
26
+ # Copy binstub
27
+ COPY binstub/${GEM} /usr/local/bundle/bin/
28
+ RUN chmod +x /usr/local/bundle/bin/${GEM}
29
+
30
+ # Switch user
31
+ USER ${USER}
32
+ WORKDIR /${USER}
33
+
34
+ CMD ["ash"]
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_development_dependency 'bundler', '~> 1.17'
30
30
  spec.add_development_dependency 'gem-release', '~> 2.1'
31
- spec.add_development_dependency 'rake', '>= 12.3.3'
31
+ spec.add_development_dependency 'rake', '~> 12.3'
32
32
  spec.add_development_dependency 'minitest', '~> 5.0'
33
33
  spec.add_development_dependency 'solargraph', '~> 0.39.11'
34
34
  spec.add_development_dependency 'rubocop', '~> 0.87.1'
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # Manually generated binstub
5
+ #
6
+
7
+ require "rubygems"
8
+ require "bundler/setup"
9
+
10
+ load Gem.bin_path("aws_recon", "aws_recon")
@@ -12,7 +12,7 @@ require 'aws-sdk'
12
12
  require 'aws_recon/options.rb'
13
13
  require 'aws_recon/lib/mapper.rb'
14
14
  require 'aws_recon/lib/formatter.rb'
15
- require 'aws_recon/collectors/collectors.rb'
15
+ require 'aws_recon/collectors.rb'
16
16
 
17
17
  require 'aws_recon/version'
18
18
  require 'aws_recon/aws_recon'
@@ -44,7 +44,7 @@ module AwsRecon
44
44
  #
45
45
  def collect(service, region)
46
46
  mapper = Object.const_get(service.name)
47
- resources = mapper.new(service.name, region, @options)
47
+ resources = mapper.new(@account_id, service.name, region, @options)
48
48
 
49
49
  collection = resources.collect.map do |resource|
50
50
  if @options.output_format == 'custom'
@@ -0,0 +1,2 @@
1
+ # require all collectors
2
+ Dir[File.join(__dir__, 'collectors', '*.rb')].each { |file| require file }
@@ -48,6 +48,23 @@ class EC2 < Mapper
48
48
  struct.arn = instance.instance_id # no true ARN
49
49
  struct.reservation_id = reservation.reservation_id
50
50
 
51
+ # collect instance user_data
52
+ if @options.collect_user_data
53
+ user_data_raw = @client.describe_instance_attribute({
54
+ attribute: 'userData',
55
+ instance_id: instance.instance_id
56
+ }).user_data.to_h[:value]
57
+
58
+ # don't save non-string user_data
59
+ if user_data_raw
60
+ user_data = Base64.decode64(user_data_raw)
61
+
62
+ if user_data.force_encoding('UTF-8').ascii_only?
63
+ struct.user_data = user_data
64
+ end
65
+ end
66
+ end
67
+
51
68
  resources.push(struct.to_h)
52
69
  end
53
70
  end
@@ -0,0 +1,22 @@
1
+ class ElastiCache < Mapper
2
+ def collect
3
+ resources = []
4
+
5
+ #
6
+ # describe_cache_clusters
7
+ #
8
+ @client.describe_cache_clusters.each_with_index do |response, page|
9
+ log(response.context.operation_name, page)
10
+
11
+ response.cache_clusters.each do |cluster|
12
+ struct = OpenStruct.new(cluster.to_h)
13
+ struct.type = 'cluster'
14
+ struct.arn = cluster.arn
15
+
16
+ resources.push(struct.to_h)
17
+ end
18
+ end
19
+
20
+ resources
21
+ end
22
+ end
@@ -48,6 +48,21 @@ class IAM < Mapper
48
48
  end
49
49
  end
50
50
 
51
+ #
52
+ # list_policies
53
+ #
54
+ @client.list_policies.each do |response|
55
+ log(response.context.operation_name)
56
+
57
+ # managed policies
58
+ response.policies.each do |policy|
59
+ struct = OpenStruct.new(policy.to_h)
60
+ struct.type = 'managed_policy'
61
+
62
+ resources.push(struct.to_h)
63
+ end
64
+ end
65
+
51
66
  #
52
67
  # get_account_password_policy
53
68
  #
@@ -56,6 +71,7 @@ class IAM < Mapper
56
71
 
57
72
  struct = OpenStruct.new(response.password_policy.to_h)
58
73
  struct.type = 'password_policy'
74
+ struct.arn = "arn:aws:iam::#{@account}:account_password_policy/global"
59
75
 
60
76
  resources.push(struct.to_h)
61
77
  end
@@ -68,6 +84,7 @@ class IAM < Mapper
68
84
 
69
85
  struct = OpenStruct.new(response.summary_map)
70
86
  struct.type = 'account_summary'
87
+ struct.arn = "arn:aws:iam::#{@account}:account_summary/global"
71
88
 
72
89
  resources.push(struct.to_h)
73
90
  end
@@ -111,6 +128,7 @@ class IAM < Mapper
111
128
 
112
129
  struct = OpenStruct.new
113
130
  struct.type = 'credential_report'
131
+ struct.arn = "arn:aws:iam::#{@account}:credential_report/global"
114
132
  struct.content = CSV.parse(response.content, headers: :first_row).map(&:to_h)
115
133
  struct.report_format = response.report_format
116
134
  struct.generated_time = response.generated_time
@@ -1,6 +1,5 @@
1
1
  class Lambda < Mapper
2
2
  def collect
3
- service = self.class.to_s.downcase
4
3
  resources = []
5
4
 
6
5
  #
@@ -13,7 +13,7 @@ class Shield < Mapper
13
13
 
14
14
  struct = OpenStruct.new(response.subscription.to_h)
15
15
  struct.type = 'subscription'
16
- struct.arn = "arn:aws:shield:#{@region}:#{account}:subscription"
16
+ struct.arn = "arn:aws:shield:#{@region}:#{@account}:subscription"
17
17
 
18
18
  resources.push(struct.to_h)
19
19
  end
@@ -26,7 +26,7 @@ class Shield < Mapper
26
26
 
27
27
  struct = OpenStruct.new
28
28
  struct.type = 'contact_list'
29
- struct.arn = "arn:aws:shield:#{@region}:#{account}:contact_list"
29
+ struct.arn = "arn:aws:shield:#{@region}:#{@account}:contact_list"
30
30
  struct.contacts = response.emergency_contact_list.map(&:to_h)
31
31
 
32
32
  resources.push(struct.to_h)
@@ -8,7 +8,7 @@ class Formatter
8
8
  def custom(account_id, region, service, resource)
9
9
  {
10
10
  account: account_id,
11
- name: resource[:arn] || "#{account_id}_#{region}_#{service.name}_#{resource[:type]}",
11
+ name: resource[:arn],
12
12
  service: service.name,
13
13
  region: region,
14
14
  asset_type: resource[:type],
@@ -22,7 +22,8 @@ class Mapper
22
22
  # S3 (unless the bucket was created in another region)
23
23
  SINGLE_REGION_SERVICES = %w[route53domains s3 shield support organizations].freeze
24
24
 
25
- def initialize(service, region, options)
25
+ def initialize(account, service, region, options)
26
+ @account = account
26
27
  @service = service
27
28
  @region = region
28
29
  @options = options
@@ -15,6 +15,7 @@ class Parser
15
15
  :output_file,
16
16
  :output_format,
17
17
  :threads,
18
+ :collect_user_data,
18
19
  :skip_slow,
19
20
  :stream_output,
20
21
  :verbose,
@@ -43,6 +44,7 @@ class Parser
43
44
  false,
44
45
  false,
45
46
  false,
47
+ false,
46
48
  false
47
49
  )
48
50
 
@@ -103,6 +105,11 @@ class Parser
103
105
  end
104
106
  end
105
107
 
108
+ # collect EC2 instance user data
109
+ opts.on('-u', '--user-data', 'Collect EC2 instance user data (default: false)') do
110
+ args.collect_user_data = true
111
+ end
112
+
106
113
  # skip slow operations
107
114
  opts.on('-z', '--skip-slow', 'Skip slow operations (default: false)') do
108
115
  args.skip_slow = true
@@ -21,8 +21,6 @@
21
21
  alias: ec2
22
22
  - name: EKS
23
23
  alias: eks
24
- excluded_regions:
25
- - us-west-1
26
24
  - name: ECS
27
25
  alias: ecs
28
26
  - name: ElasticLoadBalancing
@@ -33,6 +31,8 @@
33
31
  alias: elbv2
34
32
  excluded_regions:
35
33
  - ap-southeast-1
34
+ - name: ElastiCache
35
+ alias: elasticache
36
36
  - name: IAM
37
37
  global: true
38
38
  alias: iam
@@ -1,3 +1,3 @@
1
1
  module AwsRecon
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.8"
3
3
  end
data/readme.md CHANGED
@@ -26,18 +26,20 @@ Ruby 2.5.x or 2.6.x (developed and tested with 2.6.5)
26
26
 
27
27
  ### Installation
28
28
 
29
- Install the gem:
29
+ AWS Recon can be run locally by installing the Ruby gem, or via a Docker container.
30
+
31
+ To run locally, first install the gem:
30
32
 
31
33
  ```
32
34
  $ gem install aws_recon
33
- Fetching aws_recon-0.2.2.gem
35
+ Fetching aws_recon-0.2.7.gem
34
36
  Fetching aws-sdk-resources-3.76.0.gem
35
37
  Fetching aws-sdk-3.0.1.gem
36
38
  Fetching parallel-1.19.2.gem
37
39
  ...
38
40
  Successfully installed aws-sdk-3.0.1
39
41
  Successfully installed parallel-1.19.2
40
- Successfully installed aws_recon-0.2.2
42
+ Successfully installed aws_recon-0.2.7
41
43
  ```
42
44
 
43
45
  Or add it to your Gemfile using `bundle`:
@@ -52,6 +54,20 @@ Using parallel 1.19.2
52
54
  Using aws_recon 0.2.2
53
55
  ```
54
56
 
57
+ To run via a Docker a container, pass the necessary AWS credentials into the Docker `run` command. For example:
58
+
59
+ ```
60
+ $ docker run --rm \
61
+ -e AWS_REGION \
62
+ -e AWS_ACCESS_KEY_ID \
63
+ -e AWS_SECRET_ACCESS_KEY \
64
+ -e AWS_SESSION_TOKEN \
65
+ -v $(pwd)/output.json:/recon/output.json \
66
+ aws_recon:latest \
67
+ aws_recon -v -s EC2 -r us-east-1,us-east-2
68
+ ```
69
+
70
+
55
71
  ## Usage
56
72
 
57
73
  AWS Recon will leverage any AWS credentials currently available to the environment it runs in. If you are collecting from multiple accounts, you may want to leverage something like [aws-vault](https://github.com/99designs/aws-vault) to manage different credentials.
@@ -66,6 +82,31 @@ Plain environment variables will work fine too.
66
82
  $ AWS_PROFILE=<profile> aws_recon
67
83
  ```
68
84
 
85
+ To run from a Docker container using `aws-vault` managed credentials (output to file):
86
+
87
+ ```
88
+ $ aws-vault exec darkbit -- docker run --rm \
89
+ -e AWS_REGION \
90
+ -e AWS_ACCESS_KEY_ID \
91
+ -e AWS_SECRET_ACCESS_KEY \
92
+ -e AWS_SESSION_TOKEN \
93
+ -v $(pwd)/output.json:/recon/output.json \
94
+ aws_recon:latest \
95
+ aws_recon -s EC2 -v -r us-east-1,us-east-2
96
+ ```
97
+
98
+ To run from a Docker container using `aws-vault` managed credentials (output to stdout):
99
+
100
+ ```
101
+ $ aws-vault exec darkbit -- docker run --rm \
102
+ -e AWS_REGION \
103
+ -e AWS_ACCESS_KEY_ID \
104
+ -e AWS_SECRET_ACCESS_KEY \
105
+ -e AWS_SESSION_TOKEN \
106
+ aws_recon:latest \
107
+ aws_recon -j -s EC2 -r us-east-1,us-east-2
108
+ ```
109
+
69
110
  You may want to use the `-v` or `--verbose` flag initially to see status and activity while collection is running.
70
111
 
71
112
  In verbose mode, the console output will show:
@@ -135,7 +176,7 @@ Most users will want to limit collection to relevant services and regions. Runni
135
176
  ```
136
177
  $ aws_recon -h
137
178
 
138
- AWS Recon - AWS Inventory Collector
179
+ AWS Recon - AWS Inventory Collector (0.2.7)
139
180
 
140
181
  Usage: aws_recon [options]
141
182
  -r, --regions [REGIONS] Regions to scan, separated by comma (default: all)
@@ -146,6 +187,7 @@ Usage: aws_recon [options]
146
187
  -o, --output [OUTPUT] Specify output file (default: output.json)
147
188
  -f, --format [FORMAT] Specify output format (default: aws)
148
189
  -t, --threads [THREADS] Specify max threads (default: 8, max: 128)
190
+ -u, --user-data Collect EC2 instance user data (default: false)
149
191
  -z, --skip-slow Skip slow operations (default: false)
150
192
  -j, --stream-output Stream JSON lines to stdout (default: false)
151
193
  -v, --verbose Output client progress and current operation
@@ -193,6 +235,7 @@ AWS Recon aims to collect all resources and metadata that are relevant in determ
193
235
  - [x] ELB
194
236
  - [x] EKS
195
237
  - [x] Elasticsearch
238
+ - [x] ElastiCache
196
239
  - [x] Firehose
197
240
  - [ ] FMS
198
241
  - [ ] Glacier
@@ -227,23 +270,27 @@ One of the primary motivations for AWS Recon was to build a tool that is easy to
227
270
 
228
271
  ### Development
229
272
 
230
- Clone this repository, then install the required gems using `bundle`:
273
+ Clone this repository:
231
274
 
232
275
  ```
233
276
  $ git clone git@github.com:darkbitio/aws-recon.git
234
277
  $ cd aws-recon
235
- $ bundle
236
- ...
237
- Using aws-sdk-core 3.103.0
238
- ...
239
- Bundle complete! 5 Gemfile dependencies, 259 gems now installed.
240
- Use `bundle info [gemname]` to see where a bundled gem is installed.
241
278
  ```
242
279
 
280
+ Create a sticky gemset if using RVM:
281
+
282
+ ```
283
+ $ rvm use 2.6.5@aws_recon_dev --create --ruby-version
284
+ ```
285
+
286
+ Run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
287
+
288
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
289
+
243
290
  ### TODO
244
291
 
245
292
  - [ ] Optionally suppress AWS API errors instead of re-raising them
246
- - [ ] Package as a gem
293
+ - [x] Package as a gem
247
294
  - [ ] Test coverage with AWS SDK stubbed resources
248
295
 
249
296