Search code examples
amazon-web-servicesamazon-s3emrhadoop2

Running jobs using EMR cluster and s3 files from other account


I would like to know if there is a way to access jar files and input and output location from s3 of another account. I have my EMR cluster running on account 1. I want to access File and jar locations from s3 of account 2. I am using AWS SDK to launch AWS Simple workflow. Thanks.


Solution

  • You need to create role for cross-account access: http://docs.aws.amazon.com/IAM/latest/UserGuide/delegation-cross-acct-access.html

    You can establish cross-account access by using IAM roles. You define a role in Account 2 that can be assumed by a user (an IAM user or a federated user) in Account 1. Using roles for cross-account access lets you grant access to any resource in Account 2 (in your case it is S3)

    EDIT:

    You need first to create a Role with readwrite access to S3 in Account 2 (let's name it "S3-ReadWrite-role"), and give permission to users from Account 1 to use the role "S3-ReadWrite-role"

    Check this link,it will explain to you how to do it: http://blogs.aws.amazon.com/security/post/TxC24FI9IDXTY1/Delegating-API-Access-to-AWS-Services-Using-IAM-span-class-matches-Roles-span

    After you finish the fist step, you can use this code ( not tested): Using your credentials, you'll receive a temporary security credentials to use "S3-ReadWrite-role", then you'll use the temporary security credentials to access to S3 ;)

    import java.util.HashMap;
    
    import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
    import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
    import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
    import com.amazonaws.services.dynamodb.AmazonDynamoDBClient;
    import com.amazonaws.services.dynamodb.model.*;
    import com.amazonaws.auth.*;
    
    public class AssumeRoleDemo {
        private static final String ROLE_ARN =
        "arn:aws:iam::111122223333:role/S3-ReadWrite-role";
    
        private static AWSCredentials longTermCredentials_;
    
        private static void init() throws Exception {
        // acquire long term credentials from the properties file ( you should use this method)
        //longTermCredentials_ = new PropertiesCredentials(AssumeRoleDemo.class.getResourceAsStream("AwsCredentials.properties"));
    
        // or you can use this one
        longTermCredentials = new BasicAWSCredentials(access_key_id, secret_access_key);
    }
    
        public static void main(String[] args) throws Exception {
            init();
    
           // Step 1. Use Joe.s long-term credentials to call the
           // AWS Security Token Service (STS) AssumeRole API, specifying 
           // the ARN for the role S3-RW-role in account2.
    
            AWSSecurityTokenServiceClient stsClient = new
              AWSSecurityTokenServiceClient(longTermCredentials_);
    
            AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
              .withRoleArn(ROLE_ARN)
              .withDurationSeconds(3600)
              .withRoleSessionName("demo");
    
           AssumeRoleResult assumeResult =
               stsClient.assumeRole(assumeRequest);
    
          // Step 2. AssumeRole returns temporary security credentials for 
          // the IAM role.
    
          BasicSessionCredentials temporaryCredentials =
             new BasicSessionCredentials(
                    assumeResult.getCredentials().getAccessKeyId(),
                    assumeResult.getCredentials().getSecretAccessKey(),
                    assumeResult.getCredentials().getSessionToken());
    
         // Step 3. Make S3 service calls to read data from a 
         // S3, stored in account2, using the 
         // temporary security credentials from the S3-ReadWrite-role 
         // that were returned in the previous step.
    
         AmazonS3 s3Client = new AmazonS3Client(temporaryCredentials);
         S3Object object = s3Client.getObject(
                  new GetObjectRequest(bucketName, key));
         InputStream objectData = object.getObjectContent();
         // Process the objectData stream.
         objectData.close();
    
        }
    }