1
votes

AWS Roles are meant for services which requires access to AWS Services e.g. S3 etc. using temporary credentials. These are done using STS. This is useful when a user/application from one account needs access to a different account-owned resources on a temporary-basis.

However, STS will only issue a temporary credentials when the credentials are passed using Profile properties. At least that's what the code provided by AWS implies anyway

import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Credentials;

public class MakingRequestsWithIAMTempCredentials {
    public static void main(String[] args) {
        String clientRegion = "*** Client region ***";
        String roleARN = "*** ARN for role to be assumed ***";
        String roleSessionName = "*** Role session name ***";
        String bucketName = "*** Bucket name ***";

        try {
            // Creating the STS client is part of your trusted code. It has
            // the security credentials you use to obtain temporary security credentials.
            AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
                                                    .withCredentials(new ProfileCredentialsProvider())
                                                    .withRegion(clientRegion)
                                                    .build();

            // Obtain credentials for the IAM role. Note that you cannot assume the role of an AWS root account;
            // Amazon S3 will deny access. You must use credentials for an IAM user or an IAM role.
            AssumeRoleRequest roleRequest = new AssumeRoleRequest()
                                                    .withRoleArn(roleARN)
                                                    .withRoleSessionName(roleSessionName);
            AssumeRoleResult roleResponse = stsClient.assumeRole(roleRequest);
            Credentials sessionCredentials = roleResponse.getCredentials();
            
            // Create a BasicSessionCredentials object that contains the credentials you just retrieved.
            BasicSessionCredentials awsCredentials = new BasicSessionCredentials(
                    sessionCredentials.getAccessKeyId(),
                    sessionCredentials.getSecretAccessKey(),
                    sessionCredentials.getSessionToken());

            // Provide temporary security credentials so that the Amazon S3 client 
        // can send authenticated requests to Amazon S3. You create the client 
        // using the sessionCredentials object.
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                                    .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                                    .withRegion(clientRegion)
                                    .build();

            // Verify that assuming the role worked and the permissions are set correctly
            // by getting a set of object keys from the bucket.
            ObjectListing objects = s3Client.listObjects(bucketName);
            System.out.println("No. of Objects: " + objects.getObjectSummaries().size());
        }
        catch(AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process 
            // it, so it returned an error response.
            e.printStackTrace();
        }
        catch(SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}

The above code will only work without providing some credentials. So my question is, how is Role useful here when I can just simply use access/secret key ?

1
If your code is going to run on EC2 (or another AWS compute service) then, in the general case, you don't have to deal with credentials at all. The SDK will retrieve credentials as needed via the implicit IAM role that the compute was launched with. If you intend to use the implicit role to explicitly assume a different role, then you will have to manage that second set of credentials . - jarmod
@jarmod. I just thought about it for a while. I think the best thing to do is use a least privileged user (say A) who wants to access a resource owned by IT admin (e.g. S3 or EBS, etc.). To do that, A can just authenticate to AWS using his creds, but he can only access S3/EBS using the Role. In this way, he can only access it per session, i.e. the STS tokens are rotated. - ha9u63ar
I would get out of the habit of using the term 'users' here, assuming we are actually talking about applications. The credentials associated with an IAM user are persistent, as opposed to those associated with an assumed IAM role, which have a limited lifetime and are auto-rotated by EC2 etc. Yes, to assume a role you need credentials. It's generally better for the base role to have permissions to assume the more powerful role than it is for the base role to simply have the more powerful permissions inline. - jarmod

1 Answers

2
votes

Exactly the point you mentioned that the credentials are temporary is one of the many reasons why IAM roles are the recommended approach.

A role can be applied to AWS services as well as resources, for example an EC2 instance can have a role attached with AWS automatically rotating these. Additionally you can use STS to assume a role as role, this can be assumed from an IAM user, a role or a federated user.

You should try to avoid using IAM users where possible, there are some usecases such as signed URLs (where you would like it to last more than a few hours) as well as in an on-premise location. If you must use an IAM key you should make sure to rotate the key frequently.

For more information take a look at the IAM Identities (users, groups, and roles) and Security best practices in IAM pages.