我正在 docker 容器内的 ruby on rails 应用程序中设置一个 Web 客户端,我希望它使用 Amazon Personalize SDK。该文档是为 Python 和 AWS CLI 编写的。我正在使用 Net::HTTP 库用 ruby 编写一个示例请求并遇到了问题。
目前我的请求返回 403 和 <InvalidSignatureException>
<Message>Credential should be scoped to correct service: 'personalize'. </Message>
错误。我认为我的问题是我没有使用正确的host
但是,当我捆绑aws-sdk
宝石时,我看到许多aws-sdk
宝石被捆绑在一起,看起来像aws-sdk-#{name_of_aws_service}
,但没有aws-sdk-personalize
。所以我的问题是,这是为什么?我试图用 Ruby 做这件事是不是吠错了树?我需要学习Python吗?
host = # removed because SO
service = 'es'
region = '' #removed because SO
signer = Aws::Sigv4::Signer.new(
service: service,
region: region,
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
)
document = {
# removed because SO
}
signature = signer.sign_request(
http_method: 'PUT',
url: host,
body: document.to_json
)
uri = URI(host)
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
request = Net::HTTP::Put.new uri
request.body = document.to_json
request['Host'] = signature.headers['host']
request['X-Amz-Date'] = signature.headers['x-amz-date']
request['X-Amz-Security-Token'] = signature.headers['x-amz-security-token']
request['X-Amz-Content-Sha256']= signature.headers['x-amz-content-sha256']
request['Authorization'] = signature.headers['authorization']
request['Content-Type'] = 'application/json'
response = http.request request
puts response.code
puts response.body
end
我仔细阅读文档得到的答案是否定的。无论如何,AWS Personalize 都不适用于常规版本。所以我要把它标记为已解决并继续前进。
另一种解决方案是使用此 gem,假设您有密钥 ID、密钥和会话令牌
https://github.com/winebarrel/faraday_middleware-aws-sigv4
conn = Faraday.new(url: API_BASE_URL) do |faraday|
faraday.request :aws_signers_v4,
credentials: Aws::Credentials.new(response["access_key_id"], response["secret_key"], response["session_token"]),
service_name: 'execute-api',
region: 'us-east-1'
faraday.adapter Faraday.default_adapter
end
puts conn.headers
response = conn.post('/orders') do |req|
req.headers['Content-Type'] = 'application/json'
end
puts response.body