#!/usr/bin/env ruby
require 'cgi'
require 'base64'
require 'net/https'
require 'openssl'
require 'time'
require 'rexml/document'
class IAMClient
API_VERSION = '2010-05-08'
HOST = 'iam.amazonaws.com'
ALGORITHM = :SHA1
def initialize(accessKeyId, secretAccessKey)
@accessKeyId = accessKeyId
@secretAccessKey = secretAccessKey
end
def query(action, params = {})
params = {
:Action => action,
:Version => API_VERSION,
:Timestamp => Time.now.getutc.strftime('%Y-%m-%dT%H:%M:%SZ'),
:SignatureVersion => 2,
:SignatureMethod => "Hmac#{ALGORITHM}",
:AWSAccessKeyId => @accessKeyId,
}.merge(params)
signature = aws_sign(params)
params[:Signature] = signature
Net::HTTP.version_1_2
https = Net::HTTP.new(HOST, 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
https.start do |w|
req = Net::HTTP::Post.new('/',
'Host' => HOST,
'Content-Type' => 'application/x-www-form-urlencoded'
)
req.set_form_data(params)
res = w.request(req)
res.body
end
end
private
def aws_sign(params)
params = params.sort_by {|a, b| a.to_s }.map {|k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')
string_to_sign = "POST\n#{HOST}\n/\n#{params}"
digest = OpenSSL::HMAC.digest(OpenSSL::Digest.const_get(ALGORITHM).new, @secretAccessKey, string_to_sign)
Base64.encode64(digest).gsub("\n", '')
end
end
AWSAccessKeyId = '...'
AWSSecretAccessKey = '...'
iamcli = IAMClient.new(AWSAccessKeyId, AWSSecretAccessKey)
source = iamcli.query('ListUsers', 'MaxItems' => 512)
doc = REXML::Document.new(source)
doc.each_element('/ListUsersResponse/ListUsersResult/Users/member') do |element|
user_id, path, user_name, arn, create_date = %w(
UserId
Path
UserName
Arn
CreateDate
).map {|i| element.get_text(i).to_s }
groups = []
REXML::Document.new(iamcli.query('ListGroupsForUser', 'UserName' => user_name, 'MaxItems' => 512)).each_element('//GroupName') do |element|
groups << element.text.to_s
end
access_keys = []
REXML::Document.new(iamcli.query('ListAccessKeys', 'UserName' => user_name, 'MaxItems' => 512)).each_element('/ListAccessKeysResponse/ListAccessKeysResult/AccessKeyMetadata/member') do |element|
access_key_id = element.get_text('AccessKeyId').to_s
status = element.get_text('Status').to_s
access_keys << "#{access_key_id} (#{status})"
end
puts [user_name, path, create_date, groups.join(','), access_keys.join(',')].join("\t")
end