aws_recon 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rubocop.yml +12 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +1000 -0
  9. data/LICENSE.txt +21 -0
  10. data/Rakefile +10 -0
  11. data/aws_recon.gemspec +36 -0
  12. data/bin/aws_recon +5 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/lib/aws_recon.rb +19 -0
  16. data/lib/aws_recon/aws_recon.rb +115 -0
  17. data/lib/aws_recon/collectors/acm.rb +32 -0
  18. data/lib/aws_recon/collectors/apigateway.rb +50 -0
  19. data/lib/aws_recon/collectors/apigatewayv2.rb +37 -0
  20. data/lib/aws_recon/collectors/athena.rb +28 -0
  21. data/lib/aws_recon/collectors/autoscaling.rb +35 -0
  22. data/lib/aws_recon/collectors/cloudformation.rb +29 -0
  23. data/lib/aws_recon/collectors/cloudfront.rb +28 -0
  24. data/lib/aws_recon/collectors/cloudtrail.rb +33 -0
  25. data/lib/aws_recon/collectors/cloudwatch.rb +33 -0
  26. data/lib/aws_recon/collectors/cloudwatchlogs.rb +36 -0
  27. data/lib/aws_recon/collectors/codebuild.rb +29 -0
  28. data/lib/aws_recon/collectors/codepipeline.rb +27 -0
  29. data/lib/aws_recon/collectors/collectors.rb +2 -0
  30. data/lib/aws_recon/collectors/configservice.rb +80 -0
  31. data/lib/aws_recon/collectors/directconnect.rb +25 -0
  32. data/lib/aws_recon/collectors/directyservice.rb +27 -0
  33. data/lib/aws_recon/collectors/dms.rb +25 -0
  34. data/lib/aws_recon/collectors/dynamodb.rb +26 -0
  35. data/lib/aws_recon/collectors/ec2.rb +257 -0
  36. data/lib/aws_recon/collectors/ecr.rb +39 -0
  37. data/lib/aws_recon/collectors/ecs.rb +40 -0
  38. data/lib/aws_recon/collectors/efs.rb +25 -0
  39. data/lib/aws_recon/collectors/eks.rb +36 -0
  40. data/lib/aws_recon/collectors/elasticloadbalancing.rb +41 -0
  41. data/lib/aws_recon/collectors/elasticloadbalancingv2.rb +63 -0
  42. data/lib/aws_recon/collectors/elasticsearch.rb +27 -0
  43. data/lib/aws_recon/collectors/firehose.rb +29 -0
  44. data/lib/aws_recon/collectors/guardduty.rb +33 -0
  45. data/lib/aws_recon/collectors/iam.rb +136 -0
  46. data/lib/aws_recon/collectors/kafka.rb +27 -0
  47. data/lib/aws_recon/collectors/kinesis.rb +26 -0
  48. data/lib/aws_recon/collectors/kms.rb +71 -0
  49. data/lib/aws_recon/collectors/lambda.rb +42 -0
  50. data/lib/aws_recon/collectors/lightsail.rb +38 -0
  51. data/lib/aws_recon/collectors/organizations.rb +36 -0
  52. data/lib/aws_recon/collectors/rds.rb +81 -0
  53. data/lib/aws_recon/collectors/redshift.rb +40 -0
  54. data/lib/aws_recon/collectors/route53.rb +28 -0
  55. data/lib/aws_recon/collectors/route53domains.rb +25 -0
  56. data/lib/aws_recon/collectors/s3.rb +80 -0
  57. data/lib/aws_recon/collectors/sagemaker.rb +25 -0
  58. data/lib/aws_recon/collectors/servicequotas.rb +44 -0
  59. data/lib/aws_recon/collectors/ses.rb +28 -0
  60. data/lib/aws_recon/collectors/shield.rb +67 -0
  61. data/lib/aws_recon/collectors/sns.rb +38 -0
  62. data/lib/aws_recon/collectors/sqs.rb +28 -0
  63. data/lib/aws_recon/collectors/ssm.rb +41 -0
  64. data/lib/aws_recon/collectors/support.rb +43 -0
  65. data/lib/aws_recon/collectors/transfer.rb +24 -0
  66. data/lib/aws_recon/collectors/wafv2.rb +49 -0
  67. data/lib/aws_recon/collectors/workspaces.rb +24 -0
  68. data/lib/aws_recon/collectors/xray.rb +19 -0
  69. data/lib/aws_recon/lib/formatter.rb +32 -0
  70. data/lib/aws_recon/lib/mapper.rb +69 -0
  71. data/lib/aws_recon/options.rb +141 -0
  72. data/lib/aws_recon/services.yaml +134 -0
  73. data/lib/aws_recon/version.rb +3 -0
  74. data/readme.md +226 -0
  75. data/readme_gem.md +39 -0
  76. 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