Presigning S3 get object URI
ceolinrenato opened this issue · 5 comments
Hey I was trying to use the lib to return a presigned url to access a file from inside a S3 bucket.
I was able to accomplish the task by following this docs https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html#query-string-auth-v4-signing-example
However I couldn't use AWS.Signature.sign_v4_query/6
because it always tries to hash to payload and for requests without a payload or when you don't know which payload will be used you have to include UNSIGNED_PAYLOAD
in the canonical URL instead.
Here's how I did it https://gist.github.com/ceolinrenato/cc7f036ef7867c4ccd08ddfd932d1520
I think a very simple fix like #88 could made the AWS.Signature.sign_v4_query/6
work for this use case
We could also update test/aws/signature_test.exs
sign_v4_query/6 test, since it seems to be target to the same use case. We need to add data to the query string instead of headers
Working example of how to get presigned url to download a s3 object (using the changes in the PR)
def signed_uri(reference, ttl) do
%{
remote_storage_bucket: remote_storage_bucket,
access_key_id: access_key_id,
remote_storage_region: remote_storage_region
} = aws_config()
uri =
URI.parse(
"https://#{remote_storage_bucket}.s3.#{remote_storage_region}.#{aws_client().endpoint}/#{AWS.Util.encode_uri(reference, true)}"
)
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
long_date = NaiveDateTime.to_iso8601(now, :basic) <> "Z"
short_date = Date.to_iso8601(now, :basic)
query_params = [
{"X-Amz-Expires", Integer.to_string(ttl)},
{"X-Amz-Algorithm", "AWS4-HMAC-SHA256"},
{"X-Amz-Credential",
"#{access_key_id}/#{short_date}/#{remote_storage_region}/s3/aws4_request"},
{"X-Amz-SignedHeaders", "host"},
{"X-Amz-Date", long_date}
]
url = URI.to_string(%{uri | query: URI.encode_query(query_params)})
signature_tuple =
%{aws_client() | service: "s3"}
|> AWS.Signature.sign_v4_query(now, :get, url, [{"Host", uri.host}], nil)
|> Enum.find(fn {key, _value} -> key == "X-Amz-Signature" end)
URI.to_string(%{
uri
| query: URI.encode_query([signature_tuple | query_params])
})
end
Hi @ceolinrenato 👋
Thank you for opening the issue and the PR. Unfortunately we just removed the signature part from this library. The idea is to keep signature features in https://github.com/aws-beam/aws_signature and share that lib with the generated packages (aws-elixir and aws-erlang).
I think we can support this feature in that lib too.
I'm closing the issue and the PR, but I have opened a new issue there: aws-beam/aws_signature#4
Thanks again!
Thanks for maintaining this lib @philss, Wish I knew some erlang to help on the aws-beam/aws_signature side