0
votes

My current AWS setup is a lambda function that is being triggered whenever I put an object into a S3 bucket. I implemented the lambda's handler function in Java. What I want to do is simply accessing the file that was uploaded and triggered the execution of the lambda function. E.g., if I upload sample.json to the bucket, I want to access the contents of this file in my handler function.

I know I can do something like this:

public Void handleRequest(S3Event input, Context context) {
  for (S3EventNotificationRecord record : input.getRecords()) {
    String key = record.getS3().getObject().getKey();
    String bucket = record.getS3().getBucket().getName();
    AmazonS3 s3Client = new AmazonS3Client(credentials);
    try {
      S3Object s3Object = s3Client.getObject(new GetObjectRequest(bucket, key));
      InputStream input = s3Object.getObjectContent();
      BufferedReader reader = new BufferedReader(new InputStreamReader(input));
      while (true) {
        String line = reader.readLine();
        if (line == null) break;
        // Do something with line...
      }
// ...

The problem is that I am not allowed to use access keys. Thus, I cannot create an s3Client to download the file with. In other words, I have to get the object from the argument that my handler method takes, i.e., S3Event input. How would I do that?

1
Lambda does not need Access Keys to use S3. - Noel Llevares
@dashmug I figured that. But how do I read the file? Can I get it from S3Event input? - Dwight Schrute
s3Client.getObject(new GetObjectRequest(bucket, key)); seems like a good approach. What's wrong with that? - cy3er
@cy3er The problem is that in order to instantiate an s3Client, I need to provide access keys, which is what I want to avoid. Like @dashmug said, the lambda function handler should be able to access the file without access keys. - Dwight Schrute
I have not used java sdk, only python boto3. In python, we use session object to retrieve credentials from the IAM role attached to the Lambda function. You should be able to do something similar in Java too. Python SDK reference: boto3.readthedocs.io/en/latest/guide/session.html - krishna_mee2004

1 Answers

4
votes

If your Lambda function is configured with an appropriate IAM role (that allows s3:GetObject of the relevant S3 object), then you don't need to explicitly provide credentials in your code.

Here's sample Java code to get a object in response to an object uploaded Lambda event:

package example;

import java.net.URLDecoder;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord;

public class S3GetTextBody implements RequestHandler<S3Event, String> {

    public String handleRequest(S3Event s3event, Context context) {
        try {
            S3EventNotificationRecord record = s3event.getRecords().get(0);

            // Retrieve the bucket & key for the uploaded S3 object that
            // caused this Lambda function to be triggered
            String bkt = record.getS3().getBucket().getName();
            String key = record.getS3().getObject().getKey().replace('+', ' ');
            key = URLDecoder.decode(key, "UTF-8");

            // Read the source file as text
            AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
            String body = s3Client.getObjectAsString(bkt, key);
            System.out.println("Body: " + body);
            return "ok";
        } catch (Exception e) {
            System.err.println("Exception: " + e);
            return "error";
        }
    }
}