Skip to content

Commit

Permalink
Merge pull request #160 from phulien/master
Browse files Browse the repository at this point in the history
Support generate presigned URL with tagging
  • Loading branch information
onno-vos-dev authored Jan 20, 2025
2 parents d16d091 + 5140aae commit 99948f7
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 11 deletions.
2 changes: 1 addition & 1 deletion rebar.config
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{erl_opts, [nowarn_unused_type, debug_info, {d, maps_support}]}.
{deps, [{hackney, "1.18.0"},
{jsx, "3.0.0"},
{aws_signature, "0.3.1"}
{aws_signature, "0.3.3"}
]}.
{project_plugins, [rebar3_hex, rebar3_ex_doc, rebar3_check_app_calls]}.
{hex, [{doc, #{provider => ex_doc}}]}.
Expand Down
6 changes: 3 additions & 3 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"1.2.0",
[{<<"aws_signature">>,{pkg,<<"aws_signature">>,<<"0.3.1">>},0},
[{<<"aws_signature">>,{pkg,<<"aws_signature">>,<<"0.3.3">>},0},
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.5.2">>},1},
{<<"hackney">>,{pkg,<<"hackney">>,<<"1.16.0">>},0},
{<<"idna">>,{pkg,<<"idna">>,<<"6.0.1">>},1},
Expand All @@ -11,7 +11,7 @@
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.5.0">>},2}]}.
[
{pkg_hash,[
{<<"aws_signature">>, <<"67F369094CBD55FFA2BBD8CC713EDE14B195FCFB45C86665CD7C5AD010276148">>},
{<<"aws_signature">>, <<"5844BEE0D3CC42EEFD21D236BBFAA8AA9B16E2F2B7EE79EDAECB321DB3FB6ADF">>},
{<<"certifi">>, <<"B7CFEAE9D2ED395695DD8201C57A2D019C0C43ECAF8B8BCB9320B40D6662F340">>},
{<<"hackney">>, <<"5096AC8E823E3A441477B2D187E30DD3FFF1A82991A806B2003845CE72CE2D84">>},
{<<"idna">>, <<"1D038FB2E7668CE41FBF681D2C45902E52B3CB9E9C77B55334353B222C2EE50C">>},
Expand All @@ -22,7 +22,7 @@
{<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>},
{<<"unicode_util_compat">>, <<"8516502659002CEC19E244EBD90D312183064BE95025A319A6C7E89F4BCCD65B">>}]},
{pkg_hash_ext,[
{<<"aws_signature">>, <<"50FC4DC1D1F7C2D0A8C63F455B3C66ECD74C1CF4C915C768A636F9227704A674">>},
{<<"aws_signature">>, <<"87E8F42B8E49002AA8D0350A71D13D69EA91B9AFB4CA9B526AE36DB1D585C924">>},
{<<"certifi">>, <<"3B3B5F36493004AC3455966991EAF6E768CE9884693D9968055AEEEB1E575040">>},
{<<"hackney">>, <<"3BF0BEBBD5D3092A3543B783BF065165FA5D3AD4B899B836810E513064134E18">>},
{<<"idna">>, <<"A02C8A1C4FD601215BB0B0324C8A6986749F807CE35F25449EC9E69758708122">>},
Expand Down
50 changes: 43 additions & 7 deletions src/aws_s3_presigned_url.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
-module(aws_s3_presigned_url).

-export([ make_presigned_v4_url/5,
make_presigned_v4_url/6
make_presigned_v4_url/6,
make_presigned_v4_url/7
]).

-include_lib("hackney/include/hackney_lib.hrl").
Expand All @@ -23,6 +24,11 @@ make_presigned_v4_url(Client0, Method, ExpireSeconds, Bucket, Key) ->

-spec make_presigned_v4_url(map(), get | put, integer(), binary(), binary(),path|virtual_host) -> {ok, binary()}.
make_presigned_v4_url(Client0, Method, ExpireSeconds, Bucket, Key, Style) ->
make_presigned_v4_url(Client0, Method, ExpireSeconds, Bucket, Key, Style, undefined).

-spec make_presigned_v4_url(map(), get | put, integer(), binary(), binary(), path|virtual_host, undefined|binary()) ->
{ok, binary()}.
make_presigned_v4_url(Client0, Method, ExpireSeconds, Bucket, Key, Style, Tags) ->
MethodBin = aws_request:method_to_binary(Method),
Path = build_path(Client0,Bucket,Key,Style),
Client = Client0#{service => <<"s3">>},
Expand All @@ -38,12 +44,20 @@ make_presigned_v4_url(Client0, Method, ExpireSeconds, Bucket, Key, Style) ->
, {body_digest, <<"UNSIGNED-PAYLOAD">>}
, {uri_encode_path, false} %% We already encode in build_path/4
],
Options = case SecurityToken of
undefined ->
Options0;
_ ->
[{session_token, hackney_url:urlencode(SecurityToken)} | Options0]
end,
Options1 =
case SecurityToken of
undefined ->
Options0;
_ ->
[{session_token, hackney_url:urlencode(SecurityToken)} | Options0]
end,
Options =
case Tags of
undefined ->
Options1;
_ ->
[{tags, Tags} | Options1]
end,
{ok, aws_signature:sign_v4_query_params(AccessKeyID, SecretAccessKey, Region, Service, Now, MethodBin, URL, Options)}.

%%====================================================================
Expand Down Expand Up @@ -197,4 +211,26 @@ presigned_url_virtual_host_style_test() ->
?assertEqual(<<"3600">>, proplists:get_value(<<"X-Amz-Expires">>, ParsedQs)),
?assertEqual(<<"Token">>, proplists:get_value(<<"X-Amz-Security-Token">>, ParsedQs)),
?assertEqual(<<"host">>, proplists:get_value(<<"X-Amz-SignedHeaders">>, ParsedQs)).

presigned_url_tags_test() ->
Client = aws_client:make_temporary_client(<<"AccessKeyID">>, <<"SecretAccessKey">>,
<<"Token">>, <<"eu-west-1">>),
{ok, Url} = aws_s3_presigned_url:make_presigned_v4_url(Client, put, 3600, <<"bucket">>, <<"key">>, path, <<"key1=value1&key2=value2">>),
HackneyUrl = hackney_url:parse_url(Url),
ParsedQs = hackney_url:parse_qs(HackneyUrl#hackney_url.qs),
Credential = proplists:get_value(<<"X-Amz-Credential">>, ParsedQs),
[AccessKeyId, _ShortDate, Region, Service, Request] = binary:split(Credential, <<"/">>, [global]),
?assertEqual(https, HackneyUrl#hackney_url.scheme),
?assertEqual(443, HackneyUrl#hackney_url.port),
?assertEqual("s3.eu-west-1.amazonaws.com", HackneyUrl#hackney_url.host),
?assertEqual(<<"/bucket/key">>, HackneyUrl#hackney_url.path),
?assertEqual(7, length(ParsedQs)),
?assertEqual(<<"AccessKeyID">>, AccessKeyId),
?assertEqual(<<"eu-west-1">>, Region),
?assertEqual(<<"s3">>, Service),
?assertEqual(<<"aws4_request">>, Request),
?assertEqual(<<"AWS4-HMAC-SHA256">>, proplists:get_value(<<"X-Amz-Algorithm">>, ParsedQs)),
?assertEqual(<<"3600">>, proplists:get_value(<<"X-Amz-Expires">>, ParsedQs)),
?assertEqual(<<"Token">>, proplists:get_value(<<"X-Amz-Security-Token">>, ParsedQs)),
?assertEqual(<<"host;x-amz-tagging">>, proplists:get_value(<<"X-Amz-SignedHeaders">>, ParsedQs)).
-endif.

0 comments on commit 99948f7

Please sign in to comment.