aws_recon 0.2.3 → 0.2.8
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 +4 -4
- data/.github/stale.yml +17 -0
- data/.gitignore +1 -0
- data/Dockerfile +34 -0
- data/aws_recon.gemspec +1 -1
- data/binstub/aws_recon +10 -0
- data/lib/aws_recon.rb +1 -1
- data/lib/aws_recon/aws_recon.rb +1 -1
- data/lib/aws_recon/collectors.rb +2 -0
- data/lib/aws_recon/collectors/ec2.rb +17 -0
- data/lib/aws_recon/collectors/elasticache.rb +22 -0
- data/lib/aws_recon/collectors/iam.rb +18 -0
- data/lib/aws_recon/collectors/lambda.rb +0 -1
- data/lib/aws_recon/collectors/shield.rb +2 -2
- data/lib/aws_recon/lib/formatter.rb +1 -1
- data/lib/aws_recon/lib/mapper.rb +2 -1
- data/lib/aws_recon/options.rb +7 -0
- data/lib/aws_recon/services.yaml +2 -2
- data/lib/aws_recon/version.rb +1 -1
- data/readme.md +59 -12
- metadata +11 -11
- data/Gemfile.lock +0 -1000
- data/lib/aws_recon/collectors/collectors.rb +0 -2
- data/readme_gem.md +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 939b12091dee8bd4c6b36877a9954ba43372267edda3b4a1d93d3c5695bfde5b
|
4
|
+
data.tar.gz: fe6dbac4e8001bd82d21bbcb8b22d904f91e864afff58d12a6f86b54d4789d2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 120629a6ac6f8839b4f5dea1a0e269133ded6e1679f4e3ca3411965e34cf901d851638edda80450423c6de86ba1701cd00d13b9ea7292cb75881189a98cf4238
|
7
|
+
data.tar.gz: 3d16a17670a9326d3668e7eb37e9fdf883d5dcce1290b368722fc205d37d0a60b58fe850b21211db435f790b1650a44312ede568db41b03537a5fca679373387
|
data/.github/stale.yml
ADDED
@@ -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
data/Dockerfile
ADDED
@@ -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"]
|
data/aws_recon.gemspec
CHANGED
@@ -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', '
|
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'
|
data/binstub/aws_recon
ADDED
data/lib/aws_recon.rb
CHANGED
@@ -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
|
15
|
+
require 'aws_recon/collectors.rb'
|
16
16
|
|
17
17
|
require 'aws_recon/version'
|
18
18
|
require 'aws_recon/aws_recon'
|
data/lib/aws_recon/aws_recon.rb
CHANGED
@@ -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'
|
@@ -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
|
@@ -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]
|
11
|
+
name: resource[:arn],
|
12
12
|
service: service.name,
|
13
13
|
region: region,
|
14
14
|
asset_type: resource[:type],
|
data/lib/aws_recon/lib/mapper.rb
CHANGED
@@ -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
|
data/lib/aws_recon/options.rb
CHANGED
@@ -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
|
data/lib/aws_recon/services.yaml
CHANGED
@@ -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
|
data/lib/aws_recon/version.rb
CHANGED
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
|
-
|
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.
|
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.
|
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
|
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
|
-
- [
|
293
|
+
- [x] Package as a gem
|
247
294
|
- [ ] Test coverage with AWS SDK stubbed resources
|
248
295
|
|
249
296
|
|