0

I am trying to access Ivona Speech Cloud using Ruby.

I have ported one of the code examples I found to Ruby, but I probably did something wrong at authenticating the request, since I am getting an error.

This is my implementation:

require 'http' # the gem
require 'openssl'
require 'pp'

def sign key, date, region, service, text
  k_date    = OpenSSL::HMAC.digest('sha256', "AWS4" + key, date)
  k_region  = OpenSSL::HMAC.digest('sha256', k_date, region)
  k_service = OpenSSL::HMAC.digest('sha256', k_region, service)
  k_signing = OpenSSL::HMAC.digest('sha256', k_service, "aws4_request")
  signature = OpenSSL::HMAC.digest('sha256', k_signing, text)
  signature
end

def run
  access_key = "GDxxxxxxxxxxxxxxxxRA"
  secret_key = "QtxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlE"

  region    = 'eu-west-1'
  date      = '20160808'
  service   = 'tts'
  body      = {"Input" => {"Data" => "Hello world"}}
  endpoint  = "https://#{service}.#{region}.ivonacloud.com/CreateSpeech"
  signature = sign secret_key, date, region, service, 'Hello World'

  headers = {
    "Content-Type" =>"application/json",
    "Authorization" => "AWS4-HMAC-SHA256",
    "Credential" => "#{access_key}/#{date}/#{region}/#{service}/aws4_request",
    "SignedHeaders" => "content-type;host;x-amz-content-sha256;x-amz-date",
    "Signature" => "#{signature}",
  }

  res = HTTP.headers(headers).post(endpoint, json: body)
  p res
end

run

This is the error I am getting (line broken for legibility):

#<HTTP::Response/1.1 403 Forbidden 
 {"X-Amzn-Requestid"=>"18a44dd8-6dc3-11e6-808f-975692d1ee55", 
  "X-Amzn-Errortype"=>"IncompleteSignatureException:http://internal.amazon.com/coral/com.amazon.coral.service/", 
  "Content-Type"=>"application/json", 
  "Content-Length"=>"293", 
  "Date"=>"Mon, 29 Aug 2016 08:32:18 GMT"}>

Any assistance is appreciated

DannyB
  • 12,810
  • 5
  • 55
  • 65

1 Answers1

1

I would suggest using the AWS4 gem to help with this. I've made similar calls using the following format:

signer = ::AWS4::Signer.new(
  access_key: "YOUR_ACCESS_KEY",
  secret_key: "YOUR_SECRET_KEY",
  region: "us-east-1"
)

aws_headers = {
  "Content-Type" => "application/json; charset=utf8",
  "Date" => Time.now.iso8601.to_s,
  "Host" => "tts.us-east-1.ivonacloud.com"
}

uri = URI(endpoint)
body_params = {"Input":{"Data":"Hello world"}}.to_json

headers = signer.sign("POST", uri, aws_headers, body_params)
res = HTTP.headers(headers).post(endpoint, body: body_params)
nykon333
  • 702
  • 4
  • 5
  • I will try, thank you. The gem seems unmaintained, but I will give it a shot. – DannyB Aug 31 '16 at 06:26
  • Cant make this work either. Added `endpoint = "https://tts.us-east-1.ivonacloud.com/CreateSpeech"` to it, and getting 403 forbidden as the response. – DannyB Aug 31 '16 at 08:12
  • Success! Just needs to add endpoint (as in my previous comment) and change the request to `res = HTTP.headers(headers).post(endpoint, body: body_params)` - with `body` instead of `json`. – DannyB Aug 31 '16 at 08:21
  • I've updated my example to use body instead of json for the key. Thanks for catching that. – nykon333 Aug 31 '16 at 13:44