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
-
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.
-
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.
-
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.
-
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 callaws sts get-caller-identity(with instance profile attached). - Lambda: In the function code, call
aws sts get-caller-identityor 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.