DannyB DannyB - 1 month ago 20
Ruby Question

Accessing Ivona Speech Cloud with Ruby

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)

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


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

#<HTTP::Response/1.1 403 Forbidden
"Date"=>"Mon, 29 Aug 2016 08:32:18 GMT"}>

Any assistance is appreciated


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, json: body_params)