diff --git a/lib/aws_public_ips/checks/apigateway.rb b/lib/aws_public_ips/checks/apigateway.rb index 40b416c..61bd500 100644 --- a/lib/aws_public_ips/checks/apigateway.rb +++ b/lib/aws_public_ips/checks/apigateway.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Apigateway - def self.run + def self.run(all) client = ::Aws::APIGateway::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/cloudfront.rb b/lib/aws_public_ips/checks/cloudfront.rb index bbf1b2d..8fce20c 100644 --- a/lib/aws_public_ips/checks/cloudfront.rb +++ b/lib/aws_public_ips/checks/cloudfront.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Cloudfront - def self.run + def self.run(all) client = ::Aws::CloudFront::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/ec2.rb b/lib/aws_public_ips/checks/ec2.rb index 5f01525..3ff3182 100644 --- a/lib/aws_public_ips/checks/ec2.rb +++ b/lib/aws_public_ips/checks/ec2.rb @@ -6,15 +6,32 @@ module AwsPublicIps module Checks module Ec2 - def self.run + def self.run(all) client = ::Aws::EC2::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) + results = [] + + if all + results += client.describe_nat_gateways.flat_map do |response| + response.nat_gateways.flat_map do |gateway| + ip_addresses = gateway.nat_gateway_addresses.map { |addresses| addresses.public_ip } + + # Don't return an entry if all ips were private + next [] if ip_addresses.empty? + + { + id: gateway.nat_gateway_id, + hostname: nil, + ip_addresses: ip_addresses.uniq + } + end + end + end + # Iterate over all EC2 instances. This will include those from EC2, ECS, EKS, Fargate, Batch, # Beanstalk, and NAT Instances - # It will not include NAT Gateways (IPv4) or Egress Only Internet Gateways (IPv6), but they do not allow - # ingress traffic so we skip them anyway - client.describe_instances.flat_map do |response| + results += client.describe_instances.flat_map do |response| response.reservations.flat_map do |reservation| reservation.instances.flat_map do |instance| # EC2-Classic instances have a `public_ip_address` and no `network_interfaces` @@ -43,6 +60,8 @@ def self.run end end end + + results end end end diff --git a/lib/aws_public_ips/checks/elasticsearch.rb b/lib/aws_public_ips/checks/elasticsearch.rb index f962ff0..0ee84a7 100644 --- a/lib/aws_public_ips/checks/elasticsearch.rb +++ b/lib/aws_public_ips/checks/elasticsearch.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Elasticsearch - def self.run + def self.run(all) client = ::Aws::ElasticsearchService::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/elb.rb b/lib/aws_public_ips/checks/elb.rb index 2218c0a..337ce57 100644 --- a/lib/aws_public_ips/checks/elb.rb +++ b/lib/aws_public_ips/checks/elb.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Elb - def self.run + def self.run(all) client = ::Aws::ElasticLoadBalancing::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/elbv2.rb b/lib/aws_public_ips/checks/elbv2.rb index 459ed72..7a77aab 100644 --- a/lib/aws_public_ips/checks/elbv2.rb +++ b/lib/aws_public_ips/checks/elbv2.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Elbv2 - def self.run + def self.run(all) client = ::Aws::ElasticLoadBalancingV2::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/lightsail.rb b/lib/aws_public_ips/checks/lightsail.rb index aea8e14..b3f743d 100644 --- a/lib/aws_public_ips/checks/lightsail.rb +++ b/lib/aws_public_ips/checks/lightsail.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Lightsail - def self.run + def self.run(all) client = ::Aws::Lightsail::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/rds.rb b/lib/aws_public_ips/checks/rds.rb index 46f8694..5cdee70 100644 --- a/lib/aws_public_ips/checks/rds.rb +++ b/lib/aws_public_ips/checks/rds.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Rds - def self.run + def self.run(all) client = ::Aws::RDS::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/checks/redshift.rb b/lib/aws_public_ips/checks/redshift.rb index b40b358..362a6b8 100644 --- a/lib/aws_public_ips/checks/redshift.rb +++ b/lib/aws_public_ips/checks/redshift.rb @@ -6,7 +6,7 @@ module AwsPublicIps module Checks module Redshift - def self.run + def self.run(all) client = ::Aws::Redshift::Client.new return [] unless ::AwsPublicIps::Utils.has_service?(client) diff --git a/lib/aws_public_ips/cli.rb b/lib/aws_public_ips/cli.rb index 74fef76..058b4e3 100644 --- a/lib/aws_public_ips/cli.rb +++ b/lib/aws_public_ips/cli.rb @@ -18,7 +18,6 @@ class CLI # Services that don't need to be supported: # S3 - all s3 buckets resolve to the same ip addresses # SQS - there's a single AWS-owned domain per region (i.e. sqs.us-east-1.amazonaws.com//) - # NAT Gateways - these do not allow ingress traffic # ElastiCache - all elasticache instances are private. You can make one public by using a NAT instance with an EIP: # https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/accessing-elasticache.html#access-from-outside-aws # but NAT instances are EC2 machines, so this will be caught by the EC2 check. @@ -74,6 +73,10 @@ def parse(args) options[:format] = fmt end + parser.on('-a', '--all', "Include all services (even those that don't allow ingress") do + options[:all] = true + end + parser.on('-v', '--[no-]verbose', 'Enable debug/trace output') do |verbose| options[:verbose] = verbose end @@ -93,9 +96,9 @@ def parse(args) options end - def check_service(service) + def check_service(service, all) require "aws_public_ips/checks/#{service}.rb" - ::AwsPublicIps::Checks.const_get(service.capitalize).run + ::AwsPublicIps::Checks.const_get(service.capitalize).run(all) end def output(formatter, options, results) @@ -110,7 +113,7 @@ def run(args) return unless options results = options[:services].map do |service| - [service.to_sym, check_service(service)] + [service.to_sym, check_service(service, options[:all])] end.to_h output(options[:format], options, results) diff --git a/spec/aws_public_ips/checks/apigateway_spec.rb b/spec/aws_public_ips/checks/apigateway_spec.rb index 7fe0193..5aed95d 100644 --- a/spec/aws_public_ips/checks/apigateway_spec.rb +++ b/spec/aws_public_ips/checks/apigateway_spec.rb @@ -10,7 +10,7 @@ 'tmtmok31nc.execute-api.us-east-1.amazonaws.com' => %w[54.0.0.3] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'e83d6nij2j', hostname: 'e83d6nij2j.execute-api.us-east-1.amazonaws.com', diff --git a/spec/aws_public_ips/checks/cloudfront_spec.rb b/spec/aws_public_ips/checks/cloudfront_spec.rb index 2ab1580..7a7dc6f 100644 --- a/spec/aws_public_ips/checks/cloudfront_spec.rb +++ b/spec/aws_public_ips/checks/cloudfront_spec.rb @@ -9,7 +9,7 @@ 'd22ycgwdruc4lt.cloudfront.net' => %w[54.0.0.1 54.0.0.2], 'd1k00qwg2uxphp.cloudfront.net' => %w[54.0.0.3] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'E1DABYDY46RHFK', hostname: 'd22ycgwdruc4lt.cloudfront.net', diff --git a/spec/aws_public_ips/checks/ec2_spec.rb b/spec/aws_public_ips/checks/ec2_spec.rb index 12c2176..b1e9f71 100644 --- a/spec/aws_public_ips/checks/ec2_spec.rb +++ b/spec/aws_public_ips/checks/ec2_spec.rb @@ -5,7 +5,7 @@ stub_request(:post, 'https://ec2.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/ec2.xml')) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'i-0f22d0af796b3cf3a', hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com', @@ -32,6 +32,6 @@ it 'should not return an entry when there are no public ips' do stub_request(:post, 'https://ec2.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/ec2-private.xml')) - expect(subject.run).to eq([]) + expect(subject.run(true)).to eq([]) end end diff --git a/spec/aws_public_ips/checks/elasticsearch_spec.rb b/spec/aws_public_ips/checks/elasticsearch_spec.rb index 5f831be..cd4ab4c 100644 --- a/spec/aws_public_ips/checks/elasticsearch_spec.rb +++ b/spec/aws_public_ips/checks/elasticsearch_spec.rb @@ -13,7 +13,7 @@ 'search-classic-fd5cbkkjuuiudho2lrwmsjp6rm.us-east-1.es.amazonaws.com' => %w[54.0.0.1] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: '154967844790/classic', hostname: 'search-classic-fd5cbkkjuuiudho2lrwmsjp6rm.us-east-1.es.amazonaws.com', diff --git a/spec/aws_public_ips/checks/elb_spec.rb b/spec/aws_public_ips/checks/elb_spec.rb index 209062d..c4631d6 100644 --- a/spec/aws_public_ips/checks/elb_spec.rb +++ b/spec/aws_public_ips/checks/elb_spec.rb @@ -10,7 +10,7 @@ 'ipv6.classic-272004174.us-east-1.elb.amazonaws.com' => %w[2600:1f18:63e0:b401:b952:5715:d981:2776] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'Z35SXDOTRQ7X7K', hostname: 'classic-272004174.us-east-1.elb.amazonaws.com', diff --git a/spec/aws_public_ips/checks/elbv2_spec.rb b/spec/aws_public_ips/checks/elbv2_spec.rb index bb664db..4643d9a 100644 --- a/spec/aws_public_ips/checks/elbv2_spec.rb +++ b/spec/aws_public_ips/checks/elbv2_spec.rb @@ -10,7 +10,7 @@ 'alb-vpc-228877692.us-east-1.elb.amazonaws.com' => %w[54.0.0.2 2600:1f18:63e0:b401:b952:5715:d981:2776] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'Z26RNL4JYFTOTI', hostname: 'nlb-vpc-d243d0acc9151631.elb.us-east-1.amazonaws.com', diff --git a/spec/aws_public_ips/checks/lightsail_spec.rb b/spec/aws_public_ips/checks/lightsail_spec.rb index f3131e1..dc74125 100644 --- a/spec/aws_public_ips/checks/lightsail_spec.rb +++ b/spec/aws_public_ips/checks/lightsail_spec.rb @@ -10,7 +10,7 @@ 'ce551c6f952085b4126e4b523a100eda-232829524.us-east-1.elb.amazonaws.com' => %w[54.88.163.90 52.205.146.152] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'Amazon_Linux-512MB-Virginia-1', hostname: nil, diff --git a/spec/aws_public_ips/checks/rds_spec.rb b/spec/aws_public_ips/checks/rds_spec.rb index a98d26c..599dc35 100644 --- a/spec/aws_public_ips/checks/rds_spec.rb +++ b/spec/aws_public_ips/checks/rds_spec.rb @@ -10,7 +10,7 @@ 'rds-vpc-public-us-east-1a.cyvjlokb0o75.us-east-1.rds.amazonaws.com' => %w[52.70.34.110] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'db-BAKGGXYRB3EBKBDQZTAMDSGCXY', hostname: 'rds-vpc-public.cyvjlokb0o75.us-east-1.rds.amazonaws.com', @@ -28,13 +28,13 @@ stub_request(:post, 'https://rds.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/rds-vpc-private.xml')) - expect(subject.run).to eq([]) + expect(subject.run(true)).to eq([]) end it 'should handle db instances with a nil endpoint' do stub_request(:post, 'https://rds.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/rds-empty-endpoint.xml')) - expect { subject.run }.to raise_error(StandardError, /has a nil endpoint/) + expect { subject.run(true) }.to raise_error(StandardError, /has a nil endpoint/) end end diff --git a/spec/aws_public_ips/checks/redshift_spec.rb b/spec/aws_public_ips/checks/redshift_spec.rb index 4a2ec45..38563da 100644 --- a/spec/aws_public_ips/checks/redshift_spec.rb +++ b/spec/aws_public_ips/checks/redshift_spec.rb @@ -5,7 +5,7 @@ stub_request(:post, 'https://redshift.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/redshift-classic-public.xml')) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'classic', hostname: 'classic.csorkyt5dk7h.us-east-1.redshift.amazonaws.com', @@ -21,7 +21,7 @@ stub_dns( 'vpc-public-2.csorkyt5dk7h.us-east-1.redshift.amazonaws.com' => %w[54.156.7.130] ) - expect(subject.run).to eq([ + expect(subject.run(true)).to eq([ { id: 'vpc-public-2', hostname: 'vpc-public-2.csorkyt5dk7h.us-east-1.redshift.amazonaws.com', @@ -34,12 +34,12 @@ stub_request(:post, 'https://redshift.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/redshift-vpc-private.xml')) - expect(subject.run).to eq([]) + expect(subject.run(true)).to eq([]) end it 'should handle clusters with a nil endpoint' do stub_request(:post, 'https://redshift.us-east-1.amazonaws.com') .to_return(body: ::IO.read('spec/fixtures/redshift-empty-endpoint.xml')) - expect { subject.run }.to raise_error(StandardError, /has a nil endpoint/) + expect { subject.run (true)}.to raise_error(StandardError, /has a nil endpoint/) end end