R53Client

ここを参考にして、簡単なRoute 53のRubyクライアントを作ってみた。

#!/usr/bin/env ruby
require 'cgi'
require 'base64'
require 'net/https'
require 'openssl'
require 'time'

$stdout.sync = true

class R53Client
  HOST = 'route53.amazonaws.com'
  API_VERSION = '2010-10-01'
  ALGORITHM = :SHA1
  #ALGORITHM = :SHA256

  def initialize(accessKeyId, secretAccessKey)
    @accessKeyId = accessKeyId
    @secretAccessKey = secretAccessKey
  end

  # Actions on Hosted Zones
  def create_hosted_zone(xml)
    path = "/#{API_VERSION}/hostedzone"
    req = Net::HTTP::Post.new(path)
    req['Content-Length'] = xml.length
    req['Content-Type'] = 'text/xml'
    req.body = xml
    query(req)
  end

  def get_hosted_zone(hosted_zone_id)
    path = "/#{API_VERSION}/hostedzone/#{hosted_zone_id}"
    req = Net::HTTP::Get.new(path)
    query(req)
  end

  def delete_hosted_zone(hosted_zone_id)
    path = "/#{API_VERSION}/hostedzone/#{hosted_zone_id}"
    req = Net::HTTP::Delete.new(path)
    query(req)
  end

  def list_hosted_zones(params = {})
    path = "/#{API_VERSION}/hostedzone"
    qs = query_string(params)
    path.concat('?' + qs) if qs

    req = Net::HTTP::Get.new(path)
    query(req)
  end

  # Actions on Resource Records Sets
  def change_resource_record_sets(hosted_zone_id, xml)
    path = "/#{API_VERSION}/hostedzone/#{hosted_zone_id}/rrset"
    req = Net::HTTP::Post.new(path)
    req['Content-Length'] = xml.length
    req['Content-Type'] = 'text/xml'
    req.body = xml

    query(req)
  end

  def list_resource_record_sets(hosted_zone_id, params = {})
    path = "/#{API_VERSION}/hostedzone/#{hosted_zone_id}/rrset"
    qs = query_string(params)
    path.concat('?' + qs) if qs

    req = Net::HTTP::Get.new(path)
    query(req)
  end

  def get_change(change_id)
    path = "/#{API_VERSION}/change/#{change_id}"
    req = Net::HTTP::Get.new(path)
    query(req)
  end

  private
  def query(req)
    date = Time.now.getutc.rfc2822
    req['X-Amzn-Authorization'] = x_amzn_authorization(date)
    req['Host'] = HOST
    req['x-amz-date'] = date

    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|
      res = w.request(req)
      res.body
    end
  end

  def x_amzn_authorization(date)
    digest = OpenSSL::HMAC.digest(OpenSSL::Digest.const_get(ALGORITHM).new, @secretAccessKey, date)
    sign = Base64.encode64(digest).gsub("\n", '')
    "AWS3-HTTPS AWSAccessKeyId=#{@accessKeyId},Algorithm=Hmac#{ALGORITHM},Signature=#{sign}"
  end

  def query_string(params)
    return nil if params.empty?
    params.map {|k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
  end
end

AWSAccessKeyId = '<YourAWSAccessKeyId>'
AWSSecretAccessKey = '<YourAWSSecretAccessKey>'

r53cli = R53Client.new(AWSAccessKeyId, AWSSecretAccessKey)
puts r53cli.list_hosted_zones