ちょっとしたメタ情報を取るのにec2-api-toolsだと遅いし(JAVA_HOMEとかの設定も必要だし)、gemでライブラリをインストールするのもいやなので、rubyの標準ライブラリだけで簡易的なクライアントを作ってみた。*1
#!/usr/bin/env ruby require 'cgi' require 'base64' require 'net/https' require 'openssl' require 'optparse' require 'rexml/document' class EC2Client API_VERSION = '2011-12-01' SIGNATURE_VERSION = 2 def initialize(accessKeyId, secretAccessKey, endpoint = 'ec2.us-east-1.amazonaws.com', algorithm = :SHA256) @accessKeyId = accessKeyId @secretAccessKey = secretAccessKey @endpoint = endpoint @algorithm = algorithm end def query(action, params = {}) params = { :Action => action, :Version => API_VERSION, :Timestamp => Time.now.getutc.strftime('%Y-%m-%dT%H:%M:%SZ'), :SignatureVersion => SIGNATURE_VERSION, :SignatureMethod => "Hmac#{@algorithm}", :AWSAccessKeyId => @accessKeyId, }.merge(params) signature = aws_sign(params) params[:Signature] = signature Net::HTTP.version_1_2 https = Net::HTTP.new(@endpoint, 443) https.use_ssl = true https.verify_mode = OpenSSL::SSL::VERIFY_NONE https.start do |w| req = Net::HTTP::Post.new('/', 'Host' => @endpoint, '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| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&') string_to_sign = "POST\n#{@endpoint}\n/\n#{params}" digest = OpenSSL::HMAC.digest(OpenSSL::Digest.const_get(@algorithm).new, @secretAccessKey, string_to_sign) Base64.encode64(digest).gsub("\n", '') end end access_key_id = nil secret_access_key = nil endpoint = 'ec2.us-east-1.amazonaws.com' ARGV.options do |opt| opt.on('-k', '--access-key-id ACCESS_KEY') {|v| access_key_id = v } opt.on('-s', '--secret-access-key SECRET_ACCESS_KEY') {|v| secret_access_key = v } opt.on('-r', '--region REGION') {|v| endpoint = v } opt.parse! unless access_key_id and secret_access_key puts opt.help exit 1 end end unless /\Aec2\.[^.]+\.amazonaws\.com\Z/ =~ endpoint endpoint = "ec2.#{endpoint}.amazonaws.com" end ec2cli = EC2Client.new(access_key_id, secret_access_key, endpoint) source = ec2cli.query('DescribeInstances') # puts source doc = REXML::Document.new(source) # docをごにょごにょ
ec2-api-toolsよりも速いのがよい。
*1:OpenSSLは標準ライブラリでいいのかな…