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

Upgrade Authentication to use AWS Signature Version 4 #50

Merged
merged 15 commits into from
Dec 14, 2016

Conversation

estadtherr
Copy link

@estadtherr estadtherr commented Oct 4, 2016

This pull request upgrades the authentication logic from version 2 to version 4 of the AWS Signature algorithm. Since more information is needed in the bucket context to compute the signature (namely the region), this is a non-backward-compatible change to the API. Consequently, I bumped the library major version from 2 to 3. I chose to support only version 4 instead of trying to support both V2 and V4, since it made the implementation more intuitive, and V4 is supported everywhere according to this note in the AWS documentation:

Note
Amazon S3 supports Signature Version 4, a protocol for authenticating inbound API requests to AWS services, in all AWS regions. At this time, AWS regions created before January 30, 2014 will continue to support the previous protocol, Signature Version 2. Any new regions after January 30, 2014 will support only Signature Version 4 and therefore all requests to those regions must be made with Signature Version 4.

As an added bonus, adding region specification to the API should make the library function much better for buckets that reside somewhere other than the default 'us-east-1' region.

Mac OS builds use the SHA/HMAC algorithms built into libSystem. Linux builds use the SHA/HMAC algorithms in libssl/libcrypto (part of OpenSSL). I am not familiar with mingw or windows, so that build may or may not need additional work. The SHA1 implementation has been removed, along with everything else that only applied to the older signature method.

This change also fixes the Mac OS compilation error referenced in #47, in a way that remains compatible with Linux builds.

@bosim
Copy link

bosim commented Dec 13, 2016

@bji do you know which of the two pull request you are going to merge in?

We are relying on the way of setting the region as this pull request implements.

@bji
Copy link
Owner

bji commented Dec 13, 2016

Do you have a preference? This one looks better to me, do you agree?

@estadtherr
Copy link
Author

I'm obviously biased, and would prefer to see this PR merged, but I can at least tell you the reasons I proceeded with a fresh implementation rather than use the other PR:

  • This PR removes support for protocol V2, which simplifies the code and, since Amazon supports V4 everywhere, is compatible with every region/environment (and I have tested it in multiple environments)
  • This PR is a more complete implementation (e.g. by supporting single-resource query strings)
  • The region specification in this PR is more amenable to API integration within other applications. The other PR follows the "s3" command-line utility convention of using an environment variable to specify region, which makes the API behavior inconsistent.
  • This PR has a more native Mac OS implementation using encryption libraries already available on the platform instead of adding an OpenSSL dependency.
  • This PR corrects some other minor issues discovered along the way, such as the fix for Fix OSX build error due to uint64_t format string incompatibility #47, and straightening out some confusion between sub-resources and query-strings in upload/copy operations.

Let me know if you have questions after performing a review!

@bji
Copy link
Owner

bji commented Dec 14, 2016

Thank you for the excellent write-up!

@@ -102,6 +102,7 @@ endif

ifndef LIBXML2_LIBS
LIBXML2_LIBS := $(shell xml2-config --libs)
LIBXML2_LIBS := $(filter-out -L$(shell xcrun --show-sdk-path)/usr/lib, $(LIBXML2_LIBS))
Copy link
Owner

Choose a reason for hiding this comment

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

Can you explain this line please? I don't even have the xcrun command on my Fedora installation. What is this supposed to do?

Copy link
Owner

Choose a reason for hiding this comment

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

Oh I just noticed that this is in the osx version of the Makefile, so I guess it's an osx specific command. Still curious about what this change is supposed to do.

Copy link
Author

Choose a reason for hiding this comment

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

This is actually a workaround for an Xcode error on Mac OS 10.11. See this Stack Overflow post for more information. I just built it now successfully without the workaround on Mac OS 10.12 (to which I've upgraded since I worked on this PR), so it may not be needed unless someone is building on 10.11. We could remove it and let people discover the workaround if they're on 10.11, or keep the workaround as a comment with a note about 10.11. What's your preference?

Copy link
Owner

Choose a reason for hiding this comment

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

My preference is to keep the workaround but add comments to the makefile so that it's not mysterious.

Copy link
Owner

Choose a reason for hiding this comment

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

Well anyway, you've already done the lion's share of the work, I'll just take the commit and add the comments myself. Thanks.

// base64 encode bytes. The output buffer must have at least
// ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written
// to [out].
int base64Encode(const unsigned char *in, int inLen, char *out);
Copy link
Owner

Choose a reason for hiding this comment

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

Curious -- why did you remove the signatures of these funtions from this header file?

Copy link
Author

@estadtherr estadtherr Dec 14, 2016

Choose a reason for hiding this comment

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

The base64Encode() function was only used by the implementation of version 2 of the signature algorithm. All of the hashing/encoding in version 4 is done with HMAC/SHA256 routines, so the base64 implementation was no longer needed.

Copy link
Owner

Choose a reason for hiding this comment

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

Does that mean that these functions can be removed from util.c as well?

Copy link
Author

Choose a reason for hiding this comment

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

I removed them from util.c in the same commit (584bf48).

Copy link
Owner

Choose a reason for hiding this comment

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

Hm, sorry, somehow I didn't see that, and I looked over the diff several times. Must have missed it.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah, it was hidden behind a 'show diff' link. Sorry I am not used to github's change inspection system.

Copy link
Author

Choose a reason for hiding this comment

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

yeah, that's caught me before, too! I think it does that with diffs larger than some threshold.

@bji bji merged commit 86cbc59 into bji:master Dec 14, 2016
@bji
Copy link
Owner

bji commented Dec 14, 2016

Thank you again!

@bji
Copy link
Owner

bji commented Dec 14, 2016 via email

@bji
Copy link
Owner

bji commented Dec 14, 2016 via email

@estadtherr
Copy link
Author

Unfortunately I don't have anything resembling a Windows environment, so I wasn't able to build or test the mingw version. Sorry, I tried to point that out in the PR description, but that fact was buried a bit in the description of the crypto libraries that I used on Mac OS and Linux.

How would you like to handle the mingw version with respect to this change?

@bji
Copy link
Owner

bji commented Dec 14, 2016 via email

@estadtherr
Copy link
Author

I think I'd like to punt on the issue. If someone comes along who really still cares about the mingw version, then they can get it to work.

Sounds like a plan - open source philosophy at work!

@codemedic
Copy link

Hey Bryan ( @bji ).. what is the state of master branch?
I was after the feature added by this PR #50.
A lot seem to have changed since 2.0; i.e no chance of applying it as a patch over v2.0.

Any chance of creating a release?

@estadtherr
Copy link
Author

@codemedic - this PR was merged to master in this commit: 86cbc59
I know some Linux distributions have picked up version 3.0 (and even version 4.0) since then.

@codemedic
Copy link

Thanks @estadtherr .. are these releases tagged or branched?
I couldn't find any, from the repo.

@estadtherr
Copy link
Author

I suspect the OS distribution maintainers grabbed an untagged commit, and did their own packaging and testing from there.

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.

4 participants