2012-07-17 1 views
1

현재 루비 라이브러리를 사용하는 RDS 아마존 웹 서비스 파트에서 예약 DB 인스턴스 목록을 얻으려고했는데 주로 안개가있는이 데이터를 반환했습니다. 도서관. 나는 그들이 불행하게도이 데이터를 반환하지 않는다는 것을 알아 차렸으므로 나는 앞서 가서 조사를 시작했다.API 호출을 통해 aws에서 예약 된 DB RDS 인스턴스 목록 가져 오기

시그니처 버전 4를 사용할 때이 데이터가 반환되고 rds cli (AWS에서 제공하는 도구)를 사용할 때 찾았으며 안개 라이브러리는 서명 요청 버전 2를 사용한다는 것을 알았습니다. 이 때문에 루비 스크립트를 사용하여 RDS 예약 인스턴스를 반환하는 간단한 솔루션을 개발할 수있게되었지만 적은 양의 문서로 인해 현재 여기에 갇혀 있습니다. 이 시점에서 해결 방법은 rds cli 스크립트를 호출하는 것이지만 잘못된 옵션입니다.

또한이 솔루션에 대한 검색 결과를 보냈지 만 (모든 언어로 표시 될 수 있음) 아무 것도 찾을 수 없었습니다. 질문은 따라서 누군가가 AWS API 호출을 만들기 위해 서명 버전 4를 사용하는 루비에서 작성된 준비된 솔루션을 선호합니까?

답변

1

얼마 후 요청 서명에 서명 버전 4를 사용하여 예약 된 rds 인스턴스를 aws에 반환하는 데 필요한 모든 기능을 갖춘 클래스를 만들었습니다. 다음은 코드입니다.

#!/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')