class Himeko::RoleManager

Attributes

iam[R]
path[R]
prefix[R]
table[R]
ttl[R]

Public Class Methods

new(iam:, prefix:, path:, ttl: 86400, dynamodb_table:) click to toggle source
# File lib/himeko/role_manager.rb, line 6
def initialize(iam:, prefix:, path:, ttl: 86400, dynamodb_table:)
  @iam = iam
  @prefix = prefix
  @path = path
  @table = dynamodb_table
  @ttl = ttl
end

Public Instance Methods

create(username) click to toggle source
# File lib/himeko/role_manager.rb, line 68
def create(username)
  role_arn = UserMimickingRole.new(iam, username, role_name_for_username(username), path).create

  table.update_item(
    key: {
      'username' => username,
    },
    update_expression: 'SET expires_at = :expires_at, role_arn = :role_arn',
    expression_attribute_values: {
      ':expires_at' => (Time.now + ttl).to_i,
      ':role_arn' => role_arn,
    },
  )
  
  role_arn
end
fetch(username, recreate: false) click to toggle source
# File lib/himeko/role_manager.rb, line 16
def fetch(username, recreate: false)
  item = table.query(
    limit: 1,
    select: 'ALL_ATTRIBUTES',
    key_condition_expression: 'username = :username',
    expression_attribute_values: {":username" => username},
  ).items.first

  if recreate || item.nil?
    begin
      return create(username)
    rescue Aws::IAM::Errors::EntityAlreadyExists
      remove(username, delete_record: false)
      retry
    end
  end

  table.update_item(
    key: {
      'username' => username,
    },
    update_expression: 'SET expires_at = :expires_at',
    expression_attribute_values: {
      ':expires_at' => (Time.now + ttl).to_i,
    },
  )

  item.fetch('role_arn')
end
prune() click to toggle source
# File lib/himeko/role_manager.rb, line 85
def prune
  table.client.scan(
    table_name: table.table_name,
    select: 'ALL_ATTRIBUTES',
    filter_expression: 'expires_at < :now',
    expression_attribute_values: {
      ':now' => Time.now.to_i,
    },
  ).each do |page|
    page.items.each do |item|
      puts "==> #{item['username']} (#{item['role_arn']})"
      remove(item['username'], role_name: item['role_arn'].split(?/)[-1])
      table.delete_item(key: {'username' => item['username']})
    end
  end
end
remove(username, role_name: nil, delete_record: true) click to toggle source
# File lib/himeko/role_manager.rb, line 46
def remove(username, role_name: nil, delete_record: true)
  role_name ||= role_name_for_username(username)

  iam.list_attached_role_policies(role_name: role_name).each.flat_map(&:attached_policies).map(&:policy_arn).each do |policy_arn|
    iam.detach_role_policy(role_name: role_name, policy_arn: policy_arn)
  end
  iam.list_role_policies(role_name: role_name).policy_names.each do |policy_name|
    iam.delete_role_policy(role_name: role_name, policy_name: policy_name)
  end
  iam.delete_role(role_name: role_name)

  if delete_record
    table.delete_item(
      key: {
        'username' => username,
      },
    )
  end
rescue Aws::IAM::Errors::NoSuchEntity
  # do nothing
end
role_name_for_username(username) click to toggle source
# File lib/himeko/role_manager.rb, line 102
def role_name_for_username(username)
  "#{prefix}#{username}"
end