Questions about Amazon AWS integration

9 replies [Last post]
shane.lipscomb
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 26 May 2011

I'm trying to use Amazon AWS simpleDB for a project and I am running into an issue with the required signature. I'm hoping someone on here has either successfully incorporated an AWS service, or can at least help me find some functions I "might" be missing.

First, has anyone done this with AWS before?

I've read online that a possible hang up might be that my secret key is not URL encoded, or that the signature is not. Both look like they need to be encoded (one has a "/" in it, the other two "="s. But I cannot find in the documentation or on the forum how to simply url encode a string.

Any (and all) help will be greatly appreciated. Thanks in advance.

Replies

briwil
User offline. Last seen 6 weeks 2 days ago. Offline
Joined: 23 Dec 2010

Did you ever figure this out?

shane.lipscomb
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 26 May 2011

Yes, we finally figured this out. But then we realized our project would also require the use of a server for another part of it, something we are not prepared at this time to pursue, so the project has been shelved. Unfortunately the code I have is just hacked together at this point to prove it will work, so it isn't pretty enough to post right off.

If you are looking to try this and have any specific questions, please, ask them. I'll try to get you as far along as I can.

briwil
User offline. Last seen 6 weeks 2 days ago. Offline
Joined: 23 Dec 2010

Well, I think I know (maybe) how to send a REST request, I'm just not sure how to use crypto to create a signature for the request.

Also need to figure out how to make a valid timestamp, but I think I can figure that one out on my own, maybe.

Any help would definitely be appreciated!

shane.lipscomb
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 26 May 2011

Okay I warned you, it's ugly, but here are the a few of the functions I built to get simpleDB working:

First, I created two variables, aKey and sKey, to hold my Amazon access and secret keys, respectively.

Be sure to include the following required modules:

1
2
local crypto = require("crypto")
local mime = require("mime")

The first set of code is my quick solution to creating a timestamp:

1
2
3
4
5
6
7
8
9
10
11
12
function twoDigit(n)
    local r = tostring(n)
    if string.len(r) < 2 then
        r = "0"..r;
    end
    return r
end
 
function getTime()
    local date = os.date("!*t")
    return date.year.."-"..twoDigit(date.month).."-"..twoDigit(date.day).."T"..twoDigit(date.hour).."%3A"..twoDigit(date.min).."%3A"..twoDigit(date.sec).."Z"
end

The next piece of code is the hash generator signature thingy (yes, technical term) borrowed from bob.dickinson (thanks Bob!)

1
2
3
4
5
local function sha1_hmac( key, text )
 
        return crypto.hmac(crypto.sha1, text, key, true)
 
end

The following is my Create a Domain function, where the passed-in-variable "name" is the name to call the domain.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function createDomain(name)
 
    local timeStamp = getTime()
 
    local toSign = "GET\nsdb.amazonaws.com\n/\nAWSAccessKeyId="..aKey.."&Action=CreateDomain&DomainName="..name.."&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp="..timeStamp.."&Version=2009-04-15"
 
    local signature = mime.b64(sha1_hmac(sKey, toSign))
        
    local myURL = "https://sdb.amazonaws.com/?Action=CreateDomain&AWSAccessKeyId="..aKey.."&DomainName="..name.."&SignatureVersion=2&SignatureMethod=HmacSHA1&Timestamp="..timeStamp.."&Version=2009-04-15&Signature="..signature
    
    local function networkListener( event )
        if ( event.isError ) then
                print( "Network error!")
        else
                print ( "RESPONSE: " .. event.response )
                
                save(event.response)
        end
    end
 
    network.request( myURL, "GET", networkListener )
 
end

This next code lists the domains:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function listDomains()
 
    local timeStamp = getTime()
 
    local toSign = "GET\nsdb.amazonaws.com\n/\nAWSAccessKeyId="..aKey.."&Action=ListDomains&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp="..timeStamp.."&Version=2009-04-15"
 
    local signature = mime.b64(sha1_hmac(sKey, toSign))
        
    local myURL = "https://sdb.amazonaws.com/?Action=ListDomains&AWSAccessKeyId="..aKey.."&SignatureVersion=2&SignatureMethod=HmacSHA1&Timestamp="..timeStamp.."&Version=2009-04-15&Signature="..signature
    
    local function networkListener( event )
        if ( event.isError ) then
                print( "Network error!")
        else
                print ( "RESPONSE: " .. event.response )
                
                save(event.response)
        end
    end
 
    network.request( myURL, "GET", networkListener )
 
end

This next code performs a "Get Attributes" call. Please note that I hard-coded into the strings the attribute and item names just to get the code tested. Like I said, I shelved this project due to other concerns. Again, the passed-in-variable "name" is the domain you are checking.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getAttributes(name)
 
    local timeStamp = getTime()
 
    local toSign = "GET\nsdb.amazonaws.com\n/\nAWSAccessKeyId="..aKey.."&Action=GetAttributes&AttributeName.1=theTest&DomainName="..name.."&ItemName=item_01&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp="..timeStamp.."&Version=2009-04-15"
 
    local signature = mime.b64(sha1_hmac(sKey, toSign))
        
    local myURL = "https://sdb.amazonaws.com/?Action=GetAttributes&AWSAccessKeyId="..aKey.."&AttributeName.1=theTest&DomainName="..name.."&ItemName=item_01&SignatureVersion=2&SignatureMethod=HmacSHA1&Timestamp="..timeStamp.."&Version=2009-04-15&Signature="..signature
    
    local function networkListener( event )
        if ( event.isError ) then
                print( "Network error!")
        else
                print ( "RESPONSE: " .. event.response )
                
                save(event.response)
        end
    end
 
    network.request( myURL, "GET", networkListener )
 
end

So, there you go. Frankencode. But it should get you started. If someone makes use of this please consider submitting a cleaned up version to the code base. Thanks.

briwil
User offline. Last seen 6 weeks 2 days ago. Offline
Joined: 23 Dec 2010

Wow, that is amazing, and so much more than I hoped for. That makes my weekend!
Yes, that should be enough I think; it all makes sense, just didn't know how to write it.

Thanks again.

shane.lipscomb
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 26 May 2011

Always glad to help :)

Dotnaught
User offline. Last seen 2 hours 56 min ago. Offline
Joined: 7 Jul 2009

Cool, thanks for the starter code.

It may be worth noting that adding crypto (HTTPS/SSL) means that you are supposed to get special approval for your app.

http://tigelane.blogspot.com/2011/01/apple-itunes-export-restrictions-on.html

shane.lipscomb
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 26 May 2011

@Dotnaught,

Yes, that was one of the things that dissuaded us from pursuing this particular project via Amazon. The signature process requires us to use crypto. It may not be that big a deal to get approval, but we are on to other things at the moment.

Thanks, though, for ensuring this is a complete discussion.

Satheesh
User offline. Last seen 16 hours 21 min ago. Offline
Joined: 25 May 2011

@shane.lipscomb
Thanks a lot for the code.

I've posted a decently patched up version in Code Exchange
http://developer.anscamobile.com/code/amazon-simpledb-api

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.