Blog

Accessing Amazon Web Services from Google App Engine

January 3, 2009 · Leave a Comment

Amazon.com has put together a set of services (AWS) that allow you to rent, not buy, your infrastructure. They are extremely competitive and competent. Despite the use of the word simple in the naming of these services, simple they are not. Echoing Einstein perhaps: things should be as simple as possible but no simpler.

A gem: Amazon knows a thing or two about payments and money transfer; no surprise that Amazon FPS (flexible payment system) should be a unique part of the offering.

When it comes to writing applications, Google App Engine (GAE) is more constrained but ramp-up is easier and more amenable to agile development — a necessity for Early Stage companies.

How can we leverage the robustness of AWS from the simple (but constrained) environment of GAE? We tried to call FPS services from GAE to see. The remainder of this post is about tips and tricks for doing so. Fair warning, it’s a bit technical.

Scenario

We’re building a GAE application that will handle its billing and collecting through Amazon FPS, so what we really need is an interface class in GAE that would access FPS (from Google’s servers to Amazon’s).

FPS offers SOAP as well as REST interfaces. REST, being closer to GAE’s urlfetch API, was the interface of choice. The trickiest part of the interface is secure signing of the URL. Any flaws in it and the FPS engine will give a terse “denied” message and send you back.

We defined an FPS class to encapsulate this behavior and all classes in our application that need to interact with FPS inherit from this class. The function MakeURL() returns a URL that is ready to send to Amazon. Here’s the code for the FPS class:

class FPS(object):
    host = '' # Populate in the derived class
    Args = {} # Dictionary. Populated with FPS parameters in the derived class
    Args['Timestamp'] = datetime.datetime.now().isoformat()
    def encode(self, aws_secret_key, str, urlencode=False):
        hm = hmac.new(aws_secret_key, str, sha).digest()
        b64_hmac = base64.encodestring(hm).strip()
        if urlencode:
            return urllib.quote_plus(b64_hmac)
        else:
            return b64_hmac

    def MakeURL(self):
        sorted_header_keys = self.Args.keys()
        sorted_header_keys.sort(key=str.lower)
        rqst = ''
        for header_key in sorted_header_keys:
            rqst += header_key + self.Args[header_key]
        encd = 'https://'+self.host+'/?'
        for header_key in sorted_header_keys:
            encd += header_key + "=%s&" % urllib.quote_plus(self.Args[header_key])
        encd += 'Signature=%s' % self.encode(SECRET_AWS_KEY, rqst, True)
        return encd

You will also need to import a bunch of libraries (datetime base64 hmac httplib urllib re sha sys time). They are all part of GAE. Everything else is part of building the application and left as an exercise for the reader.

Oh, and one last thing: the Getting Started Guide calls for downloading a number of artifacts (AWS Access Key ID, AWS Secret Access Key, X.509 Certificates and Private Key, and various SDK components). You will need the ID and the secret key but none of the other components.

Copyright © 2009, J Singh


Categories: Requirements · Techniques
Tagged: ,

0 responses so far ↓

  • There are no comments yet...Kick things off by filling out the form below.

Leave a Comment