通过执行API调用从aws获取保留DB RDS实例的列表



我试图使用现有的ruby库从RDS amazon web services部分获取保留DB实例的列表,并返回这些数据,主要是使用雾库。但我注意到,不幸的是,他们没有返回这些数据,因此我继续进行调查。

我发现,当使用签名版本4时,会返回此数据,当使用rds cli(AWS提供的工具)时会发现此数据,而雾库则使用签名版本2进行请求。这让我开始开发一个简单的解决方案,该解决方案将使用ruby脚本返回RDS保留实例,但由于文档数量很少,我目前被困在这里。此时,解决方法是调用rds-cli脚本,但这是一个糟糕的选项。

还花了一些时间在谷歌上搜索该案件的现成解决方案(可以是任何语言),但找不到任何解决方案。因此,问题是,是否有人有一个最好用ruby编写的现成解决方案,使用签名版本4对AWS进行API调用?

过了一段时间,我们成功地构建了一个具有所有所需功能的类,该类将使用签名版本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="GETn"
  @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 == "GETn"
   @hex_sign_string=Digest::SHA256.digest("").unpack('H*').first
  elsif @request_type == "POSTn"
   @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+"nn"+@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_requestn#{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')

最新更新