1

主にフォグ ライブラリを使用して、存在する ruby​​ ライブラリを使用して RDS アマゾン Web サービス パーツから予約済み DB インスタンスのリストを取得し、このデータを返そうとしました。残念ながら、このデータが返されないことに気付いたので、先に進んで調査を開始しました。

署名バージョン 4 を使用すると、このデータが返されることがわかりました。rds cli (AWS が提供するツール) を使用すると見つかりましたが、フォグ ライブラリは署名バージョン 2 を使用してリクエストを作成します。これにより、Ruby スクリプトを使用して RDS 予約インスタンスを返す簡単なソリューションの開発を開始しましたが、ドキュメントの量が少ないため、現在ここで立ち往生しています。この時点での回避策は、rds cli スクリプトを呼び出すことですが、これは悪いオプションです。

また、ケースの準備ができているソリューション(任意の言語である可能性があります)をグーグルで検索しましたが、何も見つかりませんでした。したがって、問題は、署名バージョン 4 を使用して AWS への API 呼び出しを行う、できれば ruby​​ で書かれたすぐに使えるソリューションを誰かが持っているかということです。

4

1 に答える 1

1

しばらくして、リクエストに署名するための署名バージョン4を使用して、awsの予約済みrdsインスタンスを返す必要なすべての機能を備えたクラスを構築することができました。コードは次のとおりです。

#!/usr/local/bin/ruby

require 'rubygems'
require 'net/http'
require 'net/https'
require 'time'
require 'hmac'
require 'hmac-sha2'
require 'base64'
require 'cgi'

class AWSGetSignatureV4
 def initialize(aws_key,aws_secretpwd)
  @regions=['ap-northeast-1', 'ap-southeast-1', 'eu-west-1', 'us-east-1', 'us-west-1', 'us-west-2', 'sa-east-1']
  @rds_list={}
  @inst_list={}
  @rds_reserves={}
  @inst_reserves={}
  @aws_key=aws_key
  @aws_secret=aws_secretpwd
  @canonical_uri="/\n"
  @request_type="GET\n"
  @request_version='2012-04-23'
  @request_headers={
   'Host' => ''
  }
 end

 def form_request(requestname, zone)
  canonical_request_full(requestname, zone)
  form_string_to_sign(zone)
  form_signature(requestname, zone)
  form_request_url(requestname, zone)
 end

 def get_data(requestname, zone)
  form_request(requestname, zone)
  http = Net::HTTP.new(@https_addr, "443")
  http.use_ssl = true
  headers = { 'Host' => "#{@https_addr}" }
  @request_data=""
  retval = http.get(@url_to_use, headers) do |chunk|
   @request_data+=chunk
  end
  puts(retval.code)
  puts(@request_data)
 end

 def get_service_type(requestname)
  if requestname == 'DescribeReservedDBInstances'
   @service_type="rds"
  else
   raise "No such request type."
  end
 end

 def form_time_values()
  @timenowz=Time.now.utc.iso8601
  @time_use_now=@timenowz.gsub(/-|:/, '')
  @date_to_use=@time_use_now.gsub(/T.*$/,'')
 end

 def init_param_values(requestname)
  @init_params = {
   'Action' => requestname,
   'Version' => @request_version
  }
 end

 def other_param_values(zone)
  @other_params = {
   'X-Amz-Algorithm' => 'AWS4-HMAC-SHA256',
   'X-Amz-Credential' => @aws_key+"/#{@date_to_use}/#{zone}/#{@service_type}/aws4_request",
   'X-Amz-Date' => @time_use_now,
   'X-Amz-SignedHeaders' => 'Host'
  }
 end

 def form_canonical_query_string(requestname, zone)
  @querystringz = @init_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')+"&"+@other_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')
 end

 def modify_request_headers(requestname, zone)
  @request_headers['Host']="#{@service_type}.#{zone}.amazonaws.com"
 end

 def form_headers()
  @queryheaderz = "host:#{@request_headers['Host']}"
  @signed_headerz =@request_headers.sort.collect { |key, value| key.to_s.downcase }.join(';')
  @canonical_headerz =@request_headers.sort.collect { |key, value| [CGI.escape(key.to_s.downcase), CGI.escape(value.to_s)].join(':') }.join("\n")
 end

 def form_payload_data()
  @payload=@init_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')
  @hex_sign_string=Digest::SHA256.digest("").unpack('H*').first
  if @request_type == "GET\n"
   @hex_sign_string=Digest::SHA256.digest("").unpack('H*').first
  elsif @request_type == "POST\n"
   @hex_sign_string=Digest::SHA256.digest(@payload).unpack('H*').first
  end
 end

 def canonical_request_full(requestname, zone)
  form_time_values()
  get_service_type(requestname)
  init_param_values(requestname)
  other_param_values(zone)
  modify_request_headers(requestname, zone)
  form_canonical_query_string(requestname, zone)
  form_headers()
  form_payload_data()
  @canonical_request=@request_type+@canonical_uri+@querystringz+"\n"+@canonical_headerz+"\n\n"+@signed_headerz+"\n"+@hex_sign_string
 end

 def form_string_to_sign(zone)
  hex_sign_sts=Digest::SHA256.digest(@canonical_request).unpack('H*').first
  @string_to_sign="#{@other_params['X-Amz-Algorithm']}\n#{@other_params['X-Amz-Date']}\n#{@date_to_use}/#{zone}/#{@service_type}/aws4_request\n#{hex_sign_sts}"
 end

 def form_signature(requestname, zone)
  @kdatez    = OpenSSL::HMAC.digest('sha256', "AWS4" + @aws_secret, @date_to_use)
  @kregionz  = OpenSSL::HMAC.digest('sha256', @kdatez, zone)
  @kservicez = OpenSSL::HMAC.digest('sha256', @kregionz, "#{@service_type}")
  @ksigningz = OpenSSL::HMAC.digest('sha256', @kservicez, "aws4_request")
  @signaturez = OpenSSL::HMAC.digest('sha256', @ksigningz, @string_to_sign)
  @other_params['X-Amz-Signature']=@signaturez.unpack('H*').first
 end

 def form_request_url(requestname, zone)
  @url_to_use = @init_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')+"&"+@other_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&')
  if requestname == 'DescribeReservedDBInstances'
   @url_to_use="/?"+@url_to_use
   @https_addr="#{@service_type}.#{zone}.amazonaws.com"
   @url_to_use_full="https://#{@service_type}.#{zone}.amazonaws.com/?"+@url_to_use
  end
 end

end

billing_obj=AWSGetSignatureV4.new("AWS_KEY","AWS_SECRET")
billing_obj.get_data("DescribeReservedDBInstances", 'us-east-1')
于 2012-07-18T14:23:30.240 に答える