├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Gemfile ├── LICENSE.md ├── README.md ├── aws_public_ips.gemspec ├── bin └── aws_public_ips ├── lib ├── aws_public_ips.rb └── aws_public_ips │ ├── checks.rb │ ├── checks │ ├── apigateway.rb │ ├── cloudfront.rb │ ├── ec2.rb │ ├── elasticsearch.rb │ ├── elb.rb │ ├── elbv2.rb │ ├── lightsail.rb │ ├── rds.rb │ └── redshift.rb │ ├── cli.rb │ ├── formatters.rb │ ├── formatters │ ├── json.rb │ ├── prettyjson.rb │ └── text.rb │ ├── utils.rb │ └── version.rb └── spec ├── aws_public_ips ├── checks │ ├── apigateway_spec.rb │ ├── cloudfront_spec.rb │ ├── ec2_spec.rb │ ├── elasticsearch_spec.rb │ ├── elb_spec.rb │ ├── elbv2_spec.rb │ ├── lightsail_spec.rb │ ├── rds_spec.rb │ └── redshift_spec.rb ├── cli_spec.rb ├── formatters │ ├── json_spec.rb │ ├── prettyjson_spec.rb │ └── text_spec.rb ├── require_spec.rb └── utils_spec.rb ├── fixtures ├── apigateway.json ├── cloudfront.xml ├── ec2-private.xml ├── ec2.xml ├── elasticsearch-describe-classic.json ├── elasticsearch-describe-vpc.json ├── elasticsearch-list.json ├── elb.xml ├── elbv2.xml ├── lightsail-instance.json ├── lightsail-load-balancer.json ├── rds-empty-endpoint.xml ├── rds-vpc-private.xml ├── rds-vpc-public.xml ├── redshift-classic-public.xml ├── redshift-empty-endpoint.xml ├── redshift-vpc-private.xml └── redshift-vpc-public.xml └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .bundle 3 | coverage/ 4 | Gemfile.lock 5 | vendor/bundle 6 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --order random 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Treat everyone with respect. 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | gemspec 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aws_public_ips [![Gem](https://img.shields.io/gem/v/aws_public_ips.svg)](https://rubygems.org/gems/aws_public_ips) [![TravisCI](https://travis-ci.com/arkadiyt/aws_public_ips.svg?branch=master)](https://travis-ci.com/arkadiyt/aws_public_ips/) [![Coverage Status](https://coveralls.io/repos/github/arkadiyt/aws_public_ips/badge.svg?branch=master)](https://coveralls.io/github/arkadiyt/aws_public_ips?branch=master) [![License](https://img.shields.io/github/license/arkadiyt/aws_public_ips.svg)](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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /spec/fixtures/elasticsearch-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "DomainNames": [ 3 | { 4 | "DomainName": "classic" 5 | }, 6 | { 7 | "DomainName": "vpc" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /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/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/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/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/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/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-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/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/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/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 | --------------------------------------------------------------------------------