How to create an IAM role for AWS services

Topic: Accounts access

Summary

Create an IAM role that an AWS service can assume to perform actions on your behalf: set the trust policy to the service principal, attach least-privilege permissions, and use the role in the service configuration. Use this for service-to-service access without long-lived keys.

Intent: How-to

Quick answer

  • Create a role with a trust policy that allows a specific AWS service principal (e.g. ec2.amazonaws.com, lambda.amazonaws.com) to assume the role in your account.
  • Attach managed or custom policies with only the actions and resources the service needs; avoid full admin unless required.
  • Assign the role to the resource (e.g. EC2 instance profile, Lambda execution role) so the service assumes it automatically; no access keys needed.

Prerequisites

Steps

  1. Create the role with a service trust policy

    In IAM → Roles → Create role, select the use case (e.g. EC2, Lambda) or custom trust; the trust policy will include the service principal (e.g. Service: ec2.amazonaws.com) and your account.

  2. Attach permission policies

    Attach one or more managed or custom policies that grant the minimum actions and resources the workload needs; avoid AdministratorAccess unless the service truly requires it.

  3. Name and assign the role

    Give the role a clear name and description; use the role as the instance profile (EC2), execution role (Lambda), or task role (ECS) so the service assumes it with no keys.

  4. Verify the service uses the role

    From the resource (e.g. EC2 instance or Lambda function), call the metadata service or run aws sts get-caller-identity to confirm the assumed role ARN matches.

Summary

You will create an IAM role that an AWS service can assume by setting a trust policy for the service principal, attaching least-privilege permissions, and assigning the role to the resource. Use this so services access AWS APIs without long-lived access keys.

Prerequisites

  • IAM permissions to create roles and attach policies (iam:CreateRole, iam:AttachRolePolicy, iam:PutRolePolicy).
  • Knowledge of which AWS service will assume the role (e.g. EC2, Lambda, ECS) and which APIs it must call.

Steps

Step 1: Create the role with a service trust policy

Console: IAM → Roles → Create role. Under Trusted entity type, choose AWS service. Select the use case (e.g. EC2, Lambda); the trust policy is pre-filled with the service principal.

CLI example (Lambda):

aws iam create-role --role-name my-lambda-role \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "lambda.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

Use the correct service principal for your use case (e.g. ec2.amazonaws.com, lambda.amazonaws.com, ecs-tasks.amazonaws.com). Restrict to your account and optionally to a specific resource (e.g. source ARN for Lambda) in the trust policy for least privilege.

Step 2: Attach permission policies

Attach managed or custom policies that grant only what the service needs:

aws iam attach-role-policy --role-name my-lambda-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Add custom policies for S3, DynamoDB, or other resources as needed. Avoid attaching AdministratorAccess unless the workload truly requires it.

Step 3: Name and assign the role

  • Set a clear name and description (e.g. prod-lambda-s3-read) so others know the purpose.
  • EC2: Attach the role as an instance profile (IAM creates the profile with the same name by default in the console). Lambda: Set the role as the function’s Execution role. ECS: Assign as Task role or Execution role as required.

The service will assume this role automatically; no access keys are stored on the resource.

Step 4: Verify the service uses the role

  • EC2: From the instance, curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ then get the role name and call aws sts get-caller-identity (with instance profile attached).
  • Lambda: In the function code, call aws sts get-caller-identity or inspect the execution role in the Lambda console. The returned ARN should match your role.

Verification

  • Role exists with the correct trust policy (service principal) and attached permission policies.
  • The resource (EC2, Lambda, etc.) has the role attached and get-caller-identity returns the role ARN when run from that resource.
  • No access keys are used; the service uses short-lived credentials from the role.

Troubleshooting

Access denied when service runs — The role’s permission policies may not include the action or resource; add the required permission or check for an explicit Deny (e.g. SCP). Use the IAM policy simulator with the role ARN.

Trust policy rejected — Ensure the Principal is the correct service (e.g. lambda.amazonaws.com). For cross-account or same-account delegation, use the correct principal and Condition keys (e.g. StringEquals for source ARN).

Role not assumed — Confirm the role is attached to the resource (instance profile for EC2, execution role for Lambda). For EC2, the instance profile must be attached to the instance; for Lambda, the function configuration must show the role ARN.

Next steps

Continue to