aws_public_ips 1.0.3 → 1.0.4

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
- SHA256:
3
- metadata.gz: c360fd8fc1dec710ad8ee00b18babdd8bb4781494dad119291a6fa03fcb65b1f
4
- data.tar.gz: bbf9fa5b7a48c45d5b9056117d5c56e9d1aac2a97acf27eebeda0198cc76cd72
2
+ SHA1:
3
+ metadata.gz: 4a083bab67810085c9610fee6ca593420f077afd
4
+ data.tar.gz: eec41af99070ed34d83759f3f042bb3461618e3d
5
5
  SHA512:
6
- metadata.gz: 7717d68059ba9b004df5f16755bfd8ce69af4fc73ade7e7cd559311d2c11d5ed2f6f704483eb667654d35e8fef4fa076ce1840f82e387dce028cb7b7dc7251a1
7
- data.tar.gz: c0b4e447f652d427077a0c9dbadc8c7b81ee620286d33508e04ef970978f8570110be11e69506f9eefac9021687e10f9ac3d424485ddbb7edff25a41e09b49d1
6
+ metadata.gz: 78688710a288065d81d6ce4ab60170cbbd3e1f83bed09d3c07efb89a4ad11e92155451ff03836b747554e485081db14b0f262c25636b38ae1c001c7556da80fc
7
+ data.tar.gz: 96ab667b2321e1c5f8b656551db71d92c1690715cba785900895493b8f402b48a3e8ea7ae56d9d8b575a2f5ccaa3412ac58f52f895bf2d5e005b616e09307560
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH.unshift(File.expand_path(File.join('..', '..', 'lib'), __FILE__))
4
+ $LOAD_PATH.unshift(::File.expand_path(::File.join('..', '..', 'lib'), __FILE__))
5
5
  require 'aws_public_ips/cli'
6
6
 
7
- AwsPublicIps::CLI.new.run(ARGV)
7
+ ::AwsPublicIps::CLI.new.run(::ARGV)
@@ -7,7 +7,7 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Apigateway
9
9
  def self.run
10
- client = Aws::APIGateway::Client.new
10
+ client = ::Aws::APIGateway::Client.new
11
11
 
12
12
  # TODO(arkadiy) https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-private-integration.html
13
13
 
@@ -19,7 +19,7 @@ module AwsPublicIps
19
19
  {
20
20
  id: api.id,
21
21
  hostname: hostname,
22
- ip_addresses: Utils.resolve_hostname(hostname)
22
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(hostname)
23
23
  }
24
24
  end
25
25
  end
@@ -7,14 +7,17 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Cloudfront
9
9
  def self.run
10
- client = Aws::CloudFront::Client.new
10
+ client = ::Aws::CloudFront::Client.new
11
+
12
+ # Cloudfront distrubtions are always public, they don't have a concept of VPC
13
+ # No "coming up" problem here like with RDS/Redshift
11
14
 
12
15
  client.list_distributions.flat_map do |response|
13
16
  response.distribution_list.items.flat_map do |distribution|
14
17
  {
15
18
  id: distribution.id,
16
19
  hostname: distribution.domain_name,
17
- ip_addresses: Utils.resolve_hostname(distribution.domain_name)
20
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(distribution.domain_name)
18
21
  }
19
22
  end
20
23
  end
@@ -6,16 +6,15 @@ module AwsPublicIps
6
6
  module Checks
7
7
  module Ec2
8
8
  def self.run
9
- client = Aws::EC2::Client.new
9
+ client = ::Aws::EC2::Client.new
10
10
 
11
- # TODO(arkadiy) confirm this covers Batch, Fargate
12
11
  # Iterate over all EC2 instances. This will include those from EC2, ECS, EKS, Fargate, Batch,
13
12
  # Beanstalk, and NAT Instances
14
13
  # It will not include NAT Gateways (IPv4) or Egress Only Internet Gateways (IPv6), but they do not allow
15
14
  # ingress traffic so we skip them anyway
16
15
  client.describe_instances.flat_map do |response|
17
16
  response.reservations.flat_map do |reservation|
18
- reservation.instances.map do |instance|
17
+ reservation.instances.flat_map do |instance|
19
18
  # EC2-Classic instances have a `public_ip_address` and no `network_interfaces`
20
19
  # EC2-VPC instances both set, so we uniq the ip addresses
21
20
  ip_addresses = [instance.public_ip_address].compact + instance.network_interfaces.flat_map do |interface|
@@ -23,6 +22,9 @@ module AwsPublicIps
23
22
  public_ip + interface.ipv_6_addresses.map(&:ipv_6_address)
24
23
  end
25
24
 
25
+ # Don't return an entry if all ips were private
26
+ next [] if ip_addresses.empty?
27
+
26
28
  # If hostname is empty string, canonicalize to nil
27
29
  hostname = instance.public_dns_name.empty? ? nil : instance.public_dns_name
28
30
  {
@@ -7,10 +7,10 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Elasticsearch
9
9
  def self.run
10
- client = Aws::ElasticsearchService::Client.new
10
+ client = ::Aws::ElasticsearchService::Client.new
11
11
 
12
- # ElasticSearch instances can be launched publicly or into VPCs. Public instances have a
13
- # `domain_status.endpoint` hostname and VPC instances have a `domain_status.endpoints['vpc']` hostname.
12
+ # ElasticSearch instances can be launched into classic into VPCs. Classic instances are public and have a
13
+ # `domain_status.endpoint` hostname, and VPC instances have a `domain_status.endpoints['vpc']` hostname.
14
14
  # However VPC ElasticSearch instances create their own Network Interface and AWS will not allow you
15
15
  # to associate an Elastic IP to it. As a result VPC ElasticSearch instances are always private, even with an
16
16
  # internet gateway.
@@ -23,7 +23,7 @@ module AwsPublicIps
23
23
  {
24
24
  id: domain.domain_status.domain_id,
25
25
  hostname: hostname,
26
- ip_addresses: Utils.resolve_hostname(hostname)
26
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(hostname)
27
27
  }
28
28
  end.compact
29
29
  end
@@ -7,18 +7,19 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Elb
9
9
  def self.run
10
- client = Aws::ElasticLoadBalancing::Client.new
10
+ client = ::Aws::ElasticLoadBalancing::Client.new
11
11
 
12
12
  # EC2-Classic load balancers are only returned by the 'elasticloadbalancing' API, and
13
13
  # EC2-VPC ALBs/NLBs are only returned by the 'elasticloadbalancingv2' API
14
14
  client.describe_load_balancers.flat_map do |response|
15
15
  response.load_balancer_descriptions.flat_map do |load_balancer|
16
16
  next [] unless load_balancer.scheme == 'internet-facing'
17
+ # EC2-Classic load balancers get IPv6 DNS records created but they are not returned by the API
18
+ hostnames = [load_balancer.dns_name, "ipv6.#{load_balancer.dns_name}"]
17
19
  {
18
20
  id: load_balancer.canonical_hosted_zone_name_id,
19
21
  hostname: load_balancer.dns_name,
20
- # EC2-Classic load balancers get IPv6 DNS records created but they are not returned by the API
21
- ip_addresses: Utils.resolve_hostnames([load_balancer.dns_name, "ipv6.#{load_balancer.dns_name}"])
22
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostnames(hostnames)
22
23
  }
23
24
  end
24
25
  end
@@ -7,7 +7,7 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Elbv2
9
9
  def self.run
10
- client = Aws::ElasticLoadBalancingV2::Client.new
10
+ client = ::Aws::ElasticLoadBalancingV2::Client.new
11
11
 
12
12
  # EC2-Classic load balancers are only returned by the 'elasticloadbalancing' API, and
13
13
  # EC2-VPC ALBs/NLBs are only returned by the 'elasticloadbalancingv2' API
@@ -21,7 +21,7 @@ module AwsPublicIps
21
21
  {
22
22
  id: load_balancer.canonical_hosted_zone_id,
23
23
  hostname: load_balancer.dns_name,
24
- ip_addresses: Utils.resolve_hostname(load_balancer.dns_name)
24
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(load_balancer.dns_name)
25
25
  }
26
26
  end
27
27
  end
@@ -7,7 +7,7 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Lightsail
9
9
  def self.run
10
- client = Aws::Lightsail::Client.new
10
+ client = ::Aws::Lightsail::Client.new
11
11
 
12
12
  # Lightsail instances are always exposed directly, and can also be put behind a load balancer
13
13
 
@@ -28,7 +28,7 @@ module AwsPublicIps
28
28
  # Names are unique
29
29
  id: load_balancer.name,
30
30
  hostname: load_balancer.dns_name,
31
- ip_addresses: Utils.resolve_hostname(load_balancer.dns_name)
31
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(load_balancer.dns_name)
32
32
  }
33
33
  end
34
34
  end
@@ -7,21 +7,25 @@ module AwsPublicIps
7
7
  module Checks
8
8
  module Rds
9
9
  def self.run
10
- client = Aws::RDS::Client.new
10
+ client = ::Aws::RDS::Client.new
11
11
 
12
- # TODO(arkadiy) not sure if this is true anymore after redshift, do more testing
13
- # RDS instances can be:
14
- # - launched into classic
15
- # - launched into VPC
16
- # - launched into a VPC but marked as `publicly_accessible`, in which case the VPC must have an Internet
17
- # Gateway attached, and the DNS endpoint will resolve to a public ip address
12
+ # RDS instances can be launched into VPCs or into Classic mode.
13
+ # In classic mode they are always public.
14
+ # In VPC mode they can be marked as `publicly_accessible` or not - if they are then its VPC must have
15
+ # an Internet Gateway attached, and the DNS endpoint will resolve to a public ip address.
18
16
  client.describe_db_instances.flat_map do |response|
19
17
  response.db_instances.flat_map do |instance|
20
18
  next [] unless instance.publicly_accessible
19
+
20
+ if instance.endpoint.nil?
21
+ raise StandardError, "RDS DB '#{instance.dbi_resource_id}' has a nil endpoint. This likely" \
22
+ ' means the DB is being brought up right now.'
23
+ end
24
+
21
25
  {
22
26
  id: instance.dbi_resource_id,
23
27
  hostname: instance.endpoint.address,
24
- ip_addresses: Utils.resolve_hostname(instance.endpoint.address)
28
+ ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(instance.endpoint.address)
25
29
  }
26
30
  end
27
31
  end
@@ -1,24 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aws-sdk-redshift'
4
+ require 'aws_public_ips/utils'
4
5
 
5
6
  module AwsPublicIps
6
7
  module Checks
7
8
  module Redshift
8
9
  def self.run
9
- client = Aws::Redshift::Client.new
10
+ client = ::Aws::Redshift::Client.new
10
11
 
11
- # TODO(arkadiy) update copy from RDS
12
- # Redshift clusters can only be launched into VPCs. They can be marked as `publicly_accessible`,
13
- # in which case the VPC must have an Internet Gateway attached, and the DNS endpoint will
14
- # resolve to a public ip address
12
+ # Redshift clusters can be launched into VPCs or into Classic mode.
13
+ # In classic mode they are always public.
14
+ # In VPC mode they can be marked as `publicly_accessible` or not - if they are then its VPC must have
15
+ # an Internet Gateway attached, and the DNS endpoint will resolve to a public ip address.
15
16
  client.describe_clusters.flat_map do |response|
16
17
  response.clusters.flat_map do |cluster|
17
18
  next [] unless cluster.publicly_accessible
19
+
20
+ if cluster.endpoint.nil?
21
+ raise StandardError, "Redshift cluster '#{cluster.cluster_identifier}' has a nil endpoint. This likely" \
22
+ ' means the cluster is being brought up right now.'
23
+ end
24
+
18
25
  {
19
26
  id: cluster.cluster_identifier,
20
27
  hostname: cluster.endpoint.address,
21
- ip_addresses: cluster.cluster_nodes.map(&:public_ip_address)
28
+ ip_addresses: cluster.cluster_nodes.map(&:public_ip_address) +
29
+ ::AwsPublicIps::Utils.resolve_hostname(cluster.endpoint.address)
22
30
  }
23
31
  end
24
32
  end
@@ -39,11 +39,11 @@ module AwsPublicIps
39
39
  # AWS Neptune (still in preview / not GA yet)
40
40
 
41
41
  def all_services
42
- @all_services ||= Dir["#{__dir__}/checks/*.rb"].map { |path| File.basename(path, '.rb') }.sort
42
+ @all_services ||= ::Dir["#{__dir__}/checks/*.rb"].map { |path| ::File.basename(path, '.rb') }.sort
43
43
  end
44
44
 
45
45
  def all_formats
46
- @all_formats ||= Dir["#{__dir__}/formatters/*.rb"].map { |path| File.basename(path, '.rb') }.sort
46
+ @all_formats ||= ::Dir["#{__dir__}/formatters/*.rb"].map { |path| ::File.basename(path, '.rb') }.sort
47
47
  end
48
48
 
49
49
  def parse(args)
@@ -53,28 +53,39 @@ module AwsPublicIps
53
53
  verbose: false
54
54
  }
55
55
 
56
- OptionParser.new do |opts|
57
- opts.banner = 'Usage: aws_public_ips [options]'
56
+ ::OptionParser.new do |parser|
57
+ parser.banner = 'Usage: aws_public_ips [options]'
58
58
 
59
- opts.on('-s', '--services <s1>,<s2>,<s3>', Array, 'List of AWS services to check. Available services: ' \
59
+ parser.on('-s', '--services <s1>,<s2>,<s3>', Array, 'List of AWS services to check. Available services: ' \
60
60
  "#{all_services.join(',')}. Defaults to all.") do |services|
61
61
  services.map(&:downcase!).uniq!
62
62
  invalid_services = services - all_services
63
- raise ArgumentError, "Invalid service(s): #{invalid_services.join(',')}" unless invalid_services.empty?
63
+ raise ::ArgumentError, "Invalid service(s): #{invalid_services.join(',')}" unless invalid_services.empty?
64
64
  options[:services] = services
65
65
  end
66
66
 
67
- opts.on('-f', '--format <format>', String, 'Set output format. Available formats: ' \
67
+ parser.on('-f', '--format <format>', String, 'Set output format. Available formats: ' \
68
68
  "#{all_formats.join(',')}. Defaults to text.") do |fmt|
69
69
  unless all_formats.include?(fmt)
70
- raise ArgumentError, "Invalid format '#{fmt}'. Valid formats are: #{all_formats.join(',')}"
70
+ raise ::ArgumentError, "Invalid format '#{fmt}'. Valid formats are: #{all_formats.join(',')}"
71
71
  end
72
72
  options[:format] = fmt
73
73
  end
74
74
 
75
- opts.on('-v', '--[no-]verbose', 'Enable debug/trace output') do |verbose|
75
+ parser.on('-v', '--[no-]verbose', 'Enable debug/trace output') do |verbose|
76
76
  options[:verbose] = verbose
77
77
  end
78
+
79
+ parser.on_tail('--version', 'Print version') do
80
+ require 'aws_public_ips/version'
81
+ ::STDOUT.puts ::AwsPublicIps::VERSION
82
+ return nil # nil to avoid rubocop warning
83
+ end
84
+
85
+ parser.on_tail('-h', '--help', 'Show this help message') do
86
+ ::STDOUT.puts parser
87
+ return nil # nil to avoid rubocop warning
88
+ end
78
89
  end.parse(args)
79
90
 
80
91
  options
@@ -82,28 +93,29 @@ module AwsPublicIps
82
93
 
83
94
  def check_service(service)
84
95
  require "aws_public_ips/checks/#{service}.rb"
85
- AwsPublicIps::Checks.const_get(service.capitalize).run
96
+ ::AwsPublicIps::Checks.const_get(service.capitalize).run
86
97
  end
87
98
 
88
99
  def output(formatter, results)
89
100
  require "aws_public_ips/formatters/#{formatter}.rb"
90
- formatter_klass = AwsPublicIps::Formatters.const_get(formatter.capitalize)
101
+ formatter_klass = ::AwsPublicIps::Formatters.const_get(formatter.capitalize)
91
102
  output = formatter_klass.new(results).format
92
- puts output unless output.empty?
103
+ ::STDOUT.puts output unless output.empty?
93
104
  end
94
105
 
95
106
  def run(args)
96
107
  options = parse(args)
108
+ return unless options
97
109
 
98
110
  results = options[:services].map do |service|
99
111
  [service.to_sym, check_service(service)]
100
112
  end.to_h
101
113
 
102
114
  output(options[:format], results)
103
- rescue StandardError, Interrupt => ex
104
- puts ex.inspect
105
- puts ex.backtrace if options[:verbose]
106
- Process.exit(1)
115
+ rescue ::StandardError, ::Interrupt => ex
116
+ ::STDERR.puts ex.inspect
117
+ ::STDERR.puts ex.backtrace if options && options[:verbose]
118
+ ::Process.exit(1)
107
119
  end
108
120
  end
109
121
  end
@@ -10,7 +10,7 @@ module AwsPublicIps
10
10
  end
11
11
 
12
12
  def format
13
- JSON.pretty_generate(@results)
13
+ ::JSON.pretty_generate(@results)
14
14
  end
15
15
  end
16
16
  end
@@ -10,9 +10,9 @@ module AwsPublicIps
10
10
 
11
11
  def self.resolve_hostname(hostname)
12
12
  # Default Resolv.getaddresses doesn't seem to return IPv6 results
13
- resources = Resolv::DNS.open do |dns|
14
- dns.getresources(hostname, Resolv::DNS::Resource::IN::A) +
15
- dns.getresources(hostname, Resolv::DNS::Resource::IN::AAAA)
13
+ resources = ::Resolv::DNS.open do |dns|
14
+ dns.getresources(hostname, ::Resolv::DNS::Resource::IN::A) +
15
+ dns.getresources(hostname, ::Resolv::DNS::Resource::IN::AAAA)
16
16
  end
17
17
 
18
18
  resources.map do |resource|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AwsPublicIps
4
- VERSION = '1.0.3'.freeze
4
+ VERSION = '1.0.4'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_public_ips
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arkadiy Tetelman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-17 00:00:00.000000000 Z
11
+ date: 2018-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-apigateway
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.55.0
187
+ version: 0.56.0
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 0.55.0
194
+ version: 0.56.0
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: webmock
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -253,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
253
253
  version: '0'
254
254
  requirements: []
255
255
  rubyforge_project:
256
- rubygems_version: 2.7.6
256
+ rubygems_version: 2.6.14
257
257
  signing_key:
258
258
  specification_version: 4
259
259
  summary: A library/cli to fetch all public IP addresses associated with an AWS account