class Miam::Driver

Constants

MAX_POLICY_SIZE
MAX_POLICY_VERSIONS

Public Class Methods

new(iam, sts, options = {}) click to toggle source
# File lib/miam/driver.rb, line 7
def initialize(iam, sts, options = {})
  @iam = iam
  @sts = sts
  @options = options
  @account_id = nil
end

Public Instance Methods

add_role_to_instance_profiles(role_name, instance_profile_names) click to toggle source
# File lib/miam/driver.rb, line 220
def add_role_to_instance_profiles(role_name, instance_profile_names)
  log(:info, "Update Role `#{role_name}`", :color => :green)
  log(:info, "  add instance_profiles=#{instance_profile_names.join(',')}", :color => :green)

  unless_dry_run do
    instance_profile_names.each do |instance_profile_name|
      @iam.add_role_to_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
    end
  end
end
add_user_to_groups(user_name, group_names) click to toggle source
# File lib/miam/driver.rb, line 117
def add_user_to_groups(user_name, group_names)
  log(:info, "Update User `#{user_name}`", :color => :green)
  log(:info, "  add groups=#{group_names.join(',')}", :color => :green)

  unless_dry_run do
    group_names.each do |group_name|
      @iam.add_user_to_group(:group_name => group_name, :user_name => user_name)
    end
  end
end
attach_policies(type, name, policies) click to toggle source
# File lib/miam/driver.rb, line 342
def attach_policies(type, name, policies)
  type = type.to_s
  type_s = type.slice(0, 1).upcase + type.slice(1..-1)

  log(:info, "Update #{type_s} `#{name}`", :color => :green)
  log(:info, "  attach policies=#{policies.join(',')}", :color => :green)

  unless_dry_run do
    policies.each do |arn|
      @iam.send("attach_#{type}_policy", :"#{type}_name" => name, :policy_arn => arn)
    end
  end
end
create_access_key(user_name) click to toggle source
# File lib/miam/driver.rb, line 28
def create_access_key(user_name)
  log(:info, "Create access key for User `#{user_name}`", :color => :cyan)
  access_key = nil

  unless_dry_run do
    resp = @iam.create_access_key(:user_name => user_name)

    access_key = {
      :access_key_id => resp.access_key.access_key_id,
      :secret_access_key => resp.access_key.secret_access_key,
    }
  end

  access_key
end
create_group(group_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 139
def create_group(group_name, attrs)
  log(:info, "Create Group `#{group_name}`", :color => :cyan)

  unless_dry_run do
    params = {:group_name => group_name}
    params[:path] = attrs[:path] if attrs[:path]
    @iam.create_group(params)
  end

  new_group_attrs = {:policies => {}, :attached_managed_policies => []}
  new_group_attrs[:path] = attrs[:path] if attrs[:path]
  new_group_attrs
end
create_instance_profile(instance_profile_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 262
def create_instance_profile(instance_profile_name, attrs)
  log(:info, "Create InstanceProfile `#{instance_profile_name}`", :color => :cyan)

  unless_dry_run do
    params = {:instance_profile_name => instance_profile_name}
    params[:path] = attrs[:path] if attrs[:path]
    @iam.create_instance_profile(params)
  end

  new_instance_profile_attrs = {}
  new_instance_profile_attrs[:path] = attrs[:path] if attrs[:path]
  new_instance_profile_attrs
end
create_login_profile(user_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 84
def create_login_profile(user_name, attrs)
  log_attrs = attrs.dup
  log_attrs.delete(:password)

  log(:info, "Update User `#{user_name}`", :color => :green)
  log(:info, "  create login profile: #{log_attrs.inspect}", :color => :green)

  unless_dry_run do
    @iam.create_login_profile(attrs.merge(:user_name => user_name))
  end
end
create_managed_policy(policy_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 386
def create_managed_policy(policy_name, attrs)
  log(:info, "Create ManagedPolicy `#{policy_name}`", :color => :cyan)

  unless_dry_run do
    params = {
      :policy_name => policy_name,
      :path => attrs[:path],
      :policy_document => encode_document(attrs[:document]),
    }

    @iam.create_policy(params)
  end
end
create_policy(type, user_or_group_name, policy_name, policy_document) click to toggle source
# File lib/miam/driver.rb, line 307
def create_policy(type, user_or_group_name, policy_name, policy_document)
  log(:info, "Create #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :cyan)
  log(:info, "  #{policy_document.pretty_inspect.gsub("\n", "\n  ").strip}", :color => :cyan)
  put_policy(type, user_or_group_name, policy_name, policy_document)
end
create_role(role_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 173
def create_role(role_name, attrs)
  log(:info, "Create Role `#{role_name}`", :color => :cyan)
  assume_role_policy_document = attrs.fetch(:assume_role_policy_document)

  unless_dry_run do
    params = {
      :role_name => role_name,
      :assume_role_policy_document => encode_document(assume_role_policy_document),
      :max_session_duration => attrs.fetch(:max_session_duration)
    }

    params[:path] = attrs[:path] if attrs[:path]
    @iam.create_role(params)
  end

  new_role_attrs = {
    :instance_profiles => [],
    :assume_role_policy_document => assume_role_policy_document,
    :policies => {},
    :attached_managed_policies => [],
    :max_session_duration => attrs.fetch(:max_session_duration),
  }

  new_role_attrs[:path] = attrs[:path] if attrs[:path]
  new_role_attrs
end
create_user(user_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 14
def create_user(user_name, attrs)
  log(:info, "Create User `#{user_name}`", :color => :cyan)

  unless_dry_run do
    params = {:user_name => user_name}
    params[:path] = attrs[:path] if attrs[:path]
    @iam.create_user(params)
  end

  new_user_attrs = {:groups => [], :policies => {}, :attached_managed_policies => []}
  new_user_attrs[:path] = attrs[:path] if attrs[:path]
  new_user_attrs
end
delete_group(group_name, attrs, users_in_group) click to toggle source
# File lib/miam/driver.rb, line 153
def delete_group(group_name, attrs, users_in_group)
  log(:info, "Delete Group `#{group_name}`", :color => :red)

  unless_dry_run do
    attrs[:policies].keys.each do |policy_name|
      @iam.delete_group_policy(:group_name => group_name, :policy_name => policy_name)
    end

    users_in_group.each do |user_name|
      @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
    end

    attrs[:attached_managed_policies].each do |policy_arn|
      @iam.detach_group_policy(:group_name => group_name, :policy_arn => policy_arn)
    end

    @iam.delete_group(:group_name => group_name)
  end
end
delete_instance_profile(instance_profile_name, attrs, roles_in_instance_profile) click to toggle source
# File lib/miam/driver.rb, line 276
def delete_instance_profile(instance_profile_name, attrs, roles_in_instance_profile)
  log(:info, "Delete InstanceProfile `#{instance_profile_name}`", :color => :red)

  unless_dry_run do
    roles_in_instance_profile.each do |role_name|
      @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
    end

    @iam.delete_instance_profile(:instance_profile_name => instance_profile_name)
  end
end
delete_login_profile(user_name) click to toggle source
# File lib/miam/driver.rb, line 96
def delete_login_profile(user_name)
  log(:info, "Update User `#{user_name}`", :color => :green)
  log(:info, "  delete login profile", :color => :green)

  unless_dry_run do
    @iam.delete_login_profile(:user_name => user_name)
  end
end
delete_managed_policy(policy_name, policy_path) click to toggle source
# File lib/miam/driver.rb, line 400
def delete_managed_policy(policy_name, policy_path)
  log(:info, "Delete ManagedPolicy `#{policy_name}`", :color => :red)

  unless_dry_run do
    policy_versions = @iam.list_policy_versions(
      :policy_arn => policy_arn(policy_name, policy_path),
      :max_items => MAX_POLICY_VERSIONS
    )

    policy_versions.versions.reject {|pv|
      pv.is_default_version
    }.each {|pv|
      @iam.delete_policy_version(
        :policy_arn => policy_arn(policy_name, policy_path),
        :version_id => pv.version_id
      )
    }

    @iam.delete_policy(
      :policy_arn => policy_arn(policy_name, policy_path)
    )
  end
end
delete_policy(type, user_or_group_name, policy_name) click to toggle source
# File lib/miam/driver.rb, line 319
def delete_policy(type, user_or_group_name, policy_name)
  logmsg = "Delete #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`"
  log(:info, logmsg, :color => :red)

  unless_dry_run do
    params = {:policy_name => policy_name}
    params["#{type}_name".to_sym] = user_or_group_name
    @iam.send("delete_#{type}_policy", params)
  end
end
delete_role(role_name, instance_profile_names, attrs) click to toggle source
# File lib/miam/driver.rb, line 200
def delete_role(role_name, instance_profile_names, attrs)
  log(:info, "Delete Role `#{role_name}`", :color => :red)

  unless_dry_run do
    attrs[:policies].keys.each do |policy_name|
      @iam.delete_role_policy(:role_name => role_name, :policy_name => policy_name)
    end

    instance_profile_names.each do |instance_profile_name|
      @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
    end

    attrs[:attached_managed_policies].each do |policy_arn|
      @iam.detach_role_policy(:role_name => role_name, :policy_arn => policy_arn)
    end

    @iam.delete_role(:role_name => role_name)
  end
end
delete_user(user_name, attrs) click to toggle source
# File lib/miam/driver.rb, line 44
def delete_user(user_name, attrs)
  log(:info, "Delete User `#{user_name}`", :color => :red)

  unless_dry_run do
    if attrs[:login_profile]
      @iam.delete_login_profile(:user_name => user_name)
    end

    attrs[:policies].keys.each do |policy_name|
      @iam.delete_user_policy(:user_name => user_name, :policy_name => policy_name)
    end

    attrs[:groups].each do |group_name|
      @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
    end

    attrs[:attached_managed_policies].each do |policy_arn|
      @iam.detach_user_policy(:user_name => user_name, :policy_arn => policy_arn)
    end

    list_access_key_ids(user_name).each do |access_key_id|
      @iam.delete_access_key(:user_name => user_name, :access_key_id => access_key_id)
    end

    list_signing_certificate_ids(user_name).each do |certificate_id|
      @iam.delete_signing_certificate(:user_name => user_name, :certificate_id => certificate_id)
    end

    mfa_devices = @iam.list_mfa_devices(:user_name => user_name).map {|resp|
      resp.mfa_devices
    }.flatten

    mfa_devices.each do |md|
      @iam.deactivate_mfa_device(:user_name => user_name, :serial_number => md.serial_number)
    end

    @iam.delete_user(:user_name => user_name)
  end
end
detach_policies(type, name, policies) click to toggle source
# File lib/miam/driver.rb, line 356
def detach_policies(type, name, policies)
  type = type.to_s
  type_s = type.slice(0, 1).upcase + type.slice(1..-1)

  log(:info, "Update #{type_s} `#{name}`", :color => :green)
  log(:info, "  detach policies=#{policies.join(',')}", :color => :red)

  unless_dry_run do
    policies.each do |arn|
      @iam.send("detach_#{type}_policy", :"#{type}_name" => name, :policy_arn => arn)
    end
  end
end
list_access_key_ids(user_name) click to toggle source
# File lib/miam/driver.rb, line 370
def list_access_key_ids(user_name)
  @iam.list_access_keys(:user_name => user_name).map {|resp|
    resp.access_key_metadata.map do |metadata|
      metadata.access_key_id
    end
  }.flatten
end
list_signing_certificate_ids(user_name) click to toggle source
# File lib/miam/driver.rb, line 378
def list_signing_certificate_ids(user_name)
  @iam.list_signing_certificates(:user_name => user_name).map {|resp|
    resp.certificates.map do |cert|
      cert.certificate_id
    end
  }.flatten
end
password_policy() click to toggle source
# File lib/miam/driver.rb, line 453
def password_policy
  return @password_policy if instance_variable_defined?(:@password_policy)

  @password_policy = @iam.get_account_password_policy.password_policy
rescue Aws::IAM::Errors::NoSuchEntity
  @password_policy = nil
end
put_policy(type, user_or_group_name, policy_name, policy_document) click to toggle source
# File lib/miam/driver.rb, line 330
def put_policy(type, user_or_group_name, policy_name, policy_document)
  unless_dry_run do
    params = {
      :policy_name => policy_name,
      :policy_document => encode_document(policy_document),
    }

    params["#{type}_name".to_sym] = user_or_group_name
    @iam.send("put_#{type}_policy", params)
  end
end
remove_role_from_instance_profiles(role_name, instance_profile_names) click to toggle source
# File lib/miam/driver.rb, line 231
def remove_role_from_instance_profiles(role_name, instance_profile_names)
  log(:info, "Update Role `#{role_name}`", :color => :green)
  log(:info, "  remove instance_profiles=#{instance_profile_names.join(',')}", :color => :green)

  unless_dry_run do
    instance_profile_names.each do |instance_profile_name|
      @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
    end
  end
end
remove_user_from_groups(user_name, group_names) click to toggle source
# File lib/miam/driver.rb, line 128
def remove_user_from_groups(user_name, group_names)
  log(:info, "Update User `#{user_name}`", :color => :green)
  log(:info, "  remove groups=#{group_names.join(',')}", :color => :green)

  unless_dry_run do
    group_names.each do |group_name|
      @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
    end
  end
end
update_assume_role_policy(role_name, policy_document, old_policy_document) click to toggle source
# File lib/miam/driver.rb, line 250
def update_assume_role_policy(role_name, policy_document, old_policy_document)
  log(:info, "Update Role `#{role_name}` > AssumeRolePolicy", :color => :green)
  log(:info, Miam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)

  unless_dry_run do
    @iam.update_assume_role_policy(
      :role_name => role_name,
      :policy_document => encode_document(policy_document),
    )
  end
end
update_login_profile(user_name, attrs, old_attrs) click to toggle source
# File lib/miam/driver.rb, line 105
def update_login_profile(user_name, attrs, old_attrs)
  log_attrs = attrs.dup
  log_attrs.delete(:password)

  log(:info, "Update User `#{user_name}`", :color => :green)
  log(:info, "  login profile:\n".green + Miam::Utils.diff(old_attrs, attrs, :color => @options[:color], :indent => '    '), :color => false)

  unless_dry_run do
    @iam.update_login_profile(attrs.merge(:user_name => user_name))
  end
end
update_managed_policy(policy_name, policy_path, policy_document, old_policy_document) click to toggle source
# File lib/miam/driver.rb, line 424
def update_managed_policy(policy_name, policy_path, policy_document, old_policy_document)
  log(:info, "Update ManagedPolicy `#{policy_name}`", :color => :green)
  log(:info, Miam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)

  unless_dry_run do
    policy_versions = @iam.list_policy_versions(
      :policy_arn => policy_arn(policy_name, policy_path),
      :max_items => MAX_POLICY_VERSIONS
    )

    if policy_versions.versions.length >= MAX_POLICY_VERSIONS
      delete_policy_version = policy_versions.versions.reject {|pv|
        pv.is_default_version
      }.sort_by {|pv| pv.version_id[1..-1].to_i }.first

      @iam.delete_policy_version(
        :policy_arn => policy_arn(policy_name, policy_path),
        :version_id => delete_policy_version.version_id
      )
    end

    @iam.create_policy_version(
      :policy_arn => policy_arn(policy_name, policy_path),
      :policy_document => encode_document(policy_document),
      set_as_default: true
    )
  end
end
update_name(type, user_or_group_name, new_name) click to toggle source
# File lib/miam/driver.rb, line 288
def update_name(type, user_or_group_name, new_name)
  log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
  log(:info, "  name:\n".green + Miam::Utils.diff(user_or_group_name, new_name, :color => @options[:color], :indent => '    '), :color => false)
  update_user_or_group(type, user_or_group_name, "new_#{type}_name".to_sym => new_name)
end
update_path(type, user_or_group_name, new_path, old_path) click to toggle source
# File lib/miam/driver.rb, line 294
def update_path(type, user_or_group_name, new_path, old_path)
  log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
  log(:info, "  path:\n".green + Miam::Utils.diff(old_path, new_path, :color => @options[:color], :indent => '    '), :color => false)
  update_user_or_group(type, user_or_group_name, :new_path => new_path)
end
update_policy(type, user_or_group_name, policy_name, policy_document, old_policy_document) click to toggle source
# File lib/miam/driver.rb, line 313
def update_policy(type, user_or_group_name, policy_name, policy_document, old_policy_document)
  log(:info, "Update #{Miam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :green)
  log(:info, Miam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)
  put_policy(type, user_or_group_name, policy_name, policy_document)
end
update_role_settings(role_name, new_settings, old_settings) click to toggle source
# File lib/miam/driver.rb, line 242
def update_role_settings(role_name, new_settings, old_settings)
  log(:info, "Update Role `#{role_name}` > Settings", :color => :green)
  log(:info, Miam::Utils.diff(old_settings, new_settings, :color => @options[:color]), :color => false)
  unless_dry_run do
    @iam.update_role(new_settings.merge(role_name: role_name))
  end
end
update_user_or_group(type, user_or_group_name, params) click to toggle source
# File lib/miam/driver.rb, line 300
def update_user_or_group(type, user_or_group_name, params)
  unless_dry_run do
    params["#{type}_name".to_sym] = user_or_group_name
    @iam.send("update_#{type}", params)
  end
end

Private Instance Methods

account_id() click to toggle source
# File lib/miam/driver.rb, line 486
def account_id
  # https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
  # http://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
  @account_id ||= @sts.get_caller_identity.account
end
encode_document(policy_document) click to toggle source
# File lib/miam/driver.rb, line 463
def encode_document(policy_document)
  if @options[:disable_form_json]
    JSON.dump(policy_document)
  else
    encoded = JSON.pretty_generate(policy_document)

    if Miam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
      encoded = JSON.pretty_generate(policy_document)
      encoded = encoded.gsub(/^\s+/m, '').strip
    end

    if Miam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
      encoded = JSON.dump(policy_document)
    end

    encoded
  end
end
policy_arn(policy_name, policy_path) click to toggle source
# File lib/miam/driver.rb, line 492
def policy_arn(policy_name, policy_path)
  File.join("arn:aws:iam::#{account_id}:policy", policy_path, policy_name)
end
unless_dry_run() { || ... } click to toggle source
# File lib/miam/driver.rb, line 482
def unless_dry_run
  yield unless @options[:dry_run]
end