Amazon AWS Signatures
Last Thursday I presented an afternoon overview on Web Services to a group. We were using soapUI to demonstrate some SOAP Web Services written for a customer, and I wanted to demonstrate also that it is just as easy to call public services which are remote. For this I chose the Amazon Product Advertising API, partly due to the fact that it’s already an example on Eviware’s soapUI website, and partly because Amazon is such a well-known company. This post is a very short follow-up to explain how to do properly, something which I had to use a nasty workaround for during the afternoon.
The problem was the signature required in the header of the SOAP request, which I had to drop-to an executable I had written to generate. I would rather have used an off-the-shelf tool, but I couldn’t get openssl to work (completely due to user-error you understand).
I knew it was one of a few gotchas that was giving me the problem but I didn’t have the time to figure it out. Now I have, so what follows is, in as few a number of steps as I can manage, a 1-2-3 of how to send a request to the Amazon Product Advertising API.
Before we begin, sign-up to Amazon AWS. Amazon will send you an email – follow the link provided in the email and grab your AWS Access Key ID and Secret Access Key and paste them somewhere – we’ll need them in a moment.
To send a SOAP request (without WS-Security):
- Run soapUI
- Create a new project with the Product Advertising API’s WSDL by entering the URL:
- In the Navigator pane on the left of the soapUI main window, find the request for the ItemSearch action and paste in:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://webservices.amazon.com/AWSECommerceService/2009-10-01"> <soapenv:Header xmlns:aws="http://security.amazonaws.com/doc/2007-01-01/"> <aws:AWSAccessKeyId>?</aws:AWSAccessKeyId> <aws:Timestamp>?</aws:Timestamp> <aws:Signature>?</aws:Signature> </soapenv:Header> <soapenv:Body> <ns:ItemSearch> <ns:AWSAccessKeyId>?</ns:AWSAccessKeyId> <ns:Shared> <ns:SearchIndex>DVD</ns:SearchIndex> </ns:Shared> <ns:Request> <ns:Title>Allo Allo</ns:Title> </ns:Request> </ns:ItemSearch> </soapenv:Body> </soapenv:Envelope>
- Replace the search criteria if you don’t wish to search for Allo Allo DVDs (I do – it is hilarious)
- Insert your AWS Access Key ID in the two places provided.
- Choose a date and time for the timestamp. Right now will do.
- Concatenate the name of the action you are invoking and the timestamp in the format YYYY-MM-DDTHH:MM:SSZ, e.g. ItemSearch2009-10-11T16:11:30Z.
- Generate the signature using openssl as follows, inserting your Secret Access Key where indicated:
$ echo -n ItemSearch2009-10-11T16:11:30Z | openssl dgst -sha256 -hmac secret_access_key -binary | openssl enc -base64
- Paste the timestamp and the signature into the request where indicated and click the ‘Play’ button in soapUI to send the request. If all is well you’ll get a set of results from Amazon.
If you don’t have openssl you can download it from http://www.openssl.org/. There are links to binaries there, including for Windows.
The -n option to echo is very important, and was where my problem lay. On UNIX it suppresses the carriage return – important since we don’t want a carriage return as part of the text to be signed. On Windows however there is no equivalent (to my knowledge) and including the carriage return gives the wrong signature.
My best suggestion for a workaround for Windows is as follows. Open up notepad and write the text to be signed “ItemSearch2009-10-11T16:11:30Z” into it with no newline after. Save it, making sure to save with ANSI encoding (an option in the Save Dialog). Then at the prompt, execute the following command, again inserting your Secret Access Key where indicated, and the filename of the file that you just created.
$ openssl dgst -sha256 -hmac secret_access_key -binary filename | openssl enc -base64
If you’re not using openssl, or you just want verification, assuming the hypothetical Secret Access Key of 1234, I get the following:
$ echo -n ItemSearch2009-10-11T16:11:30Z | openssl dgst -sha256 -hmac 1234 -binary | openssl enc -base64
If you’re getting the same then you’re okay 🙂
Full documentation of the Amazon Web Services security can be found here.