├── CODE_OF_CONDUCT.md
├── .rspec
├── .gitignore
├── Gemfile
├── Dockerfile
├── lib
├── aws_public_ips
│ ├── version.rb
│ ├── formatters.rb
│ ├── formatters
│ │ ├── json.rb
│ │ ├── prettyjson.rb
│ │ └── text.rb
│ ├── checks.rb
│ ├── checks
│ │ ├── cloudfront.rb
│ │ ├── apigateway.rb
│ │ ├── elb.rb
│ │ ├── elbv2.rb
│ │ ├── lightsail.rb
│ │ ├── rds.rb
│ │ ├── redshift.rb
│ │ ├── elasticsearch.rb
│ │ └── ec2.rb
│ ├── utils.rb
│ └── cli.rb
└── aws_public_ips.rb
├── spec
├── fixtures
│ ├── elasticsearch-list.json
│ ├── apigateway.json
│ ├── lightsail-load-balancer.json
│ ├── elasticsearch-describe-classic.json
│ ├── elasticsearch-describe-vpc.json
│ ├── lightsail-instance.json
│ ├── elb.xml
│ ├── redshift-empty-endpoint.xml
│ ├── elbv2.xml
│ ├── redshift-classic-public.xml
│ ├── redshift-vpc-public.xml
│ ├── redshift-vpc-private.xml
│ ├── ec2-private.xml
│ ├── rds-empty-endpoint.xml
│ ├── rds-vpc-private.xml
│ ├── rds-vpc-public.xml
│ ├── cloudfront.xml
│ └── ec2.xml
├── aws_public_ips
│ ├── formatters
│ │ ├── json_spec.rb
│ │ ├── prettyjson_spec.rb
│ │ └── text_spec.rb
│ ├── checks
│ │ ├── elb_spec.rb
│ │ ├── cloudfront_spec.rb
│ │ ├── apigateway_spec.rb
│ │ ├── elbv2_spec.rb
│ │ ├── lightsail_spec.rb
│ │ ├── elasticsearch_spec.rb
│ │ ├── ec2_spec.rb
│ │ ├── rds_spec.rb
│ │ └── redshift_spec.rb
│ ├── require_spec.rb
│ ├── utils_spec.rb
│ └── cli_spec.rb
└── spec_helper.rb
├── bin
└── aws_public_ips
├── .travis.yml
├── .rubocop_todo.yml
├── .rubocop.yml
├── LICENSE.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── aws_public_ips.gemspec
└── README.md
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | Treat everyone with respect.
2 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --order random
3 | --require spec_helper
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .bundle
3 | coverage/
4 | Gemfile.lock
5 | vendor/bundle
6 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 | gemspec
5 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:2.6.5-alpine
2 |
3 | USER nobody
4 |
5 | RUN gem install aws_public_ips
6 |
7 | CMD aws_public_ips
8 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AwsPublicIps
4 | VERSION = '1.0.7'.freeze
5 | end
6 |
--------------------------------------------------------------------------------
/spec/fixtures/elasticsearch-list.json:
--------------------------------------------------------------------------------
1 | {
2 | "DomainNames": [
3 | {
4 | "DomainName": "classic"
5 | },
6 | {
7 | "DomainName": "vpc"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/bin/aws_public_ips:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | $LOAD_PATH.unshift(::File.expand_path(::File.join('..', '..', 'lib'), __FILE__))
5 | require 'aws_public_ips/cli'
6 |
7 | ::AwsPublicIps::CLI.new.run(::ARGV)
8 |
--------------------------------------------------------------------------------
/lib/aws_public_ips.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AwsPublicIps
4 | end
5 |
6 | require 'aws_public_ips/checks'
7 | require 'aws_public_ips/cli'
8 | require 'aws_public_ips/formatters'
9 | require 'aws_public_ips/utils'
10 | require 'aws_public_ips/version'
11 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/formatters.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AwsPublicIps
4 | module Formatters
5 | end
6 | end
7 |
8 | require 'aws_public_ips/formatters/json'
9 | require 'aws_public_ips/formatters/prettyjson'
10 | require 'aws_public_ips/formatters/text'
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | dist: trusty
3 | rvm:
4 | - ruby-2.2
5 | - ruby-2.3
6 | - ruby-2.4
7 | - ruby-2.5
8 | - ruby-2.6
9 | - ruby-2.7
10 | services:
11 | - docker
12 | script:
13 | - bundle exec bundler-audit
14 | - bundle exec rubocop
15 | - bundle exec rspec
16 | - docker build .
17 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/formatters/json.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 |
5 | module AwsPublicIps
6 | module Formatters
7 | class Json
8 | def initialize(results, options)
9 | @results = results
10 | @options = options
11 | end
12 |
13 | def format
14 | @results.to_json
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/formatters/prettyjson.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 |
5 | module AwsPublicIps
6 | module Formatters
7 | class Prettyjson
8 | def initialize(results, options)
9 | @results = results
10 | @options = options
11 | end
12 |
13 | def format
14 | ::JSON.pretty_generate(@results)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/.rubocop_todo.yml:
--------------------------------------------------------------------------------
1 | # This configuration was generated by
2 | # `rubocop --auto-gen-config`
3 | # on 2018-05-11 18:49:11 -0700 using RuboCop version 0.55.0.
4 | # The point is for the user to remove these configuration records
5 | # one by one as the offenses are removed from the code base.
6 | # Note that changes in the inspected code, or installation of new
7 | # versions of RuboCop, may require this file to be generated again.
8 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/formatters/json_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Formatters::Json do
4 | it 'should output the right format' do
5 | results = {
6 | ec2: [{
7 | id: 'i-0f22d0af796b3cf3a',
8 | hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com',
9 | ip_addresses: %w[54.234.208.236]
10 | }]
11 | }
12 |
13 | expect(::AwsPublicIps::Formatters::Json.new(results, {}).format).to eq(results.to_json)
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AwsPublicIps
4 | module Checks
5 | end
6 | end
7 |
8 | require 'aws_public_ips/checks/apigateway'
9 | require 'aws_public_ips/checks/cloudfront'
10 | require 'aws_public_ips/checks/ec2'
11 | require 'aws_public_ips/checks/elasticsearch'
12 | require 'aws_public_ips/checks/elb'
13 | require 'aws_public_ips/checks/elbv2'
14 | require 'aws_public_ips/checks/lightsail'
15 | require 'aws_public_ips/checks/rds'
16 | require 'aws_public_ips/checks/redshift'
17 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/formatters/prettyjson_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Formatters::Prettyjson do
4 | it 'should output the right format' do
5 | results = {
6 | ec2: [{
7 | id: 'i-0f22d0af796b3cf3a',
8 | hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com',
9 | ip_addresses: %w[54.234.208.236]
10 | }]
11 | }
12 |
13 | expect(::AwsPublicIps::Formatters::Prettyjson.new(results, {}).format).to include('54.234.208.236')
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | inherit_from:
2 | - .rubocop_todo.yml
3 |
4 | Layout/IndentArray:
5 | EnforcedStyle: consistent
6 |
7 | Layout/IndentHash:
8 | EnforcedStyle: consistent
9 |
10 | Layout/MultilineMethodCallIndentation:
11 | EnforcedStyle: indented
12 |
13 | Layout/SpaceInsideHashLiteralBraces:
14 | EnforcedStyle: no_space
15 |
16 | Metrics/AbcSize:
17 | Enabled: false
18 |
19 | Metrics/BlockLength:
20 | Enabled: false
21 |
22 | Metrics/LineLength:
23 | Max: 120
24 |
25 | Metrics/MethodLength:
26 | Enabled: false
27 |
28 | Naming/PredicateName:
29 | Enabled: false
30 |
31 | Style/Documentation:
32 | Enabled: false
33 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/elb_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Elb do
4 | it 'should return elb ips' do
5 | stub_request(:post, 'https://elasticloadbalancing.us-east-1.amazonaws.com')
6 | .to_return(body: ::IO.read('spec/fixtures/elb.xml'))
7 |
8 | stub_dns(
9 | 'classic-272004174.us-east-1.elb.amazonaws.com' => %w[54.0.0.1],
10 | 'ipv6.classic-272004174.us-east-1.elb.amazonaws.com' => %w[2600:1f18:63e0:b401:b952:5715:d981:2776]
11 | )
12 |
13 | expect(subject.run).to eq([
14 | {
15 | id: 'Z35SXDOTRQ7X7K',
16 | hostname: 'classic-272004174.us-east-1.elb.amazonaws.com',
17 | ip_addresses: %w[54.0.0.1 2600:1f18:63e0:b401:b952:5715:d981:2776]
18 | }
19 | ])
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'coveralls'
4 | ::Coveralls.wear! do |config|
5 | # Output html report for development & default json report for Travis/Coveralls
6 | config.formatter = SimpleCov::Formatter::HTMLFormatter unless ::ENV['TRAVIS']
7 | end
8 | ::ENV['COVERALLS_NOISY'] = '1'
9 | require 'webmock/rspec'
10 | require 'aws_public_ips'
11 |
12 | # So the AWS gem doesn't try to hit the metadata endpoint
13 | ::ENV['AWS_REGION'] = 'us-east-1'
14 | ::ENV['AWS_ACCESS_KEY_ID'] = 'AAAAAAAAAAAAAAAAAAAA'
15 | ::ENV['AWS_SECRET_ACCESS_KEY'] = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
16 |
17 | def stub_dns(mapping)
18 | mapping.each do |hostname, ips|
19 | expect(::AwsPublicIps::Utils).to receive(:resolve_hostname).with(hostname).and_return(ips)
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/cloudfront_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Cloudfront do
4 | it 'should return cloudfront ips' do
5 | stub_request(:get, 'https://cloudfront.amazonaws.com/2018-06-18/distribution')
6 | .to_return(body: ::IO.read('spec/fixtures/cloudfront.xml'))
7 |
8 | stub_dns(
9 | 'd22ycgwdruc4lt.cloudfront.net' => %w[54.0.0.1 54.0.0.2],
10 | 'd1k00qwg2uxphp.cloudfront.net' => %w[54.0.0.3]
11 | )
12 | expect(subject.run).to eq([
13 | {
14 | id: 'E1DABYDY46RHFK',
15 | hostname: 'd22ycgwdruc4lt.cloudfront.net',
16 | ip_addresses: %w[54.0.0.1 54.0.0.2]
17 | },
18 | {
19 | id: 'E3SFCHHIPK43DR',
20 | hostname: 'd1k00qwg2uxphp.cloudfront.net',
21 | ip_addresses: %w[54.0.0.3]
22 | }
23 | ])
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/require_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe 'File requires' do
4 | def traverse(dir)
5 | results = {}
6 |
7 | ::Dir["#{dir}/*"].each do |path|
8 | next unless ::File.directory?(path)
9 | next unless ::File.exist?("#{path}.rb")
10 |
11 | results[path] = ::Dir["#{path}/*.rb"].map { |file| file.chomp('.rb') }
12 | end
13 |
14 | results
15 | end
16 |
17 | it 'should require all the right files' do
18 | stack = %w[lib]
19 |
20 | until stack.empty?
21 | matches = traverse(stack.pop)
22 | matches.each do |dir, files|
23 | stack.push(dir)
24 | expected_requires = files.sort.map do |file|
25 | "require '#{file.gsub(%r{^lib/}, '')}'"
26 | end.join("\n")
27 | expect(::IO.read("#{dir}.rb")).to include(expected_requires)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/formatters/text_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Formatters::Text do
4 | let(:entry) do
5 | {
6 | id: 'i-0f22d0af796b3cf3a',
7 | hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com',
8 | ip_addresses: %w[54.234.208.236]
9 | }
10 | end
11 |
12 | let(:results) do
13 | {
14 | ec2: [entry]
15 | }
16 | end
17 |
18 | it 'should output the right format' do
19 | expect(::AwsPublicIps::Formatters::Text.new(results, {}).format).to eq(entry[:ip_addresses].join("\n"))
20 | end
21 |
22 | it 'should output id and hostname if using verbose mode' do
23 | output = ::AwsPublicIps::Formatters::Text.new(results, verbose: true).format
24 | expect(output).to include(entry[:id])
25 | expect(output).to include(entry[:hostname])
26 | expect(output).to include(entry[:ip_addresses].join("\n"))
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/apigateway_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Apigateway do
4 | it 'should return gateway ips' do
5 | stub_request(:get, 'https://apigateway.us-east-1.amazonaws.com/restapis')
6 | .to_return(body: ::IO.read('spec/fixtures/apigateway.json'))
7 |
8 | stub_dns(
9 | 'e83d6nij2j.execute-api.us-east-1.amazonaws.com' => %w[54.0.0.1 54.0.0.2],
10 | 'tmtmok31nc.execute-api.us-east-1.amazonaws.com' => %w[54.0.0.3]
11 | )
12 |
13 | expect(subject.run).to eq([
14 | {
15 | id: 'e83d6nij2j',
16 | hostname: 'e83d6nij2j.execute-api.us-east-1.amazonaws.com',
17 | ip_addresses: %w[54.0.0.1 54.0.0.2]
18 | },
19 | {
20 | id: 'tmtmok31nc',
21 | hostname: 'tmtmok31nc.execute-api.us-east-1.amazonaws.com',
22 | ip_addresses: %w[54.0.0.3]
23 | }
24 | ])
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/fixtures/apigateway.json:
--------------------------------------------------------------------------------
1 | {
2 | "item": [
3 | {
4 | "apiKeySource": "HEADER",
5 | "createdDate": 1526178732,
6 | "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints",
7 | "endpointConfiguration": {
8 | "ipv6": false,
9 | "types": [
10 | "EDGE"
11 | ]
12 | },
13 | "id": "e83d6nij2j",
14 | "name": "PetStore"
15 | },
16 | {
17 | "apiKeySource": "HEADER",
18 | "createdDate": 1526178701,
19 | "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints",
20 | "endpointConfiguration": {
21 | "ipv6": false,
22 | "types": [
23 | "REGIONAL"
24 | ]
25 | },
26 | "id": "tmtmok31nc",
27 | "name": "PetStore"
28 | }
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/cloudfront.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-cloudfront'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Cloudfront
9 | def self.run
10 | client = ::Aws::CloudFront::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # Cloudfront distrubtions are always public, they don't have a concept of VPC
14 | # No "coming up" problem here like with RDS/Redshift
15 |
16 | client.list_distributions.flat_map do |response|
17 | response.distribution_list.items.flat_map do |distribution|
18 | {
19 | id: distribution.id,
20 | hostname: distribution.domain_name,
21 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(distribution.domain_name)
22 | }
23 | end
24 | end
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/formatters/text.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module AwsPublicIps
4 | module Formatters
5 | class Text
6 | def initialize(results, options)
7 | @results = results
8 | @options = options
9 | end
10 |
11 | def format
12 | lines = @options[:verbose] ? format_verbose : format_normal
13 | lines.uniq.join("\n")
14 | end
15 |
16 | def format_normal
17 | @results.values.flatten.flat_map do |hash|
18 | hash[:ip_addresses]
19 | end
20 | end
21 |
22 | def format_verbose
23 | @results.flat_map do |service, hashes|
24 | next [] if hashes.empty?
25 |
26 | ["## #{service}"] + hashes.flat_map do |hash|
27 | [hash[:id], hash[:hostname]].compact.map do |line|
28 | "# #{line}"
29 | end + hash[:ip_addresses]
30 | end
31 | end
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/elbv2_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Elbv2 do
4 | it 'should return elbv2 ips' do
5 | stub_request(:post, 'https://elasticloadbalancing.us-east-1.amazonaws.com')
6 | .to_return(body: ::IO.read('spec/fixtures/elbv2.xml'))
7 |
8 | stub_dns(
9 | 'nlb-vpc-d243d0acc9151631.elb.us-east-1.amazonaws.com' => %w[54.0.0.1],
10 | 'alb-vpc-228877692.us-east-1.elb.amazonaws.com' => %w[54.0.0.2 2600:1f18:63e0:b401:b952:5715:d981:2776]
11 | )
12 |
13 | expect(subject.run).to eq([
14 | {
15 | id: 'Z26RNL4JYFTOTI',
16 | hostname: 'nlb-vpc-d243d0acc9151631.elb.us-east-1.amazonaws.com',
17 | ip_addresses: %w[54.0.0.1]
18 | },
19 | {
20 | id: 'Z35SXDOTRQ7X7K',
21 | hostname: 'alb-vpc-228877692.us-east-1.elb.amazonaws.com',
22 | ip_addresses: %w[54.0.0.2 2600:1f18:63e0:b401:b952:5715:d981:2776]
23 | }
24 | ])
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/lightsail_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Lightsail do
4 | it 'should return lightsail ips' do
5 | stub_request(:post, 'https://lightsail.us-east-1.amazonaws.com')
6 | .to_return({body: ::IO.read('spec/fixtures/lightsail-instance.json')},
7 | body: ::IO.read('spec/fixtures/lightsail-load-balancer.json'))
8 |
9 | stub_dns(
10 | 'ce551c6f952085b4126e4b523a100eda-232829524.us-east-1.elb.amazonaws.com' => %w[54.88.163.90 52.205.146.152]
11 | )
12 |
13 | expect(subject.run).to eq([
14 | {
15 | id: 'Amazon_Linux-512MB-Virginia-1',
16 | hostname: nil,
17 | ip_addresses: %w[18.206.153.10]
18 | },
19 | {
20 | id: 'LoadBalancer-Virginia-1',
21 | hostname: 'ce551c6f952085b4126e4b523a100eda-232829524.us-east-1.elb.amazonaws.com',
22 | ip_addresses: %w[54.88.163.90 52.205.146.152]
23 | }
24 | ])
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Arkadiy Tetelman
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### 1.0.7 (11/7/2019)
2 | * Find all addresses when an EC2 instance has multiple ([@breser](https://github.com/breser))
3 | * Add Docker support
4 |
5 | ### 1.0.6 (10/26/2018)
6 | * Ignore services when they're not available in the requested region
7 | * Update dependencies
8 |
9 | ### 1.0.5 (05/25/2018)
10 | * Output more details in text formatter when using --verbose
11 |
12 | ### 1.0.4 (05/20/2018)
13 | * Handle RDS and Redshift instances which are in the process of coming up/down
14 | * Add --help, --version commands to CLI
15 | * Improve CLI error output
16 | * Fix issue where using the EC2 check with the JSON formatter could output empty entries
17 | * Fix issue with RDS check where the endpoint hostname was not being counted as a public IP
18 |
19 | ### 1.0.3 (05/17/2018)
20 | * Fix bug in relative file loading/checking
21 |
22 | ### 1.0.2 (05/15/2018)
23 | * Don't depend on bundler being installed
24 |
25 | ### 1.0.1 (05/15/2018)
26 | * Fix a bug where the gem was not installing an executable CLI script
27 |
28 | ### 1.0.0 (05/13/2018)
29 | * Initial release
30 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/apigateway.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-apigateway'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Apigateway
9 | def self.run
10 | client = ::Aws::APIGateway::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # TODO(arkadiy) https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-private-integration.html
14 |
15 | # APIGateway doesn't return the full domain in the response, we have to build
16 | # it using the api id and region
17 | client.get_rest_apis.flat_map do |response|
18 | response.items.map do |api|
19 | hostname = "#{api.id}.execute-api.#{client.config.region}.amazonaws.com"
20 | {
21 | id: api.id,
22 | hostname: hostname,
23 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(hostname)
24 | }
25 | end
26 | end
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/elasticsearch_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Elasticsearch do
4 | it 'should return elasticsearch ips' do
5 | stub_request(:get, 'https://es.us-east-1.amazonaws.com/2015-01-01/domain')
6 | .to_return(body: ::IO.read('spec/fixtures/elasticsearch-list.json'))
7 | stub_request(:get, 'https://es.us-east-1.amazonaws.com/2015-01-01/es/domain/classic')
8 | .to_return(body: ::IO.read('spec/fixtures/elasticsearch-describe-classic.json'))
9 | stub_request(:get, 'https://es.us-east-1.amazonaws.com/2015-01-01/es/domain/vpc')
10 | .to_return(body: ::IO.read('spec/fixtures/elasticsearch-describe-vpc.json'))
11 |
12 | stub_dns(
13 | 'search-classic-fd5cbkkjuuiudho2lrwmsjp6rm.us-east-1.es.amazonaws.com' => %w[54.0.0.1]
14 | )
15 |
16 | expect(subject.run).to eq([
17 | {
18 | id: '154967844790/classic',
19 | hostname: 'search-classic-fd5cbkkjuuiudho2lrwmsjp6rm.us-east-1.es.amazonaws.com',
20 | ip_addresses: %w[54.0.0.1]
21 | }
22 | ])
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/utils.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'resolv'
4 | require 'aws-partitions'
5 |
6 | module AwsPublicIps
7 | module Utils
8 | def self.resolve_hostnames(hostnames)
9 | hostnames.flat_map(&method(:resolve_hostname))
10 | end
11 |
12 | def self.resolve_hostname(hostname)
13 | # Default Resolv.getaddresses doesn't seem to return IPv6 results
14 | resources = ::Resolv::DNS.open do |dns|
15 | dns.getresources(hostname, ::Resolv::DNS::Resource::IN::A) +
16 | dns.getresources(hostname, ::Resolv::DNS::Resource::IN::AAAA)
17 | end
18 |
19 | resources.map do |resource|
20 | resource.address.to_s.downcase
21 | end
22 | end
23 |
24 | def self.has_service?(client)
25 | region_partition = ::Aws::Partitions.partitions.find do |partition|
26 | partition.regions.map(&:name).include?(client.config.region)
27 | end
28 | service_name = client.class.to_s.split('::')[-2]
29 |
30 | aws_service = region_partition.services.find { |service| service.name == service_name }
31 | !aws_service.regionalized? || aws_service.regions.include?(client.config.region)
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/utils_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Utils do
4 | it 'should resolve a single hostname' do
5 | hostname = 'www.example.com'
6 |
7 | expect(::Resolv::DNS).to receive(:open) do |&block|
8 | dns = double('dns')
9 | expect(dns).to receive(:getresources).with(hostname, ::Resolv::DNS::Resource::IN::A)
10 | .and_return([double(address: '54.0.0.1')])
11 | expect(dns).to receive(:getresources).with(hostname, ::Resolv::DNS::Resource::IN::AAAA)
12 | .and_return([double(address: '2606:2800:220:1:248:1893:25c8:1946')])
13 | block.call(dns)
14 | end
15 |
16 | expect(::AwsPublicIps::Utils.resolve_hostname(hostname)).to eq(%w[54.0.0.1 2606:2800:220:1:248:1893:25c8:1946])
17 | end
18 |
19 | it 'should resolve multiple hostnames' do
20 | mapping = {
21 | 'example.com' => %w[54.0.0.1],
22 | 'www.example.com' => %w[54.0.0.2]
23 | }
24 |
25 | mapping.each do |hostname, ips|
26 | expect(::AwsPublicIps::Utils).to receive(:resolve_hostname).with(hostname).and_return(ips)
27 | end
28 |
29 | expect(::AwsPublicIps::Utils.resolve_hostnames(mapping.keys)).to eq(mapping.values.flatten)
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/elb.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-elasticloadbalancing'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Elb
9 | def self.run
10 | client = ::Aws::ElasticLoadBalancing::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # EC2-Classic load balancers are only returned by the 'elasticloadbalancing' API, and
14 | # EC2-VPC ALBs/NLBs are only returned by the 'elasticloadbalancingv2' API
15 | client.describe_load_balancers.flat_map do |response|
16 | response.load_balancer_descriptions.flat_map do |load_balancer|
17 | next [] unless load_balancer.scheme == 'internet-facing'
18 |
19 | # EC2-Classic load balancers get IPv6 DNS records created but they are not returned by the API
20 | hostnames = [load_balancer.dns_name, "ipv6.#{load_balancer.dns_name}"]
21 | {
22 | id: load_balancer.canonical_hosted_zone_name_id,
23 | hostname: load_balancer.dns_name,
24 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostnames(hostnames)
25 | }
26 | end
27 | end
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/elbv2.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-elasticloadbalancingv2'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Elbv2
9 | def self.run
10 | client = ::Aws::ElasticLoadBalancingV2::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # EC2-Classic load balancers are only returned by the 'elasticloadbalancing' API, and
14 | # EC2-VPC ALBs/NLBs are only returned by the 'elasticloadbalancingv2' API
15 |
16 | # NLBs only support IPv4
17 | # ALBs support IPv4 or dualstack. Unlike Classic ELBs which have a separate IPv6 DNS name,
18 | # dualstack ALBs only have a single DNS name
19 | client.describe_load_balancers.flat_map do |response|
20 | response.load_balancers.flat_map do |load_balancer|
21 | next [] unless load_balancer.scheme == 'internet-facing'
22 |
23 | {
24 | id: load_balancer.canonical_hosted_zone_id,
25 | hostname: load_balancer.dns_name,
26 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(load_balancer.dns_name)
27 | }
28 | end
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/fixtures/lightsail-load-balancer.json:
--------------------------------------------------------------------------------
1 | {
2 | "loadBalancers": [
3 | {
4 | "arn": "arn:aws:lightsail:us-east-1:154967844790:LoadBalancer/542e0d8d-e57a-4bea-8132-53a8b0cd0de4",
5 | "configurationOptions": {
6 | "SessionStickinessEnabled": "false",
7 | "SessionStickiness_LB_CookieDurationSeconds": "86400"
8 | },
9 | "createdAt": 1526182918.935,
10 | "dnsName": "ce551c6f952085b4126e4b523a100eda-232829524.us-east-1.elb.amazonaws.com",
11 | "healthCheckPath": "/",
12 | "instanceHealthSummary": [
13 | {
14 | "instanceHealth": "initial",
15 | "instanceHealthReason": "Lb.RegistrationInProgress",
16 | "instanceName": "Amazon_Linux-512MB-Virginia-1"
17 | }
18 | ],
19 | "instancePort": 80,
20 | "location": {
21 | "availabilityZone": "all",
22 | "regionName": "us-east-1"
23 | },
24 | "name": "LoadBalancer-Virginia-1",
25 | "protocol": "HTTP",
26 | "publicPorts": [
27 | 80
28 | ],
29 | "resourceType": "LoadBalancer",
30 | "state": "provisioning",
31 | "supportCode": "083651072206/arn:aws:elasticloadbalancing:us-east-1:083651072206:loadbalancer/app/ce551c6f952085b4126e4b523a100eda/727fb77509ebef09",
32 | "tlsCertificateSummaries": []
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/ec2_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Ec2 do
4 | it 'should return ec2 ips' do
5 | stub_request(:post, 'https://ec2.us-east-1.amazonaws.com')
6 | .to_return(body: ::IO.read('spec/fixtures/ec2.xml'))
7 |
8 | expect(subject.run).to eq([
9 | {
10 | id: 'i-0f22d0af796b3cf3a',
11 | hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com',
12 | ip_addresses: %w[54.234.208.236]
13 | },
14 | {
15 | id: 'i-04ef469b441883eda',
16 | hostname: 'ec2-18-206-76-65.compute-1.amazonaws.com',
17 | ip_addresses: %w[18.206.76.65 2600:1f18:63e0:b400:f50c:59a7:a182:3717]
18 | },
19 | {
20 | id: 'i-03a7b3bc2b4c20742',
21 | hostname: nil,
22 | ip_addresses: %w[2600:1f18:60f3:eb00:1c6e:5184:8955:170c]
23 | },
24 | {
25 | id: 'i-01e4cbbe2c7fb98f6',
26 | hostname: 'ec2-50-112-85-68.us-west-2.compute.amazonaws.com',
27 | ip_addresses: %w[50.112.85.68 54.214.97.117]
28 | }
29 | ])
30 | end
31 |
32 | it 'should not return an entry when there are no public ips' do
33 | stub_request(:post, 'https://ec2.us-east-1.amazonaws.com')
34 | .to_return(body: ::IO.read('spec/fixtures/ec2-private.xml'))
35 | expect(subject.run).to eq([])
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/lightsail.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-lightsail'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Lightsail
9 | def self.run
10 | client = ::Aws::Lightsail::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # Lightsail instances are always exposed directly, and can also be put behind a load balancer
14 |
15 | instances = client.get_instances.flat_map do |response|
16 | response.instances.map do |instance|
17 | {
18 | # Names are unique
19 | id: instance.name,
20 | hostname: nil,
21 | ip_addresses: [instance.public_ip_address]
22 | }
23 | end
24 | end
25 |
26 | load_balancers = client.get_load_balancers.flat_map do |response|
27 | response.load_balancers.map do |load_balancer|
28 | {
29 | # Names are unique
30 | id: load_balancer.name,
31 | hostname: load_balancer.dns_name,
32 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(load_balancer.dns_name)
33 | }
34 | end
35 | end
36 |
37 | instances + load_balancers
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/rds.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-rds'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Rds
9 | def self.run
10 | client = ::Aws::RDS::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # RDS instances can be launched into VPCs or into Classic mode.
14 | # In classic mode they are always public.
15 | # In VPC mode they can be marked as `publicly_accessible` or not - if they are then its VPC must have
16 | # an Internet Gateway attached, and the DNS endpoint will resolve to a public ip address.
17 | client.describe_db_instances.flat_map do |response|
18 | response.db_instances.flat_map do |instance|
19 | next [] unless instance.publicly_accessible
20 |
21 | if instance.endpoint.nil?
22 | raise StandardError, "RDS DB '#{instance.dbi_resource_id}' has a nil endpoint. This likely" \
23 | ' means the DB is being brought up right now.'
24 | end
25 |
26 | {
27 | id: instance.dbi_resource_id,
28 | hostname: instance.endpoint.address,
29 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(instance.endpoint.address)
30 | }
31 | end
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | Thank you for your interest in contributing to aws_public_ips!
4 |
5 | ### Code of conduct
6 |
7 | Please adhere to the [code of conduct](https://github.com/arkadiyt/aws_public_ips/blob/master/CODE_OF_CONDUCT.md).
8 |
9 | ### Bugs
10 |
11 | **Known issues:** Before reporting new bugs, search if your issue already exists in the [open issues](https://github.com/arkadiyt/aws_public_ips/issues).
12 |
13 | **Reporting new issues:** Provide a reduced test case with clear reproduction steps.
14 |
15 | **Security issues:** If you believe you've found a security issue please disclose it privately first, either through my [vulnerability disclosure program](https://hackerone.com/arkadiyt-projects) on Hackerone or by direct messaging me on [twitter](https://twitter.com/arkadiyt).
16 |
17 | ### Proposing a change
18 |
19 | If you plan on making large changes, please file an issue before submitting a pull request so we can reach agreement on your proposal.
20 |
21 | ### Sending a pull request
22 |
23 | 1. Fork this repository
24 | 2. Check out a feature branch: `git checkout -b your-feature-branch`
25 | 3. Make changes on your branch
26 | 4. Add/update tests - this project maintains 100% code coverage
27 | 5. Make sure all status checks pass locally:
28 | - `bundle exec bundler-audit`
29 | - `bundle exec rubocop`
30 | - `bundle exec rspec`
31 | 6. Submit a pull request with a description of your changes
32 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/redshift.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-redshift'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Redshift
9 | def self.run
10 | client = ::Aws::Redshift::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # Redshift clusters can be launched into VPCs or into Classic mode.
14 | # In classic mode they are always public.
15 | # In VPC mode they can be marked as `publicly_accessible` or not - if they are then its VPC must have
16 | # an Internet Gateway attached, and the DNS endpoint will resolve to a public ip address.
17 | client.describe_clusters.flat_map do |response|
18 | response.clusters.flat_map do |cluster|
19 | next [] unless cluster.publicly_accessible
20 |
21 | if cluster.endpoint.nil?
22 | raise StandardError, "Redshift cluster '#{cluster.cluster_identifier}' has a nil endpoint. This likely" \
23 | ' means the cluster is being brought up right now.'
24 | end
25 |
26 | {
27 | id: cluster.cluster_identifier,
28 | hostname: cluster.endpoint.address,
29 | ip_addresses: cluster.cluster_nodes.map(&:public_ip_address) +
30 | ::AwsPublicIps::Utils.resolve_hostname(cluster.endpoint.address)
31 | }
32 | end
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/elasticsearch.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-elasticsearchservice'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Elasticsearch
9 | def self.run
10 | client = ::Aws::ElasticsearchService::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # ElasticSearch instances can be launched into classic into VPCs. Classic instances are public and have a
14 | # `domain_status.endpoint` hostname, and VPC instances have a `domain_status.endpoints['vpc']` hostname.
15 | # However VPC ElasticSearch instances create their own Network Interface and AWS will not allow you
16 | # to associate an Elastic IP to it. As a result VPC ElasticSearch instances are always private, even with an
17 | # internet gateway.
18 |
19 | client.list_domain_names.flat_map do |response|
20 | response.domain_names.flat_map do |domain_name|
21 | client.describe_elasticsearch_domain(domain_name: domain_name.domain_name).map do |domain|
22 | hostname = domain.domain_status.endpoint
23 | next unless hostname
24 |
25 | {
26 | id: domain.domain_status.domain_id,
27 | hostname: hostname,
28 | ip_addresses: ::AwsPublicIps::Utils.resolve_hostname(hostname)
29 | }
30 | end.compact
31 | end
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/rds_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Rds do
4 | it 'should return rds ips for vpc public instances' do
5 | stub_request(:post, 'https://rds.us-east-1.amazonaws.com')
6 | .to_return(body: ::IO.read('spec/fixtures/rds-vpc-public.xml'))
7 |
8 | stub_dns(
9 | 'rds-vpc-public.cyvjlokb0o75.us-east-1.rds.amazonaws.com' => %w[35.171.145.174],
10 | 'rds-vpc-public-us-east-1a.cyvjlokb0o75.us-east-1.rds.amazonaws.com' => %w[52.70.34.110]
11 | )
12 |
13 | expect(subject.run).to eq([
14 | {
15 | id: 'db-BAKGGXYRB3EBKBDQZTAMDSGCXY',
16 | hostname: 'rds-vpc-public.cyvjlokb0o75.us-east-1.rds.amazonaws.com',
17 | ip_addresses: %w[35.171.145.174]
18 | },
19 | {
20 | id: 'db-B3N4GULDAFGDKEGXBD7CXKZQV4',
21 | hostname: 'rds-vpc-public-us-east-1a.cyvjlokb0o75.us-east-1.rds.amazonaws.com',
22 | ip_addresses: %w[52.70.34.110]
23 | }
24 | ])
25 | end
26 |
27 | it 'should return nothing for vpc private db instances' do
28 | stub_request(:post, 'https://rds.us-east-1.amazonaws.com')
29 | .to_return(body: ::IO.read('spec/fixtures/rds-vpc-private.xml'))
30 |
31 | expect(subject.run).to eq([])
32 | end
33 |
34 | it 'should handle db instances with a nil endpoint' do
35 | stub_request(:post, 'https://rds.us-east-1.amazonaws.com')
36 | .to_return(body: ::IO.read('spec/fixtures/rds-empty-endpoint.xml'))
37 |
38 | expect { subject.run }.to raise_error(StandardError, /has a nil endpoint/)
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/fixtures/elasticsearch-describe-classic.json:
--------------------------------------------------------------------------------
1 | {
2 | "DomainStatus": {
3 | "ARN": "arn:aws:es:us-east-1:154967844790:domain/classic",
4 | "AccessPolicies": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"es:*\",\"Resource\":\"arn:aws:es:us-east-1:154967844790:domain/classic/*\"}]}",
5 | "AdvancedOptions": {
6 | "rest.action.multi.allow_explicit_index": "true"
7 | },
8 | "CognitoOptions": {
9 | "Enabled": false,
10 | "IdentityPoolId": null,
11 | "RoleArn": null,
12 | "UserPoolId": null
13 | },
14 | "Created": true,
15 | "Deleted": false,
16 | "DomainId": "154967844790/classic",
17 | "DomainName": "classic",
18 | "EBSOptions": {
19 | "EBSEnabled": true,
20 | "Iops": null,
21 | "VolumeSize": 10,
22 | "VolumeType": "gp2"
23 | },
24 | "ElasticsearchClusterConfig": {
25 | "DedicatedMasterCount": 3,
26 | "DedicatedMasterEnabled": true,
27 | "DedicatedMasterType": "m4.large.elasticsearch",
28 | "InstanceCount": 1,
29 | "InstanceType": "m4.large.elasticsearch",
30 | "ZoneAwarenessEnabled": false
31 | },
32 | "ElasticsearchVersion": "6.2",
33 | "EncryptionAtRestOptions": {
34 | "Enabled": false,
35 | "KmsKeyId": null
36 | },
37 | "Endpoint": "search-classic-fd5cbkkjuuiudho2lrwmsjp6rm.us-east-1.es.amazonaws.com",
38 | "Endpoints": null,
39 | "LogPublishingOptions": null,
40 | "Processing": false,
41 | "SnapshotOptions": {
42 | "AutomatedSnapshotStartHour": 0
43 | },
44 | "VPCOptions": null
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/aws_public_ips.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | $LOAD_PATH.unshift ::File.expand_path('lib', __dir__)
4 | require 'aws_public_ips/version'
5 |
6 | ::Gem::Specification.new do |gem|
7 | gem.name = 'aws_public_ips'
8 | gem.platform = ::Gem::Platform::RUBY
9 | gem.version = ::AwsPublicIps::VERSION
10 | gem.authors = ['Arkadiy Tetelman']
11 | gem.required_ruby_version = '>= 2.2.0'
12 | gem.summary = 'A library/cli to fetch all public IP addresses associated with an AWS account'
13 | gem.description = gem.summary
14 | gem.homepage = 'https://github.com/arkadiyt/aws_public_ips'
15 | gem.license = 'MIT'
16 | gem.files = ::Dir['lib/**/*.rb'] + ::Dir['bin/*']
17 | gem.bindir = 'bin'
18 | gem.executables = 'aws_public_ips'
19 |
20 | gem.add_dependency('aws-sdk-apigateway', '~> 1.21.0')
21 | gem.add_dependency('aws-sdk-cloudfront', '~> 1.10.0')
22 | gem.add_dependency('aws-sdk-ec2', '~> 1.54.0')
23 | gem.add_dependency('aws-sdk-elasticloadbalancing', '~> 1.7.0')
24 | gem.add_dependency('aws-sdk-elasticloadbalancingv2', '~> 1.16.0')
25 | gem.add_dependency('aws-sdk-elasticsearchservice', '~> 1.14.0')
26 | gem.add_dependency('aws-sdk-lightsail', '~> 1.10.0')
27 | gem.add_dependency('aws-sdk-rds', '~> 1.35.0')
28 | gem.add_dependency('aws-sdk-redshift', '~> 1.13.0')
29 |
30 | gem.add_development_dependency('bundler-audit', '~> 0.6.0')
31 | gem.add_development_dependency('coveralls', '~> 0.8.22')
32 | gem.add_development_dependency('rspec', '~> 3.8.0')
33 | gem.add_development_dependency('rubocop', '~> 0.65.0')
34 | gem.add_development_dependency('webmock', '~> 3.4.2')
35 | end
36 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/checks/redshift_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::Checks::Redshift do
4 | it 'should return redshift ips for classic public clusters' do
5 | stub_request(:post, 'https://redshift.us-east-1.amazonaws.com')
6 | .to_return(body: ::IO.read('spec/fixtures/redshift-classic-public.xml'))
7 |
8 | expect(subject.run).to eq([
9 | {
10 | id: 'classic',
11 | hostname: 'classic.csorkyt5dk7h.us-east-1.redshift.amazonaws.com',
12 | ip_addresses: %w[54.167.97.240 54.91.252.196 54.242.227.110]
13 | }
14 | ])
15 | end
16 |
17 | it 'should return redshift ips for vpc public clusters' do
18 | stub_request(:post, 'https://redshift.us-east-1.amazonaws.com')
19 | .to_return(body: ::IO.read('spec/fixtures/redshift-vpc-public.xml'))
20 |
21 | stub_dns(
22 | 'vpc-public-2.csorkyt5dk7h.us-east-1.redshift.amazonaws.com' => %w[54.156.7.130]
23 | )
24 | expect(subject.run).to eq([
25 | {
26 | id: 'vpc-public-2',
27 | hostname: 'vpc-public-2.csorkyt5dk7h.us-east-1.redshift.amazonaws.com',
28 | ip_addresses: %w[52.44.170.10 54.209.53.206 54.208.75.129 54.156.7.130]
29 | }
30 | ])
31 | end
32 |
33 | it 'should return nothing for vpc private clusters' do
34 | stub_request(:post, 'https://redshift.us-east-1.amazonaws.com')
35 | .to_return(body: ::IO.read('spec/fixtures/redshift-vpc-private.xml'))
36 |
37 | expect(subject.run).to eq([])
38 | end
39 |
40 | it 'should handle clusters with a nil endpoint' do
41 | stub_request(:post, 'https://redshift.us-east-1.amazonaws.com')
42 | .to_return(body: ::IO.read('spec/fixtures/redshift-empty-endpoint.xml'))
43 | expect { subject.run }.to raise_error(StandardError, /has a nil endpoint/)
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/aws_public_ips/cli_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | describe ::AwsPublicIps::CLI do
4 | it 'should parse the options' do
5 | options = subject.parse(%w[--format json --services ec2,elb,redshift --verbose])
6 | expect(options).to eq(format: 'json', services: %w[ec2 elb redshift], verbose: true)
7 | end
8 |
9 | it 'should raise on an invalid formatter' do
10 | expect { subject.parse(%w[--format blah]) }.to raise_error(::ArgumentError, /Invalid format/)
11 | end
12 |
13 | it 'should raise on an invalid service' do
14 | expect { subject.parse(%w[--service blah]) }.to raise_error(::ArgumentError, /Invalid service/)
15 | end
16 |
17 | it 'should select the right directory' do
18 | ::Dir.chdir('/') do
19 | options = subject.parse(%w[--service ec2 --format prettyjson])
20 | expect(options).to include(services: %w[ec2], format: 'prettyjson')
21 | end
22 | end
23 |
24 | it 'should run' do
25 | expect(::AwsPublicIps::Checks::Ec2).to receive(:run).and_return([{
26 | id: 'i-0f22d0af796b3cf3a',
27 | hostname: 'ec2-54-234-208-236.compute-1.amazonaws.com',
28 | ip_addresses: %w[54.234.208.236]
29 | }])
30 | expect(::STDOUT).to receive(:puts)
31 | subject.run(['-s', 'ec2'])
32 | end
33 |
34 | it 'should rescue exceptions' do
35 | expect(subject).to receive(:check_service).and_raise(::StandardError)
36 | expect(::Process).to receive(:exit).with(1)
37 | expect(::STDERR).to receive(:puts)
38 | subject.run(['-s', 'ec2'])
39 | end
40 |
41 | it 'should print the version' do
42 | expect(::STDOUT).to receive(:puts).with(::AwsPublicIps::VERSION)
43 | subject.run(['--version'])
44 | end
45 |
46 | it 'should print help' do
47 | expect(::STDOUT).to receive(:puts)
48 | subject.run(['--help'])
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/fixtures/elasticsearch-describe-vpc.json:
--------------------------------------------------------------------------------
1 | {
2 | "DomainStatus": {
3 | "ARN": "arn:aws:es:us-east-1:154967844790:domain/vpc",
4 | "AccessPolicies": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"es:*\",\"Resource\":\"arn:aws:es:us-east-1:154967844790:domain/vpc/*\"}]}",
5 | "AdvancedOptions": {
6 | "rest.action.multi.allow_explicit_index": "true"
7 | },
8 | "CognitoOptions": {
9 | "Enabled": false,
10 | "IdentityPoolId": null,
11 | "RoleArn": null,
12 | "UserPoolId": null
13 | },
14 | "Created": true,
15 | "Deleted": false,
16 | "DomainId": "154967844790/vpc",
17 | "DomainName": "vpc",
18 | "EBSOptions": {
19 | "EBSEnabled": true,
20 | "Iops": null,
21 | "VolumeSize": 10,
22 | "VolumeType": "gp2"
23 | },
24 | "ElasticsearchClusterConfig": {
25 | "DedicatedMasterCount": null,
26 | "DedicatedMasterEnabled": false,
27 | "DedicatedMasterType": null,
28 | "InstanceCount": 1,
29 | "InstanceType": "m4.large.elasticsearch",
30 | "ZoneAwarenessEnabled": false
31 | },
32 | "ElasticsearchVersion": "6.2",
33 | "EncryptionAtRestOptions": {
34 | "Enabled": false,
35 | "KmsKeyId": null
36 | },
37 | "Endpoint": null,
38 | "Endpoints": {
39 | "vpc": "vpc-vpc-ncoseatahpr5ywmjpukt4xra5q.us-east-1.es.amazonaws.com"
40 | },
41 | "LogPublishingOptions": null,
42 | "Processing": false,
43 | "SnapshotOptions": {
44 | "AutomatedSnapshotStartHour": 0
45 | },
46 | "VPCOptions": {
47 | "AvailabilityZones": [
48 | "us-east-1f"
49 | ],
50 | "SecurityGroupIds": [
51 | "sg-f2ce17ba"
52 | ],
53 | "SubnetIds": [
54 | "subnet-f4be30fb"
55 | ],
56 | "VPCId": "vpc-23a48958"
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/checks/ec2.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'aws-sdk-ec2'
4 | require 'aws_public_ips/utils'
5 |
6 | module AwsPublicIps
7 | module Checks
8 | module Ec2
9 | def self.run
10 | client = ::Aws::EC2::Client.new
11 | return [] unless ::AwsPublicIps::Utils.has_service?(client)
12 |
13 | # Iterate over all EC2 instances. This will include those from EC2, ECS, EKS, Fargate, Batch,
14 | # Beanstalk, and NAT Instances
15 | # It will not include NAT Gateways (IPv4) or Egress Only Internet Gateways (IPv6), but they do not allow
16 | # ingress traffic so we skip them anyway
17 | client.describe_instances.flat_map do |response|
18 | response.reservations.flat_map do |reservation|
19 | reservation.instances.flat_map do |instance|
20 | # EC2-Classic instances have a `public_ip_address` and no `network_interfaces`
21 | # EC2-VPC instances both set, so we uniq the ip addresses
22 | ip_addresses = [instance.public_ip_address].compact + instance.network_interfaces.flat_map do |interface|
23 | public_ip = []
24 |
25 | interface.private_ip_addresses.flat_map do |private_ip|
26 | if private_ip.association && private_ip.association.public_ip
27 | public_ip << private_ip.association.public_ip
28 | end
29 | end
30 | public_ip + interface.ipv_6_addresses.map(&:ipv_6_address)
31 | end
32 |
33 | # Don't return an entry if all ips were private
34 | next [] if ip_addresses.empty?
35 |
36 | # If hostname is empty string, canonicalize to nil
37 | hostname = instance.public_dns_name.empty? ? nil : instance.public_dns_name
38 | {
39 | id: instance.instance_id,
40 | hostname: hostname,
41 | ip_addresses: ip_addresses.uniq
42 | }
43 | end
44 | end
45 | end
46 | end
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/spec/fixtures/lightsail-instance.json:
--------------------------------------------------------------------------------
1 | {
2 | "instances": [
3 | {
4 | "arn": "arn:aws:lightsail:us-east-1:154967844790:Instance/4854f8f4-8572-43d1-aa45-c76f1df66f8d",
5 | "blueprintId": "amazon_linux_2017_09_1_2",
6 | "blueprintName": "Amazon Linux",
7 | "bundleId": "nano_1_0",
8 | "createdAt": 1526182910.872,
9 | "hardware": {
10 | "cpuCount": 1,
11 | "disks": [
12 | {
13 | "attachedTo": "Amazon_Linux-512MB-Virginia-1",
14 | "attachmentState": "attached",
15 | "createdAt": 1526182910.872,
16 | "iops": 100,
17 | "isSystemDisk": true,
18 | "path": "/dev/xvda",
19 | "sizeInGb": 20
20 | }
21 | ],
22 | "ramSizeInGb": 0.5
23 | },
24 | "isStaticIp": false,
25 | "location": {
26 | "availabilityZone": "us-east-1a",
27 | "regionName": "us-east-1"
28 | },
29 | "name": "Amazon_Linux-512MB-Virginia-1",
30 | "networking": {
31 | "monthlyTransfer": {
32 | "gbPerMonthAllocated": 1024
33 | },
34 | "ports": [
35 | {
36 | "accessDirection": "inbound",
37 | "accessFrom": "Anywhere (0.0.0.0/0)",
38 | "accessType": "public",
39 | "commonName": "",
40 | "fromPort": 80,
41 | "protocol": "tcp",
42 | "toPort": 80
43 | },
44 | {
45 | "accessDirection": "inbound",
46 | "accessFrom": "Anywhere (0.0.0.0/0)",
47 | "accessType": "public",
48 | "commonName": "",
49 | "fromPort": 22,
50 | "protocol": "tcp",
51 | "toPort": 22
52 | }
53 | ]
54 | },
55 | "privateIpAddress": "172.26.4.200",
56 | "publicIpAddress": "18.206.153.10",
57 | "resourceType": "Instance",
58 | "sshKeyName": "LightsailDefaultKeyPair",
59 | "state": {
60 | "code": 16,
61 | "name": "running"
62 | },
63 | "supportCode": "083651072206/i-019d2da9fda7e1bbf",
64 | "username": "ec2-user"
65 | }
66 | ]
67 | }
68 |
--------------------------------------------------------------------------------
/spec/fixtures/elb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Z35SXDOTRQ7X7K
7 | internet-facing
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | us-east-1a
16 |
17 | classic-272004174.us-east-1.elb.amazonaws.com
18 |
19 |
20 | amazon-elb
21 | amazon-elb-sg
22 |
23 |
24 |
25 |
26 | 80
27 | HTTP
28 | HTTP
29 | 80
30 |
31 |
32 |
33 |
34 | classic
35 |
36 | 2
37 | 30
38 | 10
39 | 5
40 | HTTP:80/index.html
41 |
42 | 2018-05-13T03:20:20.830Z
43 |
44 |
45 | classic-272004174.us-east-1.elb.amazonaws.com
46 |
47 |
48 |
49 |
50 | 840ea6f9-565d-11e8-bbe4-a56c8ac3fd36
51 |
52 |
53 |
--------------------------------------------------------------------------------
/spec/fixtures/redshift-empty-endpoint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | classic-private
7 | 2058
8 | 2
9 | 1.0
10 | true
11 | admin
12 | dev
13 | false
14 |
15 |
16 |
17 | default
18 | active
19 |
20 |
21 | ds2.8xlarge
22 |
23 |
24 |
25 |
26 | default.redshift-1.0
27 | in-sync
28 |
29 |
30 | false
31 |
32 |
33 | LEADER
34 |
35 |
36 | COMPUTE-0
37 |
38 |
39 | COMPUTE-1
40 |
41 |
42 |
43 | ****
44 |
45 | fri:08:30-fri:09:00
46 | 1
47 | creating
48 |
49 |
50 |
51 |
52 | 61692f3a-5c81-11e8-a732-9da506d397b6
53 |
54 |
55 |
--------------------------------------------------------------------------------
/spec/fixtures/elbv2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | arn:aws:elasticloadbalancing:us-east-1:154967844790:loadbalancer/net/nlb-vpc/d243d0acc9151631
7 | internet-facing
8 |
9 |
10 | subnet-f4be30fb
11 | us-east-1f
12 |
13 |
14 |
15 |
16 |
17 | nlb-vpc-d243d0acc9151631.elb.us-east-1.amazonaws.com
18 | network
19 | ipv4
20 | nlb-vpc
21 | vpc-23a48958
22 | Z26RNL4JYFTOTI
23 | 2018-05-13T03:26:42.946Z
24 |
25 | active
26 |
27 |
28 |
29 | arn:aws:elasticloadbalancing:us-east-1:154967844790:loadbalancer/app/alb-vpc/7bf8de9a53767b79
30 | internet-facing
31 |
32 |
33 | subnet-b61fecea
34 | us-east-1a
35 |
36 |
37 | subnet-f4be30fb
38 | us-east-1f
39 |
40 |
41 | alb-vpc-228877692.us-east-1.elb.amazonaws.com
42 | application
43 | dualstack
44 | alb-vpc
45 | vpc-23a48958
46 | Z35SXDOTRQ7X7K
47 | 2018-05-13T03:25:59.250Z
48 |
49 | sg-f2ce17ba
50 |
51 |
52 | active
53 |
54 |
55 |
56 |
57 |
58 | ce4fe5bc-565d-11e8-bb48-774de7ae8e01
59 |
60 |
61 |
--------------------------------------------------------------------------------
/spec/fixtures/redshift-classic-public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true
7 | classic
8 | 2058
9 | 2
10 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCSPmQsGIwwL/bitvJ7h0FVoryK8+I7p2hWs1t77bitoi/gCGvqUENS1bnK39bDJRq9Mtzn7nqs1CnvETcPm1kTOOX26mi8WNgLflDFgCmtul2v/bU9JS1gkZ3XA5NeD50PD1PAUvld35F0bi1v0tKIL5TQ40fWCGzgcb7VhyrWExbPw3f7WkggjB4xftb9N717evyy2HtWwwZs0J07oY/tZj2HYg/8BjcVB/T+RXu7stRHJW5AWVw2i6UbZ/W/3au9UAA4H8szJmc+kz2Kf2Ob96U2eV/IV+60K2dElmUZNfrt1UDGCurBbUBcbceyNuWD2CqQEXGssbZH0C0WG7SF Amazon-Redshift
11 | us-east-1d
12 | 1.0
13 |
14 | 5439
15 | classic.csorkyt5dk7h.us-east-1.redshift.amazonaws.com
16 |
17 | true
18 | 2018-05-13T04:33:43.549Z
19 | admin
20 | dev
21 | false
22 |
23 |
24 |
25 | default
26 | active
27 |
28 |
29 | dc1.large
30 |
31 |
32 |
33 |
34 | default.redshift-1.0
35 | in-sync
36 |
37 |
38 | false
39 |
40 |
41 | 10.186.39.210
42 | LEADER
43 | 54.167.97.240
44 |
45 |
46 | 10.35.228.3
47 | COMPUTE-0
48 | 54.91.252.196
49 |
50 |
51 | 10.218.185.143
52 | COMPUTE-1
53 | 54.242.227.110
54 |
55 |
56 |
57 | wed:09:00-wed:09:30
58 | 1
59 | available
60 |
61 |
62 |
63 |
64 | 2e397df0-5667-11e8-8d61-2b67811cfc51
65 |
66 |
67 |
--------------------------------------------------------------------------------
/spec/fixtures/redshift-vpc-public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true
7 | vpc-public-2
8 | 2058
9 | 2
10 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCRYweW+m8TP/PdsScndXIZn+ZPUBuUUuwjP1450y2ralYX57O9HHyGEhLt8LZIECEPa0Mw14OIbHW/x3QbO+6KSUaWN6erppkEhrlGIhjPSTq9JEUHngMIQiEEcrUla3Jj7iU72gEfhsZbJ5iOTw+1V/AqJh4QOMhVe32jZa5nCn5PJ7Luc0+dWACS730TqExftstDGfeD8sK0YIyRg3vu95Uxz5HbB0CMF/Kz4+WWLWOSg9IlhXYzmJTfRJu5hxT7xkvZbqZ6qrTQqhm/FFeVwkt8vrV5nzPvt59gn5661LoamU/GX7JKva3Hqy4iB4/uxGEGDTaY7+3PAclpVDst Amazon-Redshift
11 | us-east-1a
12 | 1.0
13 |
14 | 5439
15 | vpc-public-2.csorkyt5dk7h.us-east-1.redshift.amazonaws.com
16 |
17 | vpc-4c89a437
18 | true
19 | 2018-05-20T22:58:31.220Z
20 | admin
21 | dev
22 | false
23 |
24 |
25 | dc2.large
26 | subnet-group
27 |
28 |
29 |
30 | sg-b777aeff
31 | active
32 |
33 |
34 |
35 |
36 | default.redshift-1.0
37 | in-sync
38 |
39 |
40 | false
41 |
42 |
43 | 10.0.0.8
44 | LEADER
45 | 52.44.170.10
46 |
47 |
48 | 10.0.0.11
49 | COMPUTE-0
50 | 54.209.53.206
51 |
52 |
53 | 10.0.0.9
54 | COMPUTE-1
55 | 54.208.75.129
56 |
57 |
58 |
59 | wed:08:00-wed:08:30
60 | 1
61 | available
62 |
63 |
64 |
65 |
66 | 61692f3a-5c81-11e8-a732-9da506d397b6
67 |
68 |
69 |
--------------------------------------------------------------------------------
/spec/fixtures/redshift-vpc-private.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true
7 | vpc-cluster-private
8 | 2058
9 | 2
10 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmkaWswOWoiWbwmwaNquPDqvNAdOS+NRO7gd9vhjLRYwGQvN3QMQNk75BkrrL+mZV9FN+1RuJ8kcZ5ucZ8RmCcfkTrk7uFvdU9Bf9qo0geBKcPQ7SotonxEv336AcQwiqTDK4EwrFwDYV19NMXVaVTLhusax6sQu0tMPUkr1r3iPfn/VYHbWHVrpdqGq6RQii1sk49QujXgJThpabGJ3cjJmdpqgo022+yRv7wf7HuRUN3qEg+904DnnVQQEDFhQ6OOGghUIt+YZBkJ1UkiXGApSn/rw/DfT2KpNYneXqBErAxcHBlY0lTq5YkglyQgDMiSNcmx2+YpBZj4Vkyjcc9 Amazon-Redshift
11 | 1.0
12 | us-east-1a
13 |
14 | 5439
15 | vpc-cluster-private.csorkyt5dk7h.us-east-1.redshift.amazonaws.com
16 |
17 | vpc-4c89a437
18 | false
19 | 2018-05-20T22:27:42.458Z
20 | admin
21 | dev
22 | false
23 |
24 |
25 | dc2.large
26 | subnet-group
27 |
28 |
29 |
30 | sg-b777aeff
31 | active
32 |
33 |
34 |
35 |
36 | default.redshift-1.0
37 | in-sync
38 |
39 |
40 | false
41 |
42 |
43 | 10.0.0.14
44 | LEADER
45 | 34.238.26.198
46 |
47 |
48 | 10.0.0.6
49 | COMPUTE-0
50 | 52.45.114.153
51 |
52 |
53 | 10.0.0.10
54 | COMPUTE-1
55 | 54.88.117.230
56 |
57 |
58 |
59 | tue:08:00-tue:08:30
60 | 1
61 | available
62 |
63 |
64 |
65 |
66 | fc18c8ea-5c7d-11e8-9acb-e3641e6aeeb7
67 |
68 |
69 |
--------------------------------------------------------------------------------
/spec/fixtures/ec2-private.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 17749bd3-9d69-4051-aa94-91e0cac5971f
4 |
5 | -
6 | r-08e6ea036e9e2e07c
7 | 154967844790
8 |
9 |
10 |
-
11 | i-090e773dd73419c8c
12 | ami-14c5486b
13 |
14 |
16
15 | running
16 |
17 | ip-10-0-0-5.ec2.internal
18 |
19 |
20 | keyname
21 | 0
22 |
23 | t2.micro
24 | 2018-05-20T22:08:25.000Z
25 |
26 | us-east-1a
27 |
28 | default
29 |
30 |
31 | disabled
32 |
33 | subnet-20f80a7c
34 | vpc-4c89a437
35 | 10.0.0.5
36 | true
37 |
38 | -
39 | sg-132fb85b
40 | launch-wizard-1
41 |
42 |
43 | x86_64
44 | ebs
45 | /dev/xvda
46 |
47 | -
48 | /dev/xvda
49 |
50 | vol-017937e9deeb3a745
51 | attached
52 | 2018-05-20T22:08:26.000Z
53 | true
54 |
55 |
56 |
57 | hvm
58 |
59 | xen
60 |
61 | -
62 | eni-3c876ea7
63 | subnet-20f80a7c
64 | vpc-4c89a437
65 | Primary network interface
66 | 154967844790
67 | in-use
68 | 0e:14:a3:7e:a6:ae
69 | 10.0.0.5
70 | true
71 |
72 |
-
73 | sg-132fb85b
74 | launch-wizard-1
75 |
76 |
77 |
78 | eni-attach-448b035f
79 | 0
80 | attached
81 | 2018-05-20T22:08:25.000Z
82 | true
83 |
84 |
85 | -
86 | 10.0.0.5
87 | true
88 |
89 |
90 |
91 |
92 |
93 | false
94 | true
95 |
96 | 1
97 | 1
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/lib/aws_public_ips/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'optparse'
4 |
5 | module AwsPublicIps
6 | class CLI
7 | # Supported services:
8 | # EC2 (and as a result: ECS, EKS, Beanstalk, Fargate, Batch, & NAT Instances)
9 | # ELB (Classic ELB)
10 | # ELBv2 (ALB/NLB)
11 | # RDS
12 | # Redshift
13 | # APIGateway
14 | # CloudFront
15 | # Lightsail
16 | # ElasticSearch
17 |
18 | # Services that don't need to be supported:
19 | # S3 - all s3 buckets resolve to the same ip addresses
20 | # SQS - there's a single AWS-owned domain per region (i.e. sqs.us-east-1.amazonaws.com//)
21 | # NAT Gateways - these do not allow ingress traffic
22 | # ElastiCache - all elasticache instances are private. You can make one public by using a NAT instance with an EIP:
23 | # https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/accessing-elasticache.html#access-from-outside-aws
24 | # but NAT instances are EC2 machines, so this will be caught by the EC2 check.
25 | # DynamoDB - no public endpoints
26 | # SNS - no public endpoints
27 | # Elastic Transcoder - no public endpoints
28 | # Athena - no public endpoints
29 |
30 | # Services that maybe have public endpoints / still need testing:
31 | # fargate
32 | # amazonmq
33 | # directory service (AD)
34 | # emr
35 | # Directconnect
36 | # Kinesis
37 | # SES
38 | # https://aws.amazon.com/products/
39 | # AWS Neptune (still in preview / not GA yet)
40 |
41 | def all_services
42 | @all_services ||= ::Dir["#{__dir__}/checks/*.rb"].map { |path| ::File.basename(path, '.rb') }.sort
43 | end
44 |
45 | def all_formats
46 | @all_formats ||= ::Dir["#{__dir__}/formatters/*.rb"].map { |path| ::File.basename(path, '.rb') }.sort
47 | end
48 |
49 | def parse(args)
50 | options = {
51 | format: 'text',
52 | services: all_services,
53 | verbose: false
54 | }
55 |
56 | ::OptionParser.new do |parser|
57 | parser.banner = 'Usage: aws_public_ips [options]'
58 |
59 | parser.on('-s', '--services ,,', Array, 'List of AWS services to check. Available services: ' \
60 | "#{all_services.join(',')}. Defaults to all.") do |services|
61 | services.map(&:downcase!).uniq!
62 | invalid_services = services - all_services
63 | raise ::ArgumentError, "Invalid service(s): #{invalid_services.join(',')}" unless invalid_services.empty?
64 |
65 | options[:services] = services
66 | end
67 |
68 | parser.on('-f', '--format ', String, 'Set output format. Available formats: ' \
69 | "#{all_formats.join(',')}. Defaults to text.") do |fmt|
70 | unless all_formats.include?(fmt)
71 | raise ::ArgumentError, "Invalid format '#{fmt}'. Valid formats are: #{all_formats.join(',')}"
72 | end
73 |
74 | options[:format] = fmt
75 | end
76 |
77 | parser.on('-v', '--[no-]verbose', 'Enable debug/trace output') do |verbose|
78 | options[:verbose] = verbose
79 | end
80 |
81 | parser.on_tail('--version', 'Print version') do
82 | require 'aws_public_ips/version'
83 | ::STDOUT.puts ::AwsPublicIps::VERSION
84 | return nil # nil to avoid rubocop warning
85 | end
86 |
87 | parser.on_tail('-h', '--help', 'Show this help message') do
88 | ::STDOUT.puts parser
89 | return nil # nil to avoid rubocop warning
90 | end
91 | end.parse(args)
92 |
93 | options
94 | end
95 |
96 | def check_service(service)
97 | require "aws_public_ips/checks/#{service}.rb"
98 | ::AwsPublicIps::Checks.const_get(service.capitalize).run
99 | end
100 |
101 | def output(formatter, options, results)
102 | require "aws_public_ips/formatters/#{formatter}.rb"
103 | formatter_klass = ::AwsPublicIps::Formatters.const_get(formatter.capitalize)
104 | output = formatter_klass.new(results, options).format
105 | ::STDOUT.puts output unless output.empty?
106 | end
107 |
108 | def run(args)
109 | options = parse(args)
110 | return unless options
111 |
112 | results = options[:services].map do |service|
113 | [service.to_sym, check_service(service)]
114 | end.to_h
115 |
116 | output(options[:format], options, results)
117 | rescue ::StandardError, ::Interrupt => ex
118 | ::STDERR.puts ex.inspect
119 | ::STDERR.puts ex.backtrace if options && options[:verbose]
120 | ::Process.exit(1)
121 | end
122 | end
123 | end
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # aws_public_ips [](https://rubygems.org/gems/aws_public_ips) [](https://travis-ci.com/arkadiyt/aws_public_ips/) [](https://coveralls.io/github/arkadiyt/aws_public_ips?branch=master) [](https://github.com/arkadiyt/aws_public_ips/blob/master/LICENSE.md)
2 |
3 | ## Table of Contents
4 | - [What's it for](https://github.com/arkadiyt/aws_public_ips#whats-it-for)
5 | - [Quick start](https://github.com/arkadiyt/aws_public_ips#quick-start)
6 | - [CLI reference](https://github.com/arkadiyt/aws_public_ips#cli-reference)
7 | - [Configuration](https://github.com/arkadiyt/aws_public_ips#configuration)
8 | - [IAM permissions](https://github.com/arkadiyt/aws_public_ips#iam-permissions)
9 | - [Changelog](https://github.com/arkadiyt/aws_public_ips#changelog)
10 | - [Contributing](https://github.com/arkadiyt/aws_public_ips#contributing)
11 | - [Getting in touch](https://github.com/arkadiyt/aws_public_ips#getting-in-touch)
12 |
13 | ### What's it for
14 |
15 | aws_public_ips is a tool to fetch all public IP addresses (both IPv4/IPv6) associated with an AWS account.
16 |
17 | It can be used as a library and as a CLI, and supports the following AWS services (all with both Classic & VPC flavors):
18 |
19 | - APIGateway
20 | - CloudFront
21 | - EC2 (and as a result: ECS, EKS, Beanstalk, Fargate, Batch, & NAT Instances)
22 | - ElasticSearch
23 | - ELB (Classic ELB)
24 | - ELBv2 (ALB/NLB)
25 | - Lightsail
26 | - RDS
27 | - Redshift
28 |
29 | If a service isn't listed (S3, ElastiCache, etc) it's most likely because it doesn't have anything to support (i.e. it might not be deployable publicly, it might have all ip addresses resolve to global AWS infrastructure, etc).
30 |
31 | ### Quick start
32 |
33 | Install the gem and run it:
34 | ```
35 | $ gem install aws_public_ips
36 |
37 | # Uses default ~/.aws/credentials
38 | $ aws_public_ips
39 | 52.84.11.13
40 | 52.84.11.83
41 | 2600:9000:2039:ba00:1a:cd27:1440:93a1
42 | 2600:9000:2039:6e00:1a:cd27:1440:93a1
43 |
44 | # With a custom profile
45 | $ AWS_PROFILE=production aws_public_ips
46 | 52.84.11.159
47 | ```
48 |
49 | The gem can also be run from Docker:
50 | ```
51 | $ docker pull arkadiyt/aws_public_ips
52 |
53 | # For credentials, ensure the appropriate environment variables are defined in the host environment:
54 | $ docker run -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN arkadiyt/aws_public_ips
55 | ```
56 |
57 | ### CLI reference
58 |
59 | ```
60 | $ aws_public_ips --help
61 | Usage: aws_public_ips [options]
62 | -s, --services ,, List of AWS services to check. Available services: apigateway,cloudfront,ec2,elasticsearch,elb,elbv2,lightsail,rds,redshift. Defaults to all.
63 | -f, --format Set output format. Available formats: json,prettyjson,text. Defaults to text.
64 | -v, --[no-]verbose Enable debug/trace output
65 | --version Print version
66 | -h, --help Show this help message
67 | ```
68 |
69 | ### Configuration
70 |
71 | For authentication aws_public_ips uses the default [aws-sdk-ruby](https://github.com/aws/aws-sdk-ruby) configuration, meaning that the following are checked in order:
72 | 1. Environment variables:
73 | - `AWS_ACCESS_KEY_ID`
74 | - `AWS_SECRET_ACCESS_KEY`
75 | - `AWS_REGION`
76 | - `AWS_PROFILE`
77 | 2. Shared credentials files:
78 | - `~/.aws/credentials`
79 | - `~/.aws/config`
80 | 3. Instance profile via metadata endpoint (if running on EC2, ECS, EKS, or Fargate)
81 |
82 | For more information see the AWS SDK [documentation on configuration](https://github.com/aws/aws-sdk-ruby#configuration).
83 |
84 | ### IAM permissions
85 | To find the public IPs from all AWS services, the minimal policy needed by your IAM user is:
86 | ```json
87 | {
88 | "Version": "2012-10-17",
89 | "Statement": [
90 | {
91 | "Effect": "Allow",
92 | "Action": [
93 | "apigateway:GET",
94 | "cloudfront:ListDistributions",
95 | "ec2:DescribeInstances",
96 | "elasticloadbalancing:DescribeLoadBalancers",
97 | "lightsail:GetInstances",
98 | "lightsail:GetLoadBalancers",
99 | "rds:DescribeDBInstances",
100 | "redshift:DescribeClusters",
101 | "es:ListDomainNames"
102 | ],
103 | "Resource": "*"
104 | }
105 | ]
106 | }
107 | ```
108 |
109 | ### Changelog
110 |
111 | Please see [CHANGELOG.md](https://github.com/arkadiyt/aws_public_ips/blob/master/CHANGELOG.md). This project follows [semantic versioning](https://semver.org/).
112 |
113 | ### Contributing
114 |
115 | Please see [CONTRIBUTING.md](https://github.com/arkadiyt/aws_public_ips/blob/master/CONTRIBUTING.md).
116 |
117 | ### Getting in touch
118 |
119 | Feel free to tweet or direct message me: [@arkadiyt](https://twitter.com/arkadiyt)
120 |
--------------------------------------------------------------------------------
/spec/fixtures/rds-empty-endpoint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1
7 |
8 |
9 | default.aurora5.6
10 | in-sync
11 |
12 |
13 | us-east-1b
14 |
15 | 5.6.10a
16 | admin
17 | db.r4.large
18 |
19 | 0
20 | creating
21 | 1
22 | 1
23 |
24 |
25 | default:aurora-5-6
26 | in-sync
27 |
28 |
29 | rds-vpc-public-cluster
30 | rds-ca-2015
31 | 0
32 | db-BAKGGXYRB3EBKBDQZTAMDSGCXY
33 | 03:17-03:47
34 | arn:aws:rds:us-east-1:154967844790:db:rds-vpc-public
35 | rds-vpc-public
36 | aurora
37 | true
38 | false
39 | false
40 | false
41 |
42 | false
43 |
44 | vpc-4c89a437
45 |
46 |
47 | subnet-20f80a7c
48 | Active
49 |
50 | us-east-1a
51 |
52 |
53 |
54 | subnet-1e3cf179
55 | Active
56 |
57 | us-east-1b
58 |
59 |
60 |
61 | Complete
62 | rds-subnet-group
63 | rds-subnet-group
64 |
65 |
66 |
67 | sg-9ba432d3
68 | active
69 |
70 |
71 | general-public-license
72 |
73 | sat:10:13-sat:10:43
74 | aurora
75 | true
76 | false
77 |
78 |
79 | 1
80 |
81 |
82 | default.aurora5.6
83 | in-sync
84 |
85 |
86 | us-east-1a
87 |
88 | 5.6.10a
89 | admin
90 | db.r4.large
91 |
92 | 0
93 | creating
94 | 1
95 | 1
96 |
97 |
98 | default:aurora-5-6
99 | in-sync
100 |
101 |
102 | rds-vpc-public-cluster
103 | rds-ca-2015
104 | 0
105 | db-B3N4GULDAFGDKEGXBD7CXKZQV4
106 | 03:17-03:47
107 | arn:aws:rds:us-east-1:154967844790:db:rds-vpc-public-us-east-1a
108 | rds-vpc-public-us-east-1a
109 | aurora
110 | true
111 | false
112 | false
113 | false
114 |
115 | false
116 |
117 | vpc-4c89a437
118 |
119 |
120 | subnet-20f80a7c
121 | Active
122 |
123 | us-east-1a
124 |
125 |
126 |
127 | subnet-1e3cf179
128 | Active
129 |
130 | us-east-1b
131 |
132 |
133 |
134 | Complete
135 | rds-subnet-group
136 | rds-subnet-group
137 |
138 |
139 |
140 | sg-9ba432d3
141 | active
142 |
143 |
144 | general-public-license
145 |
146 | sun:08:16-sun:08:46
147 | aurora
148 | true
149 | false
150 |
151 |
152 |
153 |
154 | 4356fb13-05a5-47de-8500-2fcc114c963e
155 |
156 |
157 |
--------------------------------------------------------------------------------
/spec/fixtures/rds-vpc-private.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1
7 |
8 |
9 | default.aurora5.6
10 | in-sync
11 |
12 |
13 | us-east-1b
14 |
15 | 5.6.10a
16 | admin
17 | 2018-05-21T00:28:01.133Z
18 | db.r4.large
19 |
20 | 0
21 | available
22 | 1
23 | 1
24 |
25 |
26 | default:aurora-5-6
27 | in-sync
28 |
29 |
30 | vpc-private-cluster
31 | rds-ca-2015
32 | 0
33 | db-QDHUSATZNYTKZ5AWV4JEPVZLZE
34 | 04:46-05:16
35 | arn:aws:rds:us-east-1:154967844790:db:vpc-private
36 | vpc-private
37 |
38 | Z2R2ITUGPM61AM
39 | vpc-private.cyvjlokb0o75.us-east-1.rds.amazonaws.com
40 | 3306
41 |
42 | aurora
43 | false
44 | false
45 | false
46 | false
47 |
48 | false
49 |
50 | vpc-4c89a437
51 |
52 |
53 | subnet-20f80a7c
54 | Active
55 |
56 | us-east-1a
57 |
58 |
59 |
60 | subnet-1e3cf179
61 | Active
62 |
63 | us-east-1b
64 |
65 |
66 |
67 | Complete
68 | rds-subnet-group
69 | rds-subnet-group
70 |
71 |
72 |
73 | sg-b777aeff
74 | active
75 |
76 |
77 | general-public-license
78 |
79 | tue:08:38-tue:09:08
80 | aurora
81 | true
82 | true
83 |
84 |
85 | 1
86 |
87 |
88 | default.aurora5.6
89 | in-sync
90 |
91 |
92 | us-east-1a
93 |
94 | 5.6.10a
95 | admin
96 | 2018-05-21T00:31:54.651Z
97 | db.r4.large
98 |
99 | 0
100 | available
101 | 1
102 | 1
103 |
104 |
105 | default:aurora-5-6
106 | in-sync
107 |
108 |
109 | vpc-private-cluster
110 | rds-ca-2015
111 | 0
112 | db-Q7KTA4DT5Q4JCBJAOVFS4HITBY
113 | 04:46-05:16
114 | arn:aws:rds:us-east-1:154967844790:db:vpc-private-us-east-1a
115 | vpc-private-us-east-1a
116 |
117 | Z2R2ITUGPM61AM
118 | vpc-private-us-east-1a.cyvjlokb0o75.us-east-1.rds.amazonaws.com
119 | 3306
120 |
121 | aurora
122 | false
123 | false
124 | false
125 | false
126 |
127 | false
128 |
129 | vpc-4c89a437
130 |
131 |
132 | subnet-20f80a7c
133 | Active
134 |
135 | us-east-1a
136 |
137 |
138 |
139 | subnet-1e3cf179
140 | Active
141 |
142 | us-east-1b
143 |
144 |
145 |
146 | Complete
147 | rds-subnet-group
148 | rds-subnet-group
149 |
150 |
151 |
152 | sg-b777aeff
153 | active
154 |
155 |
156 | general-public-license
157 |
158 | thu:09:36-thu:10:06
159 | aurora
160 | true
161 | true
162 |
163 |
164 |
165 |
166 | 8f4ee8ee-5958-4da8-94a2-be40301c82f1
167 |
168 |
169 |
--------------------------------------------------------------------------------
/spec/fixtures/rds-vpc-public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1
7 |
8 |
9 | default.aurora5.6
10 | in-sync
11 |
12 |
13 | us-east-1b
14 |
15 | 5.6.10a
16 | admin
17 | 2018-05-21T00:12:20.781Z
18 | db.r4.large
19 |
20 | 0
21 | available
22 | 1
23 | 1
24 |
25 |
26 | default:aurora-5-6
27 | in-sync
28 |
29 |
30 | rds-vpc-public-cluster
31 | rds-ca-2015
32 | 0
33 | db-BAKGGXYRB3EBKBDQZTAMDSGCXY
34 | 03:17-03:47
35 | rds-vpc-public
36 | arn:aws:rds:us-east-1:154967844790:db:rds-vpc-public
37 |
38 | Z2R2ITUGPM61AM
39 | rds-vpc-public.cyvjlokb0o75.us-east-1.rds.amazonaws.com
40 | 3306
41 |
42 | aurora
43 | true
44 | false
45 | false
46 | false
47 |
48 | false
49 |
50 | vpc-4c89a437
51 |
52 |
53 | subnet-20f80a7c
54 | Active
55 |
56 | us-east-1a
57 |
58 |
59 |
60 | subnet-1e3cf179
61 | Active
62 |
63 | us-east-1b
64 |
65 |
66 |
67 | Complete
68 | rds-subnet-group
69 | rds-subnet-group
70 |
71 |
72 |
73 | sg-9ba432d3
74 | active
75 |
76 |
77 | general-public-license
78 |
79 | sat:10:13-sat:10:43
80 | aurora
81 | true
82 | false
83 |
84 |
85 | 1
86 |
87 |
88 | default.aurora5.6
89 | in-sync
90 |
91 |
92 | us-east-1a
93 |
94 | 5.6.10a
95 | admin
96 | 2018-05-21T00:14:20.296Z
97 | db.r4.large
98 |
99 | 0
100 | available
101 | 1
102 | 1
103 |
104 |
105 | default:aurora-5-6
106 | in-sync
107 |
108 |
109 | rds-vpc-public-cluster
110 | rds-ca-2015
111 | 0
112 | db-B3N4GULDAFGDKEGXBD7CXKZQV4
113 | 03:17-03:47
114 | rds-vpc-public-us-east-1a
115 | arn:aws:rds:us-east-1:154967844790:db:rds-vpc-public-us-east-1a
116 |
117 | Z2R2ITUGPM61AM
118 | rds-vpc-public-us-east-1a.cyvjlokb0o75.us-east-1.rds.amazonaws.com
119 | 3306
120 |
121 | aurora
122 | true
123 | false
124 | false
125 | false
126 |
127 | false
128 |
129 | vpc-4c89a437
130 |
131 |
132 | subnet-20f80a7c
133 | Active
134 |
135 | us-east-1a
136 |
137 |
138 |
139 | subnet-1e3cf179
140 | Active
141 |
142 | us-east-1b
143 |
144 |
145 |
146 | Complete
147 | rds-subnet-group
148 | rds-subnet-group
149 |
150 |
151 |
152 | sg-9ba432d3
153 | active
154 |
155 |
156 | general-public-license
157 |
158 | sun:08:16-sun:08:46
159 | aurora
160 | true
161 | false
162 |
163 |
164 |
165 |
166 | f05d3871-a7b3-4bf4-a324-6f0866b0cf67
167 |
168 |
169 |
--------------------------------------------------------------------------------
/spec/fixtures/cloudfront.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 100
6 | false
7 | 2
8 |
9 |
10 | E1DABYDY46RHFK
11 | arn:aws:cloudfront::154967844790:distribution/E1DABYDY46RHFK
12 | Deployed
13 | 2018-04-22T22:33:13.512Z
14 | d22ycgwdruc4lt.cloudfront.net
15 |
16 | 1
17 |
18 | example.com
19 |
20 |
21 |
22 | 1
23 |
24 |
25 | example-com
26 | example-com.s3.amazonaws.com
27 |
28 |
29 |
30 | 0
31 |
32 |
33 | origin-access-identity/cloudfront/E32EG6T6E6W76Z
34 |
35 |
36 |
37 |
38 |
39 | example-com
40 |
41 | false
42 |
43 | none
44 |
45 |
46 | 0
47 |
48 |
49 | 0
50 |
51 |
52 |
53 | false
54 | 0
55 |
56 | redirect-to-https
57 | 86400
58 |
59 | 3
60 |
61 | HEAD
62 | GET
63 | OPTIONS
64 |
65 |
66 | 3
67 |
68 | HEAD
69 | GET
70 | OPTIONS
71 |
72 |
73 |
74 | false
75 | 86400
76 | 86400
77 | true
78 |
79 | 2
80 |
81 |
82 | arn:aws:lambda:us-east-1:154967844790:function:website_origin_request:40
83 | origin-request
84 |
85 |
86 | arn:aws:lambda:us-east-1:154967844790:function:website_origin_response:27
87 | origin-response
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | 1
96 |
97 |
98 | __errors/*
99 | example-com
100 |
101 | false
102 |
103 | none
104 |
105 |
106 | 0
107 |
108 |
109 | 0
110 |
111 |
112 |
113 | false
114 | 0
115 |
116 | https-only
117 | 86400
118 |
119 | 3
120 |
121 | HEAD
122 | GET
123 | OPTIONS
124 |
125 |
126 | 3
127 |
128 | HEAD
129 | GET
130 | OPTIONS
131 |
132 |
133 |
134 | false
135 | 86400
136 | 86400
137 | true
138 |
139 | 1
140 |
141 |
142 | arn:aws:lambda:us-east-1:154967844790:function:website_origin_response:27
143 | origin-response
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | 11
154 |
155 |
156 | 400
157 | /__errors/400.html
158 | 400
159 | 0
160 |
161 |
162 | 403
163 | /__errors/403.html
164 | 403
165 | 0
166 |
167 |
168 | 404
169 | /__errors/404.html
170 | 404
171 | 0
172 |
173 |
174 | 405
175 | /__errors/405.html
176 | 405
177 | 0
178 |
179 |
180 | 414
181 | /__errors/414.html
182 | 414
183 | 0
184 |
185 |
186 | 416
187 | /__errors/416.html
188 | 416
189 | 0
190 |
191 |
192 | 500
193 | /__errors/500.html
194 | 500
195 | 0
196 |
197 |
198 | 501
199 | /__errors/501.html
200 | 501
201 | 0
202 |
203 |
204 | 502
205 | /__errors/502.html
206 | 502
207 | 0
208 |
209 |
210 | 503
211 | /__errors/503.html
212 | 503
213 | 0
214 |
215 |
216 | 504
217 | /__errors/504.html
218 | 504
219 | 0
220 |
221 |
222 |
223 |
224 |
225 | PriceClass_100
226 | true
227 |
228 | arn:aws:acm:us-east-1:154967844790:certificate/01f2bc8f-2aac-466c-a148-1932567d030e
229 | sni-only
230 | TLSv1.2_2018
231 | arn:aws:acm:us-east-1:154967844790:certificate/01f2bc8f-2aac-466c-a148-1932567d030e
232 | acm
233 |
234 |
235 |
236 | none
237 | 0
238 |
239 |
240 |
241 |
242 | HTTP2
243 | true
244 |
245 |
246 | E3SFCHHIPK43DR
247 | arn:aws:cloudfront::154967844790:distribution/E3SFCHHIPK43DR
248 | Deployed
249 | 2018-01-30T06:26:48.987Z
250 | d1k00qwg2uxphp.cloudfront.net
251 |
252 | 1
253 |
254 | www.example.com
255 |
256 |
257 |
258 | 1
259 |
260 |
261 | example-com
262 | example-com.s3.amazonaws.com
263 |
264 |
265 |
266 | 0
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 | example-com
277 |
278 | false
279 |
280 | none
281 |
282 |
283 | 0
284 |
285 |
286 | 0
287 |
288 |
289 |
290 | false
291 | 0
292 |
293 | allow-all
294 | 86400
295 |
296 | 3
297 |
298 | HEAD
299 | GET
300 | OPTIONS
301 |
302 |
303 | 3
304 |
305 | HEAD
306 | GET
307 | OPTIONS
308 |
309 |
310 |
311 | false
312 | 86400
313 | 86400
314 | true
315 |
316 | 1
317 |
318 |
319 | arn:aws:lambda:us-east-1:154967844790:function:redirect_origin_request:15
320 | origin-request
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | 0
329 |
330 |
331 | 0
332 |
333 |
334 |
335 | PriceClass_100
336 | true
337 |
338 | arn:aws:acm:us-east-1:154967844790:certificate/01f2bc8f-2aac-466c-a148-1932567d030e
339 | sni-only
340 | TLSv1.2_2018
341 | arn:aws:acm:us-east-1:154967844790:certificate/01f2bc8f-2aac-466c-a148-1932567d030e
342 | acm
343 |
344 |
345 |
346 | none
347 | 0
348 |
349 |
350 |
351 |
352 | HTTP2
353 | true
354 |
355 |
356 |
357 |
--------------------------------------------------------------------------------
/spec/fixtures/ec2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 96d9a23f-f1a8-417e-b5da-758842dfbe5a
4 |
5 | -
6 | r-0d589c1a0ed18e213
7 | 154967844790
8 |
9 |
-
10 | sg-6ab45e01
11 | default
12 |
13 |
14 |
15 | -
16 | i-0f22d0af796b3cf3a
17 | ami-467ca739
18 |
19 |
16
20 | running
21 |
22 | ip-10-234-68-246.ec2.internal
23 | ec2-54-234-208-236.compute-1.amazonaws.com
24 |
25 | 0
26 |
27 | m1.small
28 | 2018-05-13T02:44:55.000Z
29 |
30 | us-east-1d
31 |
32 | default
33 |
34 |
35 | disabled
36 |
37 | 10.234.68.246
38 | 54.234.208.236
39 |
40 | -
41 | sg-6ab45e01
42 | default
43 |
44 |
45 | x86_64
46 | ebs
47 | /dev/xvda
48 |
49 | -
50 | /dev/xvda
51 |
52 | vol-0282f201689e44883
53 | attached
54 | 2018-05-13T02:44:56.000Z
55 | true
56 |
57 |
58 |
59 | hvm
60 |
61 | xen
62 |
63 | false
64 | true
65 |
66 | 1
67 | 1
68 |
69 |
70 |
71 |
72 | -
73 | r-0069e18c636d252c7
74 | 154967844790
75 |
76 |
77 |
-
78 | i-04ef469b441883eda
79 | ami-467ca739
80 |
81 |
16
82 | running
83 |
84 | ip-10-0-0-187.ec2.internal
85 | ec2-18-206-76-65.compute-1.amazonaws.com
86 |
87 | keyname
88 | 0
89 |
90 | t2.micro
91 | 2018-05-13T03:08:08.000Z
92 |
93 | us-east-1f
94 |
95 | default
96 |
97 |
98 | disabled
99 |
100 | subnet-f4be30fb
101 | vpc-23a48958
102 | 10.0.0.187
103 | 18.206.76.65
104 | true
105 |
106 | -
107 | sg-03fe274b
108 | launch-wizard-4
109 |
110 |
111 | x86_64
112 | ebs
113 | /dev/xvda
114 |
115 | -
116 | /dev/xvda
117 |
118 | vol-090850d84dca740d0
119 | attached
120 | 2018-05-13T03:08:08.000Z
121 | true
122 |
123 |
124 |
125 | hvm
126 |
127 | xen
128 |
129 | -
130 | eni-1f5cceba
131 | subnet-f4be30fb
132 | vpc-23a48958
133 | Primary network interface
134 | 154967844790
135 | in-use
136 | 16:e2:8b:1a:b7:40
137 | 10.0.0.187
138 | ip-10-0-0-187.ec2.internal
139 | true
140 |
141 |
-
142 | sg-03fe274b
143 | launch-wizard-4
144 |
145 |
146 |
147 | eni-attach-094e0a19
148 | 0
149 | attached
150 | 2018-05-13T03:08:08.000Z
151 | true
152 |
153 |
154 | 18.206.76.65
155 | ec2-18-206-76-65.compute-1.amazonaws.com
156 | amazon
157 |
158 |
159 | -
160 | 10.0.0.187
161 | ip-10-0-0-187.ec2.internal
162 | true
163 |
164 | 18.206.76.65
165 | ec2-18-206-76-65.compute-1.amazonaws.com
166 | amazon
167 |
168 |
169 |
170 |
171 | -
172 | 2600:1f18:63e0:b400:f50c:59a7:a182:3717
173 |
174 |
175 |
176 |
177 | false
178 | true
179 |
180 | 1
181 | 1
182 |
183 |
184 |
185 |
186 | -
187 | r-04301f4980f5fdaba
188 | 154967844790
189 |
190 |
191 |
-
192 | i-03a7b3bc2b4c20742
193 | ami-467ca739
194 |
195 |
16
196 | running
197 |
198 | ip-10-0-0-6.ec2.internal
199 |
200 |
201 | 0
202 |
203 | m5.large
204 | 2018-05-13T22:23:55.000Z
205 |
206 | us-east-1a
207 |
208 | default
209 |
210 |
211 | disabled
212 |
213 | subnet-20f80a7c
214 | vpc-4c89a437
215 | 10.0.0.6
216 | true
217 |
218 | -
219 | sg-13298c5b
220 | launch-wizard-1
221 |
222 |
223 | x86_64
224 | ebs
225 | /dev/xvda
226 |
227 | -
228 | /dev/xvda
229 |
230 | vol-01bc294dbc428dd54
231 | attached
232 | 2018-05-13T22:23:55.000Z
233 | true
234 |
235 |
236 |
237 | hvm
238 |
239 | xen
240 |
241 | -
242 | eni-2bdfaeb3
243 | subnet-20f80a7c
244 | vpc-4c89a437
245 |
246 | 154967844790
247 | in-use
248 | 0e:e5:cd:f2:33:90
249 | 10.0.0.8
250 | true
251 |
252 |
-
253 | sg-13298c5b
254 | launch-wizard-1
255 |
256 |
257 |
258 | eni-attach-672ae57c
259 | 1
260 | attached
261 | 2018-05-13T22:23:55.000Z
262 | true
263 |
264 |
265 | -
266 | 10.0.0.8
267 | true
268 |
269 | -
270 | 10.0.0.10
271 |
272 | false
273 |
274 |
275 |
276 | -
277 | 2600:1f18:60f3:eb00:1c6e:5184:8955:170c
278 |
279 |
280 |
281 | -
282 | eni-94c2b30c
283 | subnet-20f80a7c
284 | vpc-4c89a437
285 | Primary network interface
286 | 154967844790
287 | in-use
288 | 0e:14:7d:3d:6d:dc
289 | 10.0.0.6
290 | true
291 |
292 |
-
293 | sg-13298c5b
294 | launch-wizard-1
295 |
296 |
297 |
298 | eni-attach-642ae57f
299 | 0
300 | attached
301 | 2018-05-13T22:23:55.000Z
302 | true
303 |
304 |
305 | -
306 | 10.0.0.6
307 | true
308 |
309 | -
310 | 10.0.0.7
311 |
312 | false
313 |
314 | -
315 | 10.0.0.13
316 |
317 | false
318 |
319 |
320 |
321 |
322 |
323 | true
324 | true
325 |
326 | 1
327 | 2
328 |
329 |
330 | -
331 | i-01e4cbbe2c7fb98f6
332 | ami-01e24be29428c15b2
333 |
334 |
16
335 | running
336 |
337 | ip-10-31-42-214.us-west-2.compute.internal
338 | ec2-50-112-85-68.us-west-2.compute.amazonaws.com
339 |
340 | 0
341 |
342 | t2.nano
343 | 2019-05-10T15:11:49.000Z
344 |
345 | us-west-2a
346 |
347 | default
348 |
349 |
350 | disabled
351 |
352 | subnet-f4be30fb
353 | vpc-23a48958
354 | 10.31.42.214
355 | 50.112.85.68
356 | true
357 |
358 | -
359 | sg-6ab45e01
360 | default
361 |
362 |
363 | x86_64
364 | ebs
365 | /dev/xvda
366 |
367 | -
368 | /dev/xvda
369 |
370 | vol-0964259d35f8ba06f
371 | attached
372 | 2019-05-10T15:11:49.000Z
373 | true
374 |
375 |
376 |
377 | hvm
378 |
379 | xen
380 |
381 | -
382 | eni-0e77318599790bcd2
383 | subnet-f4be30fb
384 | vpc-23a48958
385 |
386 | 154967844790
387 | in-use
388 | 06:a1:e2:ce:32:16
389 | 10.31.42.214
390 | ip-10-31-42-214.us-west-2.compute.internal
391 | true
392 |
393 |
-
394 | sg-6ab45e01
395 | default
396 |
397 |
398 |
399 | eni-attach-0e1004d8f294c30ca
400 | 0
401 | attached
402 | 2019-05-10T15:11:49.000Z
403 | true
404 |
405 |
406 | 50.112.85.68
407 | ec2-50-112-85-68.us-west-2.compute.amazonaws.com
408 | 154967844790
409 |
410 |
411 | -
412 | 10.31.42.214
413 | ip-10-31-42-214.us-west-2.compute.internal
414 | true
415 |
416 | 50.112.85.68
417 | ec2-50-112-85-68.us-west-2.compute.amazonaws.com
418 | 154967844790
419 |
420 |
421 | -
422 | 10.31.32.64
423 | ip-10-31-32-64.us-west-2.compute.internal
424 | false
425 |
426 | 54.214.97.117
427 | ec2-54-214-97-117.us-west-2.compute.amazonaws.com
428 | 154967844790
429 |
430 |
431 |
432 |
433 | interface
434 |
435 |
436 | false
437 | true
438 |
439 | 1
440 | 1
441 |
442 |
443 | open
444 |
445 |
446 | false
447 |
448 |
449 |
450 |
451 |
452 |
453 |
--------------------------------------------------------------------------------