Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support generate presigned URL with tagging #29

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

phulien
Copy link

@phulien phulien commented Dec 31, 2024

No description provided.

@onno-vos-dev
Copy link
Member

onno-vos-dev commented Jan 3, 2025

Thank you @phulien for your contribution! I tried adding a test and it immediately fails with below error:

1) aws_signature:sign_v4_query_params_with_tags_test/0
     Failure/Error: {error,undef,
                        [{hackney_url,urlencode,[<<"host;x-amz-tagging">>],[]},
                         {aws_signature,sign_v4_query_params,8,
                             [{file,
                                  "/Users/onno.vos/src/github/aws_signature/src/aws_signature.erl"},
                              {line,272}]},
                         {aws_signature,sign_v4_query_params_with_tags_test,
                             0,
                             [{file,
                                  "/Users/onno.vos/src/github/aws_signature/src/aws_signature.erl"},
                              {line,1098}]},
                         {aws_signature,sign_v4_query_params_with_tags_test,
                             0,[]}]}

You're relying on hackney_url to encode the query params here while hackney is not available as part of this package. Either we need to include hackney as part of this repo or bring the urlencode in here as a hardcopy.

Considering that aws-elixir has hackney as an optional dependency, I'd like to avoid bringing it in here as a dependency. Since that would force it to become part of aws-elixir (IIRC, I may be wrong and the optional:true would still allow an override on that but I'd need to verify that before chosing a way forward. I know the Elixir folks prefer finch over hackney typically speaking.

Perhaps we can use the uri_string module instead? 👍

if Tag == undefined ->
<<"host">>;
Tag =/= undefined ->
hackney_url:urlencode(<<"host;x-amz-tagging">>)
Copy link
Member

@onno-vos-dev onno-vos-dev Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this works? I'd expect something like below instead:

BaseParams0 =
        [{<<"X-Amz-Algorithm">>, <<"AWS4-HMAC-SHA256">>},
         {<<"X-Amz-SignedHeaders">>, <<"host">>}],
BaseParams = maybe_add_tag_header(BaseParams0, Tags),

With the maybe_add_tag_header/2 being defined as something like below (leaving aside the hackney_url problem highlighted in a previous comment) but I'd expect the header to be a part of this?

maybe_add_tag_header(Headers, undefined) ->
    Headers;  
maybe_add_tag_header(Headers, [{_K, _V} | _] = Tags) ->
    [<<"X-Amz-Tagging">>, hackney_url:qs(Tags)} | Headers].

(Notice also the usage of Tags since it can be a list of tags :-) )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wouldn't be enough since we need to add X-Amz-Tagging to X-Amz-SignedHeaders as defined here: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right; it should be a list of tags.

Comment on lines 358 to 361
maybe_add_tag_query_param(QueryParams, undefined) ->
QueryParams;
maybe_add_tag_query_param(QueryParams, Tag) ->
[{<<"X-Amz-Tagging">>, Tag} | QueryParams].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From quick search online, it seems to me that x-amz-tagging always needs to be send in the headers, so there is no reason to put it in the params.

See https://stackoverflow.com/a/77418874.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if people want to generate a pre-signed URL with tagging, then x-amz-tagging needs to be included. However, we need to support both scenarios, with and without tagging.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that there is no reason to add x-amz-tagging as query param. It's either sent as header or not. I may totally be missing something though :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand what you mean now, and you are correct. It should not be needed.

if Tag == undefined ->
[HostHeader];
Tag =/= undefined ->
[HostHeader, {<<"X-Amz-Tagging">>, hackney_url:urldecode(Tag)}]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should accept an unescaped value instead, the same that the caller would use for the header.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, that's because we put it in the query params. My point is that we should not add tag to the query params, and only add it to headers for signing. So given that, the value should match the actual header value.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That actually makes a lot of sense. Thanks.

if Tag == undefined ->
<<"host">>;
Tag =/= undefined ->
hackney_url:urlencode(<<"host;x-amz-tagging">>)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we can encode by hand to avoid depending on hackney:

Suggested change
hackney_url:urlencode(<<"host;x-amz-tagging">>)
<<"host%3x-amz-tagging">>

@onno-vos-dev
Copy link
Member

onno-vos-dev commented Jan 3, 2025

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?

If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

@phulien
Copy link
Author

phulien commented Jan 3, 2025

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?

If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

I got this error when trying this branch

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>There were headers present in the request which were not signed</Message>
  <HeadersNotSigned>x-amz-tagging</HeadersNotSigned>
  <RequestId>8CA589EDB3KB3EKE</RequestId>
  <HostId>/4HjL9q/xBLps/U8Pd9zbkd3ASCEyScl1lcoxi0SM6y80/2BCX9fvJKwi9IFWMrPLhXwRzzEaOY=</HostId>
</Error>

@onno-vos-dev
Copy link
Member

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?
If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

I got this error when trying this branch

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>There were headers present in the request which were not signed</Message>
  <HeadersNotSigned>x-amz-tagging</HeadersNotSigned>
  <RequestId>8CA589EDB3KB3EKE</RequestId>
  <HostId>/4HjL9q/xBLps/U8Pd9zbkd3ASCEyScl1lcoxi0SM6y80/2BCX9fvJKwi9IFWMrPLhXwRzzEaOY=</HostId>
</Error>

@phulien Can you try again after pulling latest change? Sorry, I'm not at the office right now so don't really have an environment where I can test my changes.

@phulien
Copy link
Author

phulien commented Jan 3, 2025

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?
If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

I got this error when trying this branch

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>There were headers present in the request which were not signed</Message>
  <HeadersNotSigned>x-amz-tagging</HeadersNotSigned>
  <RequestId>8CA589EDB3KB3EKE</RequestId>
  <HostId>/4HjL9q/xBLps/U8Pd9zbkd3ASCEyScl1lcoxi0SM6y80/2BCX9fvJKwi9IFWMrPLhXwRzzEaOY=</HostId>
</Error>

@phulien Can you try again after pulling latest change? Sorry, I'm not at the office right now so don't really have an environment where I can test my changes.

I got the same error with latest change (54fadb5).

@onno-vos-dev
Copy link
Member

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?
If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

I got this error when trying this branch

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>There were headers present in the request which were not signed</Message>
  <HeadersNotSigned>x-amz-tagging</HeadersNotSigned>
  <RequestId>8CA589EDB3KB3EKE</RequestId>
  <HostId>/4HjL9q/xBLps/U8Pd9zbkd3ASCEyScl1lcoxi0SM6y80/2BCX9fvJKwi9IFWMrPLhXwRzzEaOY=</HostId>
</Error>

@phulien Can you try again after pulling latest change? Sorry, I'm not at the office right now so don't really have an environment where I can test my changes.

I got the same error with latest change (54fadb5).

😢 Let me see what I can do without making you my personal guinea pig 😅 Give me an hour or so :-)

@jonatanklosko
Copy link
Collaborator

@onno-vos-dev the header needs to be listed in X-Amz-SignedHeaders :)

@phulien
Copy link
Author

phulien commented Jan 3, 2025

@phulien Can you try branch: add-tagging-to-presign-urls that is in this repo? :-) Perhaps that would do the trick?
If so, I can tidy that up and bring your commit along in there so you'd still get your name as a contributor 😉 👍

I got this error when trying this branch

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>AccessDenied</Code>
  <Message>There were headers present in the request which were not signed</Message>
  <HeadersNotSigned>x-amz-tagging</HeadersNotSigned>
  <RequestId>8CA589EDB3KB3EKE</RequestId>
  <HostId>/4HjL9q/xBLps/U8Pd9zbkd3ASCEyScl1lcoxi0SM6y80/2BCX9fvJKwi9IFWMrPLhXwRzzEaOY=</HostId>
</Error>

@phulien Can you try again after pulling latest change? Sorry, I'm not at the office right now so don't really have an environment where I can test my changes.

I got the same error with latest change (54fadb5).

😢 Let me see what I can do without making you my personal guinea pig 😅 Give me an hour or so :-)

I have updated the MR. Please check the latest version; it is now much simpler.

@jonatanklosko
Copy link
Collaborator

FWIW the current version looks good to me, we just need to add the option in the docstring and it also needs a test.

@@ -253,6 +254,7 @@ sign_v4_query_params(AccessKeyID, SecretAccessKey, Region, Service, DateTime, Me
URIEncodePath = proplists:get_value(uri_encode_path, Options, true),
TimeToLive = proplists:get_value(ttl, Options, 86400),
SessionToken = proplists:get_value(session_token, Options, undefined),
Tag = proplists:get_value(tag, Options, undefined),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer plural of tag (so tags) both as the key in the Options as well as the variable name :-)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I will update Tags, document and add a test case. Thank for reviewing!

@onno-vos-dev
Copy link
Member

FWIW the current version looks good to me, we just need to add the option in the docstring and it also needs a test.

Agreed 👍 Add a test and I'd be happy 👍

@phulien
Copy link
Author

phulien commented Jan 3, 2025

@onno-vos-dev please double-check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants