Connecting To DynamoDB From an iPhone App

A couple of days ago, Amazon released DynamoDB for their AWS services.  Amazon describes DynamoDB as follows:

Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability. With a few clicks in the AWS Management Console, customers can launch a new Amazon DynamoDB database table, scale up or down their request capacity for the table without downtime or performance degradation, and gain visibility into resource utilization and performance metrics. Amazon DynamoDB enables customers to offload the administrative burdens of operating and scaling distributed databases to AWS, so they don’t have to worry about hardware provisioning, setup and configuration, replication, software patching, or cluster scaling.

DynamoDB is one of the new suite of “NoSQL” databases, similar in many respects to Mongo, Parse, and Amazon’s own SimpleDB. There is a ton of information about NoSQL databases on the web, if you’re interested in learning more, but for my purposes, they provide a quick and easy way to implement Cloud storage in my iPhone and Android apps.

Connecting to DynamoDB from an iPhone app is actually pretty simple, but the documentation about HOW to do it pretty sketchy, and requires a lot of poking around.   First and foremost, you’ll need to download the AWS SDK for iPhone (or Android).  Following the directions about how to integrate the SDK is pretty straightforward, so I’ll leave it at that.

The DynamoDB API is included in the latest SDK.  If you’ve used AWS before, you’ll know that for most IOS connections, it’s pretty easy to follow the examples and be successful, but there are no examples for DynamoDB.  That’s ok, you’ll try to use the same model to connect, and you’ll find that you’ll get an exception:

Requests must include an X-Amz-Security-Token header

Hmm.  What the heck is that?

Well, DynamoDB is one of the newer breed of AWS services that requires a security token from IAM.  This is where the headache comes into play.  It’s not that simple to find the information that you need to get this security token.  Turns out that it’s pretty easy to do, it’s just the finding the pieces and parts is tedious… sorta like looking for a tool on a really messy bench.

Getting a security token from IAM is pretty easy, but you must do two things.  First, you must configure and install a Token Vending Machine on AWS in order to get the token.  There are two kinds, anonymous and identifiable.  For my purposes, we’re going to use the anonymous TVM, and Amazon provides both a reference implementation and complete installation instructions.

The next thing you must do is to get one of these tokens from within your IOS app.  This too is pretty simple, but first you’ll need to grab some code.

In the SDK, you’ll find an example app called AWSiOSDemoTVM, and in there, you’ll need to copy all the code from the TVMClient folder into your own app.  You’ll also need to add the Security Framework.

Once this code is in your app, it’s a simple matter to get the security credentials and use them in your DynamoDB calls.  You can do so thusly:

 

-(AmazonCredentials *)getCredentials {
    Response *tvmResponse = nil;
    AmazonCredentials *credentials = nil;

    AmazonTVMClient *tvm = [[AmazonTVMClient alloc] initWithEndpoint: TVM_ENDPOINT useSSL: NO];
    tvmResponse = [tvm anonymousRegister];
    if ([tvmResponse wasSuccessful]) {
        tvmResponse = [tvm getToken];
    }

    if ([tvmResponse wasSuccessful]) {
        credentials = [AmazonKeyChainWrapper getCredentialsFromKeyChain];
    }

    return credentials;
}

Once you’ve gotten to this point, you have everything you need to connect to DynamoDB from within your iPhone or iPad app, and you can use the SDK normally. This, for example, will connect and return a list of table names:

-(NSArray *)getTableNames {
    NSArray *tableNames = nil;

    @try {
        AmazonCredentials *credentials = [self getCredentials];
        AmazonDynamoDBClient *client = [[AmazonDynamoDBClient alloc] initWithCredentials:credentials];

        DynamoDBListTablesResponse *response = [client listTables: [[DynamoDBListTablesRequest alloc] init]];

        tableNames = [response tableNames];
    }
    @catch (AmazonServiceException *exception) {
        NSLog(@"%@", [exception description]);
    }

    return tableNames;
}

I hope you’ve found this useful!

Tagged with: , , , , , , ,
Posted in Mobile Apps