aws-inventory 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +16 -0
 - data/.rspec +2 -0
 - data/Gemfile +6 -0
 - data/Gemfile.lock +661 -0
 - data/Guardfile +19 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +65 -0
 - data/Rakefile +6 -0
 - data/exe/aws-inventory +14 -0
 - data/inventory.gemspec +37 -0
 - data/lib/inventory.rb +29 -0
 - data/lib/inventory/acm.rb +15 -0
 - data/lib/inventory/aws_services.rb +53 -0
 - data/lib/inventory/base.rb +74 -0
 - data/lib/inventory/cfn.rb +50 -0
 - data/lib/inventory/cli.rb +86 -0
 - data/lib/inventory/cloudwatch.rb +38 -0
 - data/lib/inventory/command.rb +25 -0
 - data/lib/inventory/eb.rb +19 -0
 - data/lib/inventory/ec2.rb +86 -0
 - data/lib/inventory/ecs.rb +10 -0
 - data/lib/inventory/ecs/cluster.rb +20 -0
 - data/lib/inventory/ecs/service.rb +33 -0
 - data/lib/inventory/elb.rb +71 -0
 - data/lib/inventory/help.rb +9 -0
 - data/lib/inventory/help/acm.md +1 -0
 - data/lib/inventory/help/cfn.md +1 -0
 - data/lib/inventory/help/cw.md +1 -0
 - data/lib/inventory/help/eb.md +1 -0
 - data/lib/inventory/help/ec2.md +1 -0
 - data/lib/inventory/help/ecs.md +1 -0
 - data/lib/inventory/help/elb.md +1 -0
 - data/lib/inventory/help/iam.md +15 -0
 - data/lib/inventory/help/keypair.md +1 -0
 - data/lib/inventory/help/rds.md +5 -0
 - data/lib/inventory/help/sg.md +1 -0
 - data/lib/inventory/help/vpc.md +1 -0
 - data/lib/inventory/iam.rb +13 -0
 - data/lib/inventory/iam/group.rb +22 -0
 - data/lib/inventory/iam/shared.rb +62 -0
 - data/lib/inventory/iam/summary.rb +16 -0
 - data/lib/inventory/iam/user.rb +21 -0
 - data/lib/inventory/keypair.rb +25 -0
 - data/lib/inventory/presenter.rb +20 -0
 - data/lib/inventory/presenters/base.rb +5 -0
 - data/lib/inventory/presenters/tab.rb +7 -0
 - data/lib/inventory/presenters/table.rb +10 -0
 - data/lib/inventory/rds.rb +11 -0
 - data/lib/inventory/rds/port.rb +53 -0
 - data/lib/inventory/rds/shared.rb +43 -0
 - data/lib/inventory/rds/summary.rb +23 -0
 - data/lib/inventory/route53.rb +29 -0
 - data/lib/inventory/security_group.rb +11 -0
 - data/lib/inventory/security_group/open.rb +76 -0
 - data/lib/inventory/security_group/shared.rb +14 -0
 - data/lib/inventory/security_group/summary.rb +17 -0
 - data/lib/inventory/shared.rb +16 -0
 - data/lib/inventory/version.rb +3 -0
 - data/lib/inventory/vpc.rb +55 -0
 - data/spec/lib/cli_spec.rb +31 -0
 - data/spec/lib/inventory/base_spec.rb +7 -0
 - data/spec/lib/inventory/security_group/open_spec.rb +31 -0
 - data/spec/spec_helper.rb +24 -0
 - metadata +308 -0
 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "action_view"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Inventory::Cloudwatch < Inventory::Base
         
     | 
| 
      
 4 
     | 
    
         
            +
              include ActionView::Helpers::DateHelper
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def header
         
     | 
| 
      
 7 
     | 
    
         
            +
                ["Alarm Name", "Threshold"]
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def data
         
     | 
| 
      
 11 
     | 
    
         
            +
                alarms.map do |alarm|
         
     | 
| 
      
 12 
     | 
    
         
            +
                  [
         
     | 
| 
      
 13 
     | 
    
         
            +
                    alarm.alarm_name,
         
     | 
| 
      
 14 
     | 
    
         
            +
                    threshold_desc(alarm)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              def threshold_desc(alarm)
         
     | 
| 
      
 20 
     | 
    
         
            +
                a = alarm
         
     | 
| 
      
 21 
     | 
    
         
            +
                total_period = a.period * a.evaluation_periods
         
     | 
| 
      
 22 
     | 
    
         
            +
                time_in_words = distance_of_time_in_words(total_period)
         
     | 
| 
      
 23 
     | 
    
         
            +
                "#{a.metric_name} #{compare_map[a.comparison_operator]} #{a.threshold} for #{a.evaluation_periods} datapoints within #{time_in_words}"
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def compare_map
         
     | 
| 
      
 27 
     | 
    
         
            +
                {
         
     | 
| 
      
 28 
     | 
    
         
            +
                  "GreaterThanOrEqualToThreshold" => ">=",
         
     | 
| 
      
 29 
     | 
    
         
            +
                  "GreaterThanThreshold" => ">",
         
     | 
| 
      
 30 
     | 
    
         
            +
                  "LessThanOrEqualToThreshold" => "<=",
         
     | 
| 
      
 31 
     | 
    
         
            +
                  "LessThanThreshold" => "<",
         
     | 
| 
      
 32 
     | 
    
         
            +
                }
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def alarms
         
     | 
| 
      
 36 
     | 
    
         
            +
                @alarms ||= cw.describe_alarms.metric_alarms
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "thor"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Inventory
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Command < Thor
         
     | 
| 
      
 5 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def dispatch(m, args, options, config)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    # Allow calling for help via:
         
     | 
| 
      
 8 
     | 
    
         
            +
                    #   inventory command help
         
     | 
| 
      
 9 
     | 
    
         
            +
                    #   inventory command -h
         
     | 
| 
      
 10 
     | 
    
         
            +
                    #   inventory command --help
         
     | 
| 
      
 11 
     | 
    
         
            +
                    #   inventory command -D
         
     | 
| 
      
 12 
     | 
    
         
            +
                    #
         
     | 
| 
      
 13 
     | 
    
         
            +
                    # as well thor's normal way:
         
     | 
| 
      
 14 
     | 
    
         
            +
                    #
         
     | 
| 
      
 15 
     | 
    
         
            +
                    #   inventory help command
         
     | 
| 
      
 16 
     | 
    
         
            +
                    help_flags = Thor::HELP_MAPPINGS + ["help"]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    if args.length > 1 && !(args & help_flags).empty?
         
     | 
| 
      
 18 
     | 
    
         
            +
                      args -= help_flags
         
     | 
| 
      
 19 
     | 
    
         
            +
                      args.insert(-2, "help")
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                    super
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/inventory/eb.rb
    ADDED
    
    | 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Eb < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def header
         
     | 
| 
      
 3 
     | 
    
         
            +
                ["Environment", "Application", "Solution Stack"]
         
     | 
| 
      
 4 
     | 
    
         
            +
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def data
         
     | 
| 
      
 7 
     | 
    
         
            +
                eb_environments.map do |environment|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  [
         
     | 
| 
      
 9 
     | 
    
         
            +
                    environment.environment_name,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    environment.application_name,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    environment.solution_stack_name,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def eb_environments
         
     | 
| 
      
 17 
     | 
    
         
            +
                @eb_environments ||= eb.describe_environments.environments
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Ec2 < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def header
         
     | 
| 
      
 3 
     | 
    
         
            +
                ["Name", "Instance Id", "Instance Type", "Platform", "Security Groups"]
         
     | 
| 
      
 4 
     | 
    
         
            +
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def data
         
     | 
| 
      
 7 
     | 
    
         
            +
                instances.map do |i|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  name = name_from_tag(i)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  group_names = security_group_names(i)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # cost = cost(i)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  [
         
     | 
| 
      
 13 
     | 
    
         
            +
                    name,
         
     | 
| 
      
 14 
     | 
    
         
            +
                    i.instance_id,
         
     | 
| 
      
 15 
     | 
    
         
            +
                    i.instance_type,
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # cost,
         
     | 
| 
      
 17 
     | 
    
         
            +
                    platform(i), # windows or linux
         
     | 
| 
      
 18 
     | 
    
         
            +
                    group_names,
         
     | 
| 
      
 19 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def name_from_tag(instance)
         
     | 
| 
      
 24 
     | 
    
         
            +
                tags = instance.tags
         
     | 
| 
      
 25 
     | 
    
         
            +
                name_tag = tags.find { |t| t.key == "Name" }
         
     | 
| 
      
 26 
     | 
    
         
            +
                name_tag ? name_tag.value : "(unnamed)"
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def security_group_names(instance)
         
     | 
| 
      
 30 
     | 
    
         
            +
                instance.security_groups.map {|sg| sg.group_name}.join(', ')
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              def cost(instance)
         
     | 
| 
      
 34 
     | 
    
         
            +
                cost_type = COST_MAP[instance.instance_type]
         
     | 
| 
      
 35 
     | 
    
         
            +
                if cost_type
         
     | 
| 
      
 36 
     | 
    
         
            +
                  cost = cost_type[platform(instance)]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  cost.round(2)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              def platform(instance)
         
     | 
| 
      
 42 
     | 
    
         
            +
                instance.platform || "linux"
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              # hardcode pricing info until access to pricing api is sorted out
         
     | 
| 
      
 46 
     | 
    
         
            +
              # these costs are per month.
         
     | 
| 
      
 47 
     | 
    
         
            +
              COST_MAP = {
         
     | 
| 
      
 48 
     | 
    
         
            +
                "t2.micro" => {
         
     | 
| 
      
 49 
     | 
    
         
            +
                  "windows" => 11.826,
         
     | 
| 
      
 50 
     | 
    
         
            +
                  "linux" => 8.468,
         
     | 
| 
      
 51 
     | 
    
         
            +
                },
         
     | 
| 
      
 52 
     | 
    
         
            +
                "t2.medium" => {
         
     | 
| 
      
 53 
     | 
    
         
            +
                  "windows" => 47.012,
         
     | 
| 
      
 54 
     | 
    
         
            +
                  "linux" => 33.872,
         
     | 
| 
      
 55 
     | 
    
         
            +
                },
         
     | 
| 
      
 56 
     | 
    
         
            +
                "t2.large" => {
         
     | 
| 
      
 57 
     | 
    
         
            +
                  "windows" => 88.184,
         
     | 
| 
      
 58 
     | 
    
         
            +
                  "linux" => 67.744,
         
     | 
| 
      
 59 
     | 
    
         
            +
                },
         
     | 
| 
      
 60 
     | 
    
         
            +
                "r3.4xlarge" => {
         
     | 
| 
      
 61 
     | 
    
         
            +
                  "windows" => 1419.12,
         
     | 
| 
      
 62 
     | 
    
         
            +
                  "linux" => 970.9,
         
     | 
| 
      
 63 
     | 
    
         
            +
                },
         
     | 
| 
      
 64 
     | 
    
         
            +
                "m4.large" => {
         
     | 
| 
      
 65 
     | 
    
         
            +
                  "windows" => 140.16,
         
     | 
| 
      
 66 
     | 
    
         
            +
                  "linux" => 73.0,
         
     | 
| 
      
 67 
     | 
    
         
            +
                },
         
     | 
| 
      
 68 
     | 
    
         
            +
                "m4.2xlarge" => {
         
     | 
| 
      
 69 
     | 
    
         
            +
                  "windows" => 560.64,
         
     | 
| 
      
 70 
     | 
    
         
            +
                  "linux" => 292,
         
     | 
| 
      
 71 
     | 
    
         
            +
                },
         
     | 
| 
      
 72 
     | 
    
         
            +
                "c3.2xlarge" => {
         
     | 
| 
      
 73 
     | 
    
         
            +
                  "windows" => 548.96,
         
     | 
| 
      
 74 
     | 
    
         
            +
                  "linux" => 306.6,
         
     | 
| 
      
 75 
     | 
    
         
            +
                },
         
     | 
| 
      
 76 
     | 
    
         
            +
              }
         
     | 
| 
      
 77 
     | 
    
         
            +
              # Currently dont have access to the pricing api so skipping
         
     | 
| 
      
 78 
     | 
    
         
            +
              # def describe_pricing
         
     | 
| 
      
 79 
     | 
    
         
            +
              #   resp = pricing.describe_services(
         
     | 
| 
      
 80 
     | 
    
         
            +
              #     format_version: "aws_v1",
         
     | 
| 
      
 81 
     | 
    
         
            +
              #     max_results: 1,
         
     | 
| 
      
 82 
     | 
    
         
            +
              #     service_code: "AmazonEC2",
         
     | 
| 
      
 83 
     | 
    
         
            +
              #   )
         
     | 
| 
      
 84 
     | 
    
         
            +
              #   pp resp
         
     | 
| 
      
 85 
     | 
    
         
            +
              # end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Ecs::Cluster < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def header
         
     | 
| 
      
 3 
     | 
    
         
            +
                ["Cluster", "Container Instances", "Running Tasks"]
         
     | 
| 
      
 4 
     | 
    
         
            +
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def data
         
     | 
| 
      
 7 
     | 
    
         
            +
                ecs_clusters.map do |cluster|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  [
         
     | 
| 
      
 9 
     | 
    
         
            +
                    cluster.cluster_name,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    cluster.registered_container_instances_count,
         
     | 
| 
      
 11 
     | 
    
         
            +
                    cluster.running_tasks_count,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def ecs_clusters
         
     | 
| 
      
 17 
     | 
    
         
            +
                cluster_arns = ecs.list_clusters.cluster_arns
         
     | 
| 
      
 18 
     | 
    
         
            +
                @ecs_clusters ||= ecs.describe_clusters(clusters: cluster_arns).clusters
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Ecs::Service < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def header
         
     | 
| 
      
 3 
     | 
    
         
            +
                ["Service", "Cluster", "Running Tasks"]
         
     | 
| 
      
 4 
     | 
    
         
            +
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def data
         
     | 
| 
      
 7 
     | 
    
         
            +
                ecs_services.map do |service|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  [
         
     | 
| 
      
 9 
     | 
    
         
            +
                    service.service_name,
         
     | 
| 
      
 10 
     | 
    
         
            +
                    cluster_name(service.cluster_arn),
         
     | 
| 
      
 11 
     | 
    
         
            +
                    service.running_count,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def cluster_name(cluster_arn)
         
     | 
| 
      
 17 
     | 
    
         
            +
                resp = ecs.describe_clusters(clusters: [cluster_arn]) # cluster takes name or ARN
         
     | 
| 
      
 18 
     | 
    
         
            +
                resp.clusters.first.cluster_name
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def ecs_services
         
     | 
| 
      
 22 
     | 
    
         
            +
                cluster_arns = ecs.list_clusters.cluster_arns
         
     | 
| 
      
 23 
     | 
    
         
            +
                @ecs_services ||= cluster_arns.map do |cluster_arn|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    service_arns = ecs.list_services(cluster: cluster_arn).service_arns
         
     | 
| 
      
 25 
     | 
    
         
            +
                    resp = ecs.describe_services(services: service_arns, cluster: cluster_arn)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    resp.services
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end.flatten
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # pp @ecs_services
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @ecs_services
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @ecs_services ||= ecs.describe_services.services
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Elb < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def header
         
     | 
| 
      
 3 
     | 
    
         
            +
                ["ELB", "Type", "Security Group", "Open Ports"]
         
     | 
| 
      
 4 
     | 
    
         
            +
              end
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def data
         
     | 
| 
      
 7 
     | 
    
         
            +
                data = []
         
     | 
| 
      
 8 
     | 
    
         
            +
                elbs.each do |lb|
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # lb.security_groups is actualy a list of group_ids
         
     | 
| 
      
 10 
     | 
    
         
            +
                  lb.security_groups.each do |group_id|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    security_group_name = security_group_name(group_id) # weird: sometimes sg doesnt exist
         
     | 
| 
      
 12 
     | 
    
         
            +
                    open_ports = open_ports(group_id)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    data << [
         
     | 
| 
      
 15 
     | 
    
         
            +
                      lb.load_balancer_name,
         
     | 
| 
      
 16 
     | 
    
         
            +
                      lb_type(lb),
         
     | 
| 
      
 17 
     | 
    
         
            +
                      security_group_name,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      open_ports]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                data
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def lb_type(lb)
         
     | 
| 
      
 26 
     | 
    
         
            +
                lb.respond_to?(:type) ? lb.type : 'classic'
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def elbs
         
     | 
| 
      
 30 
     | 
    
         
            +
                application_load_balancers + classic_load_balancers
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              # override custom sort
         
     | 
| 
      
 34 
     | 
    
         
            +
              def sort(data)
         
     | 
| 
      
 35 
     | 
    
         
            +
                data
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def classic_load_balancers
         
     | 
| 
      
 39 
     | 
    
         
            +
                @classic_load_balancers ||= elbv1.describe_load_balancers.load_balancer_descriptions
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def security_group_names(lb)
         
     | 
| 
      
 43 
     | 
    
         
            +
                # lb.security_groups is actualy a list of group_ids
         
     | 
| 
      
 44 
     | 
    
         
            +
                lb.security_groups.map do |group_id|
         
     | 
| 
      
 45 
     | 
    
         
            +
                  security_group_name(group_id)
         
     | 
| 
      
 46 
     | 
    
         
            +
                end.join(', ')
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              # Somehow sometimes there can be an ELB with a security group that does
         
     | 
| 
      
 50 
     | 
    
         
            +
              # not actually exist.  In the AWS Console it says:
         
     | 
| 
      
 51 
     | 
    
         
            +
              #  "There was an error loading the Security Groups."
         
     | 
| 
      
 52 
     | 
    
         
            +
              def security_group_name(group_id)
         
     | 
| 
      
 53 
     | 
    
         
            +
                security_group = security_groups.find { |sg| sg.group_id == group_id }
         
     | 
| 
      
 54 
     | 
    
         
            +
                group_name = security_group ? security_group.group_name : "not found"
         
     | 
| 
      
 55 
     | 
    
         
            +
                "#{group_id} (#{group_name})"
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              def application_load_balancers
         
     | 
| 
      
 59 
     | 
    
         
            +
                @application_load_balancers ||= elbv2.describe_load_balancers.load_balancers
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              # Returns an Array of ports with a cidr of 0.0.0.0/0
         
     | 
| 
      
 63 
     | 
    
         
            +
              # Delegates to Inventory::SecurityGroup
         
     | 
| 
      
 64 
     | 
    
         
            +
              def open_ports(group_id)
         
     | 
| 
      
 65 
     | 
    
         
            +
                sg = security_groups.find { |sg| sg.group_id == group_id }
         
     | 
| 
      
 66 
     | 
    
         
            +
                return unless sg
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                inventory = Inventory::SecurityGroup::Open.new(@options)
         
     | 
| 
      
 69 
     | 
    
         
            +
                inventory.ports_open_to_world(sg)
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the AWS Certificate Manager inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the CloudFormation inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the CloudWatch inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the Elastic Beanstalk inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the EC2 inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the ECS inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the Elastic Load Balancer inventory. Reports both Classic and Application Load Balancers.
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the IAM inventory.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            List of groups and users in the groups:
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            $ inventory iam --report-type groups # this is the default
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            $ inventory iam  # same as above
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            List of the users and their groups:
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            $ inventory iam --report-type users
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Summary of number of groups and users
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            $ inventory iam --report-type summary
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the Keypair inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the security groups inventory
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Reports the VPC inventory
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Iam < Inventory::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              autoload :Shared, "inventory/iam/shared"
         
     | 
| 
      
 3 
     | 
    
         
            +
              autoload :Summary, "inventory/iam/summary"
         
     | 
| 
      
 4 
     | 
    
         
            +
              autoload :User, "inventory/iam/user"
         
     | 
| 
      
 5 
     | 
    
         
            +
              autoload :Group, "inventory/iam/group"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              # Default is the groups report because it seems like the most useful report
         
     | 
| 
      
 8 
     | 
    
         
            +
              def report
         
     | 
| 
      
 9 
     | 
    
         
            +
                Summary.new(@options).report if show(:summary)
         
     | 
| 
      
 10 
     | 
    
         
            +
                User.new(@options).report if show(:users)
         
     | 
| 
      
 11 
     | 
    
         
            +
                Group.new(@options).report if show(:groups)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Inventory::Iam
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Group < Inventory::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Shared
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def header
         
     | 
| 
      
 6 
     | 
    
         
            +
                  ["Group Name", "User Count", "User Names"]
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def data
         
     | 
| 
      
 10 
     | 
    
         
            +
                  data = [["(groupless)", groupless_users.size, groupless_users.join(', ')]]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  data += groups.map do |group|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    group_users = users_in_group(group.group_name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    [
         
     | 
| 
      
 14 
     | 
    
         
            +
                      group.group_name,
         
     | 
| 
      
 15 
     | 
    
         
            +
                      group_users.size,
         
     | 
| 
      
 16 
     | 
    
         
            +
                      group_users.join(', ')
         
     | 
| 
      
 17 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  data
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Inventory::Iam::Shared
         
     | 
| 
      
 2 
     | 
    
         
            +
              def group_names(user)
         
     | 
| 
      
 3 
     | 
    
         
            +
                groups = groups_for(user)
         
     | 
| 
      
 4 
     | 
    
         
            +
                groups.map(&:group_name)
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              @@groups = {}
         
     | 
| 
      
 8 
     | 
    
         
            +
              def groups_for(user)
         
     | 
| 
      
 9 
     | 
    
         
            +
                return @@groups[user.user_name] if @@groups[user.user_name]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                @@groups[user.user_name] = iam.list_groups_for_user(user_name: user.user_name).groups
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              # iam.list_groups does not show the users in the groups.
         
     | 
| 
      
 15 
     | 
    
         
            +
              # so users_in_groups returns an Array of the user_names in the specified group
         
     | 
| 
      
 16 
     | 
    
         
            +
              def users_in_group(group_name)
         
     | 
| 
      
 17 
     | 
    
         
            +
                # user_name is a String
         
     | 
| 
      
 18 
     | 
    
         
            +
                # group_names is an Array of Strings
         
     | 
| 
      
 19 
     | 
    
         
            +
                selected_users = all_users.select do |user_name, group_names|
         
     | 
| 
      
 20 
     | 
    
         
            +
                    group_names.include?(group_name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                selected_users.map { |a| a[0] }
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def groupless_users
         
     | 
| 
      
 26 
     | 
    
         
            +
                selected_users = all_users.select do |user_name, group_names|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    group_names.empty?
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  selected_users.map { |a| a[0] }
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              # {
         
     | 
| 
      
 33 
     | 
    
         
            +
              #   "tung": ["admin", "developers"],
         
     | 
| 
      
 34 
     | 
    
         
            +
              #   "vuon": ["admin"],
         
     | 
| 
      
 35 
     | 
    
         
            +
              #   "bob": ["developers"]
         
     | 
| 
      
 36 
     | 
    
         
            +
              # }
         
     | 
| 
      
 37 
     | 
    
         
            +
              def all_users
         
     | 
| 
      
 38 
     | 
    
         
            +
                @all_users ||= users.inject({}) do |result, user|
         
     | 
| 
      
 39 
     | 
    
         
            +
                  result[user.user_name] = group_names(user)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  result
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              def user_count(group)
         
     | 
| 
      
 45 
     | 
    
         
            +
                group_counts[group.group_name]
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              def user_names(group)
         
     | 
| 
      
 49 
     | 
    
         
            +
                users.each do |user|
         
     | 
| 
      
 50 
     | 
    
         
            +
                  result[user.user_name] = group_names(user)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  result
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              def users
         
     | 
| 
      
 56 
     | 
    
         
            +
                @users ||= iam.list_users.users
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              def groups
         
     | 
| 
      
 60 
     | 
    
         
            +
                @groups ||= iam.list_groups.groups
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     |