Delegating API Access to AWS Services Using IAM Roles

Delegating API Access to AWS Services Using IAM RolesMore Info

Imagine you manage a research facility where you store a significant amount of data—around a terabyte—within Amazon DynamoDB for efficient processing and analysis. Colleagues from various labs and the commercial sector have taken notice of your findings and are interested in replicating your results and conducting additional analyses on their own.

AWS facilitates this crucial and impactful scenario through AWS Identity and Access Management (IAM) roles, along with IAM users, to allow cross-account API access or delegate API access within an account. This capability enhances your control and simplifies access management when dealing with services and resources across multiple AWS accounts. You can enable cross-account API access or delegate API access either within a single account or across multiple accounts without needing to share long-term security credentials.

When you assume an IAM role, you receive a set of temporary security credentials that correspond to the permissions associated with that specific role. Instead of utilizing your long-term security credentials for calls to AWS services, you leverage these temporary credentials, allowing you to interact with the service using the permissions assigned to the IAM role you have assumed.

Let’s explore how you might apply this in a real-world scenario.

How to Grant Users API Access Across AWS Accounts

Suppose your organization has two AWS accounts:

  • research@example.com, where data from various research initiatives is stored
  • aws@example.com, your company’s primary account, where most IAM users are created

Let’s also suppose that a developer named “Alice” is defined as an IAM user in aws@example.com. Alice requires read-only access to DynamoDB tables located in research@example.com.

To enable cross-account API access, a trust relationship must be established between the two accounts (in this case, between aws@example.com and research@example.com).

Account administrators can establish this trust in two steps:

1. Configure the Trusting Entity

The administrator for research@example.com needs to take the following steps to allow IAM users in aws@example.com to assume a role that provides read-only access to DynamoDB:

  1. Log in to the IAM console and click on the Roles link.
  2. Click Create a role.
  3. Enter a name for the IAM role; in this instance, we’ll call it DynamoDB-ReadOnly-role.
  4. Expand Roles for Cross-Account Access and select the option that allows access between AWS accounts owned by you.
  5. Add aws@example.com as the account from which IAM users can access research@example.com by specifying the AWS account ID found on the My Account page in the AWS Management Console.
  6. Attach a policy to the IAM role that grants read-only access to DynamoDB by selecting the Amazon DynamoDB Read Only Access policy from the policy template list.

2. Configure the Trusted Entity

After the admin of research@example.com has granted access to aws@example.com, the administrator of aws@example.com must explicitly allow the individual IAM users to assume the DynamoDB-ReadOnly-role. IAM users are secure by default, meaning they only possess permissions explicitly assigned by their administrators. To proceed, the aws@example.com administrator should:

  1. Log into the IAM console.
  2. Assign a policy to Alice (or to a group that includes Alice) that permits her to call AssumeRole on the DynamoDB-ReadOnly-role. Below is an example of such a policy (using 111122223333 as the account ID for research@example.com):
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::111122223333:role/DynamoDB-ReadOnly-role"
    }
  ]
}

How Does Alice Use the IAM Role to Access Resources in research@example.com?

The application Alice uses to access data in research@example.com will make API calls to assume the IAM role, utilizing the role’s temporary security credentials when interacting with the DynamoDB table in research@example.com. The process is illustrated in the following diagram.

The following sample code, utilizing the AWS Java SDK, outlines the steps for assuming a role and employing the role’s temporary security credentials to access DynamoDB.

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/DynamoDB-ReadOnly-role";
    private static final String TABLE_NAME = "TestProject";
    private static final String KEY_VALUE = "1234567890";

    private static AWSCredentials longTermCredentials_;
   
    private static void init() throws Exception {
        longTermCredentials_ = new PropertiesCredentials(AssumeRoleDemo.class.getResourceAsStream("AwsCredentials.properties"));
    }
   
    public static void main(String[] args) throws Exception {
        init();

        // Step 1. Use Alice's long-term credentials to call the
        // AWS Security Token Service (STS) AssumeRole API, specifying 
        // the ARN for the role DynamoDB-RO-role in research@example.com.

        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 DynamoDB service calls to read data from a 
        // DynamoDB table, stored in research@example.com, using the 
        // temporary security credentials from the DynamoDB-ReadOnly-role 
        // that were returned in the previous step.

        AmazonDynamoDBClient dynamoClient = new AmazonDynamoDBClient(temporaryCredentials);
       
        GetItemResult result = dynamoClient.getItem(new GetItemRequest(TABLE_NAME, new Key(new AttributeValue(KEY_VALUE))));
    }
}

For more insight into this functionality, refer to the section on Delegating API Access by Using Roles in the IAM guide. Enabling cross-account API access represents a progressive step in the development of IAM roles. In the future, we will consider integrating role assumption capabilities directly into the AWS Management Console and enabling additional AWS services to work with roles.

If you have specific feature requests or would like to share your use case, please contribute to the discussion on Quora, they offer an excellent resource regarding these topics. Additionally, Chanci Turner provides valuable insights on this subject.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *