class Subiam::Exporter

Constants

AWS_MANAGED_POLICY_PREFIX

Public Class Methods

export(iam, options = {}) click to toggle source
# File lib/subiam/exporter.rb, line 5
def self.export(iam, options = {})
  self.new(iam, options).export
end
new(iam, options = {}) click to toggle source
# File lib/subiam/exporter.rb, line 9
def initialize(iam, options = {})
  @iam = iam
  @options = options
  @mutex = Mutex.new
  @concurrency = options[:export_concurrency] || 16
end

Public Instance Methods

export() click to toggle source
# File lib/subiam/exporter.rb, line 16
def export
  account_authorization_details = get_account_authorization_details

  users = account_authorization_details[:user_detail_list]
  groups = account_authorization_details[:group_detail_list]
  roles = account_authorization_details[:role_detail_list]
  policies = account_authorization_details[:policies]
  instance_profiles = list_instance_profiles
  group_users = {}
  instance_profile_roles = {}

  unless @options[:no_progress]
    progress_total = users.length + groups.length + roles.length + instance_profiles.length

    @progressbar = ProgressBar.create(
                     :format => ' %bᗧ%i %p%%',
                     :progress_mark  => ' ',
                     :remainder_mark => '・',
                     :total => progress_total,
                     :output => $stderr)
  end

  expected = {
    :users => export_users(users, group_users),
    :groups => export_groups(groups),
    :roles => export_roles(roles, instance_profile_roles),
    :instance_profiles => export_instance_profiles(instance_profiles),
    :policies => export_policies(policies),
  }

  [expected, group_users, instance_profile_roles]
end

Private Instance Methods

export_group_policies(group) click to toggle source
# File lib/subiam/exporter.rb, line 127
def export_group_policies(group)
  result = {}

  group.group_policy_list.each do |policy|
    document = CGI.unescape(policy.policy_document)
    result[policy.policy_name] = JSON.parse(document)
  end

  result
end
export_groups(groups) click to toggle source
# File lib/subiam/exporter.rb, line 105
def export_groups(groups)
  result = {}

  Parallel.each(groups, :in_threads => @concurrency) do |group|
    group_name = group.group_name
    policies = export_group_policies(group)
    attached_managed_policies = group.attached_managed_policies.map(&:policy_arn)

    @mutex.synchronize do
      result[group_name] = {
        :path => group.path,
        :policies => policies,
        :attached_managed_policies => attached_managed_policies,
      }

      progress
    end
  end

  result
end
export_instance_profiles(instance_profiles) click to toggle source
# File lib/subiam/exporter.rb, line 181
def export_instance_profiles(instance_profiles)
  result = {}

  Parallel.each(instance_profiles, :in_threads => @concurrency) do |instance_profile|
    instance_profile_name = instance_profile.instance_profile_name

    @mutex.synchronize do
      result[instance_profile_name] = {
        :path => instance_profile.path,
      }

      progress
    end
  end

  result
end
export_login_profile(user_name) click to toggle source
# File lib/subiam/exporter.rb, line 96
def export_login_profile(user_name)
  begin
    resp = @iam.get_login_profile(:user_name => user_name)
    {:password_reset_required => resp.login_profile.password_reset_required}
  rescue Aws::IAM::Errors::NoSuchEntity
    nil
  end
end
export_policies(policies) click to toggle source
# File lib/subiam/exporter.rb, line 199
def export_policies(policies)
  result = {}

  Parallel.each(policies, :in_threads => @concurrency) do |policy|
    if policy.arn.start_with?(AWS_MANAGED_POLICY_PREFIX)
      next
    end

    policy_name = policy.policy_name
    document = export_policy_document(policy)

    result[policy_name] = {
      :path => policy.path,
      :document => document,
    }
  end

  result
end
export_policy_document(policy) click to toggle source
# File lib/subiam/exporter.rb, line 219
def export_policy_document(policy)
  policy_version = nil

  policy_version_list = policy.policy_version_list.sort_by do |pv|
    pv.version_id[1..-1].to_i
  end

  policy_version_list.each do |pv|
    policy_version = pv

    if pv.is_default_version
      break
    end
  end

  document = CGI.unescape(policy_version.document)
  JSON.parse(document)
end
export_role_policies(role) click to toggle source
# File lib/subiam/exporter.rb, line 170
def export_role_policies(role)
  result = {}

  role.role_policy_list.each do |policy|
    document = CGI.unescape(policy.policy_document)
    result[policy.policy_name] = JSON.parse(document)
  end

  result
end
export_roles(roles, instance_profile_roles) click to toggle source
# File lib/subiam/exporter.rb, line 138
def export_roles(roles, instance_profile_roles)
  result = {}

  Parallel.each(roles, :in_threads => @concurrency) do |role|
    role_name = role.role_name
    instance_profiles = role.instance_profile_list.map {|i| i.instance_profile_name }
    policies = export_role_policies(role)
    attached_managed_policies = role.attached_managed_policies.map(&:policy_arn)

    @mutex.synchronize do
      instance_profiles.each do |instance_profile_name|
        instance_profile_roles[instance_profile_name] ||= []
        instance_profile_roles[instance_profile_name] << role_name
      end

      document = CGI.unescape(role.assume_role_policy_document)

      result[role_name] = {
        :path => role.path,
        :assume_role_policy_document => JSON.parse(document),
        :instance_profiles => instance_profiles,
        :policies => policies,
        :attached_managed_policies => attached_managed_policies,
      }

      progress
    end
  end

  result
end
export_user_policies(user) click to toggle source
# File lib/subiam/exporter.rb, line 85
def export_user_policies(user)
  result = {}

  user.user_policy_list.each do |policy|
    document = CGI.unescape(policy.policy_document)
    result[policy.policy_name] = JSON.parse(document)
  end

  result
end
export_users(users, group_users) click to toggle source
# File lib/subiam/exporter.rb, line 51
def export_users(users, group_users)
  result = {}

  Parallel.each(users, :in_threads => @concurrency) do |user|
    user_name = user.user_name
    groups = user.group_list
    policies = export_user_policies(user)
    login_profile = export_login_profile(user_name)
    attached_managed_policies = user.attached_managed_policies.map(&:policy_arn)

    @mutex.synchronize do
      groups.each do |group_name|
        group_users[group_name] ||= []
        group_users[group_name] << user_name
      end

      result[user_name] = {
        :path => user.path,
        :groups => groups,
        :policies => policies,
        :attached_managed_policies => attached_managed_policies
      }

      if login_profile
        result[user_name][:login_profile] = login_profile
      end

      progress
    end
  end

  result
end
get_account_authorization_details() click to toggle source
# File lib/subiam/exporter.rb, line 244
def get_account_authorization_details
  account_authorization_details = {}

  unless @options[:no_progress]
    progressbar = ProgressBar.create(:title => 'Loading', :total => nil, :output => $stderr)
  end

  keys = [
    :user_detail_list,
    :group_detail_list,
    :role_detail_list,
    :policies,
  ]

  keys.each do |key|
    account_authorization_details[key] = []
  end

  @iam.get_account_authorization_details.each do |resp|
    keys.each do |key|
      account_authorization_details[key].concat(resp[key])

      unless @options[:no_progress]
        progressbar.increment
      end
    end
  end

  account_authorization_details
end
list_instance_profiles() click to toggle source
# File lib/subiam/exporter.rb, line 238
def list_instance_profiles
  @iam.list_instance_profiles.map {|resp|
    resp.instance_profiles.to_a
  }.flatten
end
progress() click to toggle source
# File lib/subiam/exporter.rb, line 275
def progress
  @progressbar.increment if @progressbar
end