Reputation: 414
I tried whole day for this, but I couldn't...
A. I made a model for creating signed cookie. I got help from : spacevatican.org
def cookie_data(resource, expiry)
raw_policy = policy(resource, expiry)
{
'CloudFront-Expires' => expiry.utc.to_i,
'CloudFront-Signature' => sign(raw_policy),
'CloudFront-Key-Pair-Id' => ENV['CLOUDFRONT_KEY_PAIR_ID']
}
end
private
def policy(url, expiry)
{
"Statement"=> [
{
"Resource" => url,
"Condition"=>{
"DateLessThan" =>{"AWS:EpochTime"=> expiry.utc.to_i}
}
}
]
}.to_json.gsub(/\s+/,'')
end
def safe_base64(data)
Base64.strict_encode64(data).tr('+=/', '-_~')
end
def sign(data)
digest = OpenSSL::Digest::SHA1.new
key = OpenSSL::PKey::RSA.new ENV['CLOUDFRONT_PRIVATE_KEY']
result = key.sign digest, data
safe_base64(result)
end
B. Call cookie_data with 'resource' and 'expiry'. I got help from randalv for proper resource.
base_domain = '.myapp.com' # sample name
cookie_domain: '.myapp.com'
cookie_data("http://#{URI.parse(base_domain).host}/*", 1.hour.from_now).each do |name, value|
cookies[name] = { value: value, domain: cookie_domain }
end
C. From A & B, Three validation of Cloudfront are passed - 1. Three cookies existing validation, and 2. Expiry existing validation, 3. Decoding avalible validation. I know these three validation because of error message on invalid request. But after all, I am always faved with same message - Access Denied.
There are some suspects.
My CNAME of Cloudfront is 'img.myapp.com'
(sample), But My testing domain is 'http://dev.myapp.com/#/home'
, and this is my local developing server(I changed localhost name).
So I tried with many combinations of (base_domain, cookie_domain) : (img.myapp.com, .myapp.com), (.myapp.com, .myapp.com), (dev.myapp.com, .myapp.com).
But All Denied.
My Cloudfront & S3 Settings are same with those on randalv. But I mind two things. 'Restrict Bucket Access' is 'NO' on origin settings of cloudfront. And I do not create CORS configuration on S3.
Upvotes: 4
Views: 2238
Reputation: 414
I solved myself. I had three defects, and now it works well after correcting them.
First, I changed expires to policy.
'CloudFront-Expires' => expiry.utc.to_i,
to
'CloudFront-Policy' => safe_base64(raw_policy),
Actually, I had used policy(custom) instead of expires(canned). During my trying, I had changed. But I don't know why expires version doesn't work.
Second, My base_domain is 'img.myapp.com' and cookie_domain is '.myapp.com'.
Third, Do not input bucket name on your final url. Very trivial mistake, but important.
Upvotes: 4