2012-07-17 54 views
1

我試圖從RDS amazon web服務部件中使用存在的ruby庫獲取預留數據庫實例列表並返回此數據,主要是使用霧圖書館。我注意到他們不會很遺憾地返回這些數據,因此我繼續前進並開始調查。通過API調用從aws獲取保留的DB RDS實例列表

我發現當使用簽名版本4時,這個數據被返回,當使用rds cli(AWS提供的工具)時發現它,而霧庫使用簽名版本2發出請求。這導致我開始開發一個簡單的解決方案,它將使用ruby腳本返回RDS保留實例,但由於我目前卡在這裏的文檔量很少。此時,解決方法是調用rds cli腳本,但這是一個糟糕的選擇。

也花了一些時間搜索一個現成的解決方案(可以用任何語言)的案件,但無法找到任何。問題是,有沒有人有最好的書面解決方案,使用簽名版本4來進行AWS的API調用?

回答

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 
    @[email protected](/-|:/, '') 
    @[email protected]_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('&')+"&"[email protected]_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 [email protected]_headers.sort.collect { |key, value| key.to_s.downcase }.join(';') 
    @canonical_headerz [email protected]_headers.sort.collect { |key, value| [CGI.escape(key.to_s.downcase), CGI.escape(value.to_s)].join(':') }.join("\n") 
end 

def form_payload_data() 
    @[email protected]_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() 
    @[email protected][email protected][email protected]+"\n"[email protected]_headerz+"\n\n"[email protected]_headerz+"\n"[email protected]_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'][email protected]('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('&')+"&"[email protected]_params.sort.collect { |key, value| [CGI.escape(key.to_s), CGI.escape(value.to_s)].join('=') }.join('&') 
    if requestname == 'DescribeReservedDBInstances' 
    @url_to_use="/?"[email protected]_to_use 
    @https_addr="#{@service_type}.#{zone}.amazonaws.com" 
    @url_to_use_full="https://#{@service_type}.#{zone}.amazonaws.com/?"[email protected]_to_use 
    end 
end 

end 

billing_obj=AWSGetSignatureV4.new("AWS_KEY","AWS_SECRET") 
billing_obj.get_data("DescribeReservedDBInstances", 'us-east-1') 
相關問題