Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when AWS Lambda trying to list DynamoDb tables

I failed to get the following logic to work on AWS Lambda using Java:

1) When there is a new object created in S3 bucket, trigger a lambda function (written in java)

2) In this lambda function, list all the DynamoDB tables.

3) Create a table if there is none.

4) Write the S3 object's details as item into DynamoDB.

I only get item #1 working. when it reach item #2, I encounter a permission related error below.

Any help or suggestion?

The permission that i use is "Basic with DynamoDB", which has the following permission:

START RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e fileSize: 1024, DateTime:1970-01-01T00:00:00.000Zs3Key : HappyFace.jpgAWS credential profiles file not found in the given path: /home/sbx_user1052/.aws/credentials: java.lang.IllegalArgumentException java.lang.IllegalArgumentException: AWS credential profiles file not found in the given path: /home/sbx_user1052/.aws/credentials at com.amazonaws.auth.profile.internal.ProfilesConfigFileLoader.loadProfiles(ProfilesConfigFileLoader.java:45) at com.amazonaws.auth.profile.ProfilesConfigFile.loadProfiles(ProfilesConfigFile.java:176) at com.amazonaws.auth.profile.ProfilesConfigFile.(ProfilesConfigFile.java:112) at com.amazonaws.auth.profile.ProfilesConfigFile.(ProfilesConfigFile.java:92) at com.amazonaws.auth.profile.ProfileCredentialsProvider.getCredentials(ProfileCredentialsProvider.java:123) at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:1763) at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.listTables(AmazonDynamoDBClient.java:1208) at com.amazonaws.services.dynamodbv2.document.internal.ListTablesCollection.firstPage(ListTablesCollection.java:46) at com.amazonaws.services.dynamodbv2.document.internal.PageIterator.next(PageIterator.java:45) at com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport.nextResource(IteratorSupport.java:79) at com.amazonaws.services.dynamodbv2.document.internal.IteratorSupport.hasNext(IteratorSupport.java:47) at com.TriggerDynamoDB.handleRequest(TriggerDynamoDB.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497)

END RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e REPORT RequestId: e9ab5aba-307b-11e5-9663-3188c327cf5e Duration: 3294.97 ms Billed Duration: 3300 ms Memory Size: 512 MB Max Memory Used: 51 MB

Code is as follows:

public class TriggerDynamoDB implements RequestHandler<S3Event, String> {

public String handleRequest(S3Event s3event, Context context) {
     LambdaLogger logger = context.getLogger();
     try {           
         S3EventNotificationRecord record = s3event.getRecords().get(0);
         // Object key may have spaces or unicode non-ASCII characters.
         String srcKey = record.getS3().getObject().getKey().replace('+', ' ');
            srcKey = URLDecoder.decode(srcKey, "UTF-8");

         long fileSize = record.getS3().getObject().getSizeAsLong();
         DateTime datetime = record.getEventTime(); 

         logger.log("fileSize: " + fileSize + ", DateTime:" + datetime);
         logger.log("s3Key   : " + srcKey);

         DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
         //Table table = dynamoDB.getTable("dimensionFile");

         TableCollection<ListTablesResult> tables = dynamoDB.listTables();
         Iterator<Table> iterator = tables.iterator();

         while (iterator.hasNext()) { // this is where the error was thrown
             Table table = iterator.next();
             System.out.println(table.getTableName());
         }                    
         return "Ok";
     } catch (Exception e) {
         throw new RuntimeException(e);
     }
}
}
like image 979
Reusable Avatar asked Jul 22 '15 14:07

Reusable


1 Answers

The ProfileCredentialsProvider you're passing to the AmazonDynamoDBClient constructor attempts to load credentials from the ~/.aws/credentials file. This file doesn't exist on the host where your Lambda function is being run, hence the exception. This provider is mainly intended for things like integration tests that run on your dev machine and use your personal IAM user credentials.

On Lambda you want the EnvironmentVariableCredentialsProvider. This provider will load temporary credentials for the IAM Role associated with your Lambda function from environment variables that Lambda sets before invoking your code.

If you use the no-argument constructor for the AmazonDynamoDBClient, it will default to using the DefaultAWSCredentialsProviderChain to pull credentials. This provider checks environment variables, Java system properties, ~/.aws/credentials, and the EC2 Instance Metadata Service (in that order), and should pick up credentials whether you're running locally or on Lambda.

like image 65
David Murray Avatar answered Oct 05 '22 23:10

David Murray