# How to Create Service Roles for AWS Glue, Lambda, ECS, and Step Functions

> Learn to create AWS service roles for Glue, Lambda, ECS, and Step Functions. Define trust policies, attach managed policies, and grant specific resource access using the AWS CLI or IAM console.

- Repository: [Amazon Web Services/agent-toolkit-for-aws](https://github.com/aws/agent-toolkit-for-aws)
- Tags: how-to-guide
- Published: 2026-07-02

---

**Create service roles by defining trust policies that allow service principals (glue.amazonaws.com, lambda.amazonaws.com, ecs.amazonaws.com, states.amazonaws.com) to assume the role, attach AWS-managed policies like AWSGlueServiceRole or AWSLambdaBasicExecutionRole, and add inline permissions for specific resource access using the AWS CLI or IAM console.**

The Agent Toolkit for AWS provides comprehensive IAM guidance for creating service roles that enable AWS workloads to run securely. According to the repository's IAM management references in [`skills/core-skills/aws-iam/references/aws-iam-role-management.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-iam/references/aws-iam-role-management.md), every service role requires a trust policy, AWS-managed permissions, and service-specific inline policies. This guide walks through the exact configurations needed for Glue, Lambda, ECS, and Step Functions.

## Prerequisites for Creating Service Roles

Before creating any service role, ensure you have the necessary IAM permissions and understand the naming conventions.

- **Required IAM permissions**: You must have `iam:CreateRole`, `iam:PutRolePolicy`, and `iam:PassRole` permissions on the target account
- **Naming convention**: Use clear, service-specific names like `MyApp-Glue-ServiceRole` or `MyApp-Lambda-ExecRole`
- **Trust policy security**: Always include the `aws:SourceAccount` condition key in trust policies to prevent confused-deputy attacks

## AWS Glue Service Role

AWS Glue ETL jobs require a service role that can access the Data Catalog, underlying data sources, and S3 Tables for data lake operations.

### Required Permissions

According to [`skills/specialized-skills/storage-skills/creating-data-lake-table/references/table-creation-glue-etl.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/specialized-skills/storage-skills/creating-data-lake-table/references/table-creation-glue-etl.md), a Glue service role requires:

- **Managed policy**: `AWSGlueServiceRole`
- **Inline permissions**: `glue:GetCatalog`, `glue:GetDatabase`, `glue:GetTable`, `glue:passConnection`
- **Data lake permissions**: `s3tables:*` for S3 Tables integration

### Trust Policy

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "glue.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<ACCOUNT_ID>"
        }
      }
    }
  ]
}

```

## AWS Lambda Execution Role

Lambda functions assume an execution role to interact with AWS services and write logs to CloudWatch.

### Required Permissions

- **Managed policy**: `AWSLambdaBasicExecutionRole` (provides CloudWatch Logs access)
- **Additional permissions**: Resource-specific policies for services your function accesses (e.g., S3, DynamoDB)

### Trust Policy

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<ACCOUNT_ID>"
        }
      }
    }
  ]
}

```

## Amazon ECS Roles

ECS workloads require three distinct role types: the service role for the control plane, the task execution role for container management, and the task role for application code.

### ECS Service Role

The service role allows the ECS control plane to manage cluster resources.

- **Managed policy**: `AmazonECSServiceRolePolicy`
- **Trust principal**: `ecs.amazonaws.com`

### ECS Task Execution Role

The task execution role enables ECS to pull container images and write logs to CloudWatch.

- **Managed policy**: `AmazonECSTaskExecutionRolePolicy`
- **Additional permissions**: `ecr:GetAuthorizationToken`, `logs:CreateLogStream`, S3 access as needed
- **Trust principal**: `ecs-tasks.amazonaws.com`

### ECS Task Role

The task role grants permissions to the application code running inside the container.

- **Policy type**: Custom inline policy based on workload requirements
- **Common permissions**: DynamoDB access, S3 operations, or other AWS API calls your containerized application requires

### Trust Policy for Service Role

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

```

## AWS Step Functions Execution Role

Step Functions state machines require an execution role that permits the service to invoke other AWS services on your behalf.

### Required Permissions

- **Managed policy**: `AWSStepFunctionsFullAccess` (or a custom least-privilege policy)
- **Service permissions**: Permissions for every service the workflow calls, such as `lambda:InvokeFunction`, `glue:StartJobRun`, or `ecs:RunTask`

### Trust Policy

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "states.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "<ACCOUNT_ID>"
        }
      }
    }
  ]
}

```

## CLI Examples for Creating Service Roles

Use the following AWS CLI commands to create and configure each service role. Replace `<ACCOUNT_ID>` with your AWS account ID.

### Create a Glue ETL Service Role

```bash

# Create the role with Glue trust policy

aws iam create-role \
  --role-name MyApp-Glue-ServiceRole \
  --assume-role-policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "glue.amazonaws.com"},
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {"aws:SourceAccount": "<ACCOUNT_ID>"}
      }
    }
  ]
}
EOF
)

# Attach AWS managed policy

aws iam attach-role-policy \
  --role-name MyApp-Glue-ServiceRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole

# Add S3 Tables inline permissions

aws iam put-role-policy \
  --role-name MyApp-Glue-ServiceRole \
  --policy-name S3TablesAccess \
  --policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3tables:GetTableBucket",
        "s3tables:CreateTable"
      ],
      "Resource": "*"
    }
  ]
}
EOF
)

```

### Create a Lambda Execution Role

```bash
aws iam create-role \
  --role-name MyApp-Lambda-ExecRole \
  --assume-role-policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "lambda.amazonaws.com"},
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {"aws:SourceAccount": "<ACCOUNT_ID>"}
      }
    }
  ]
}
EOF
)

aws iam attach-role-policy \
  --role-name MyApp-Lambda-ExecRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

```

### Create ECS Service and Task Roles

```bash

# ECS Service Role (control plane)

aws iam create-role \
  --role-name MyApp-ECS-ServiceRole \
  --assume-role-policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "ecs.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
)

aws iam attach-role-policy \
  --role-name MyApp-ECS-ServiceRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSServiceRolePolicy

# ECS Task Execution Role

aws iam create-role \
  --role-name MyApp-ECS-TaskExecRole \
  --assume-role-policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "ecs-tasks.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
)

aws iam attach-role-policy \
  --role-name MyApp-ECS-TaskExecRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

```

### Create a Step Functions Execution Role

```bash
aws iam create-role \
  --role-name MyApp-States-ExecRole \
  --assume-role-policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"Service": "states.amazonaws.com"},
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {"aws:SourceAccount": "<ACCOUNT_ID>"}
      }
    }
  ]
}
EOF
)

# Add permissions for Lambda and Glue integration

aws iam put-role-policy \
  --role-name MyApp-States-ExecRole \
  --policy-name StateMachinePermissions \
  --policy-document file://<(cat <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["lambda:InvokeFunction"],
      "Resource": "arn:aws:lambda:*:*:<ACCOUNT_ID>:function:*"
    },
    {
      "Effect": "Allow",
      "Action": ["glue:StartJobRun"],
      "Resource": "arn:aws:glue:*:*:<ACCOUNT_ID>:job/*"
    }
  ]
}
EOF
)

```

## Summary

- **Trust policies** must allow the specific service principal (e.g., `glue.amazonaws.com`, `lambda.amazonaws.com`) to assume the role using `sts:AssumeRole`
- **AWS-managed policies** provide baseline permissions: `AWSGlueServiceRole` for Glue, `AWSLambdaBasicExecutionRole` for Lambda, `AmazonECSServiceRolePolicy` and `AmazonECSTaskExecutionRolePolicy` for ECS
- **Security conditions** should include `aws:SourceAccount` in trust policies to prevent confused-deputy attacks across accounts
- **Inline policies** extend managed policies with specific resource permissions, such as S3 Tables access for Glue ETL jobs or service invocation permissions for Step Functions
- **ECS requires three roles**: a service role for the control plane, a task execution role for container management, and a task role for application permissions

## Frequently Asked Questions

### What is the difference between an ECS task execution role and a task role?

The **task execution role** (`ecs-tasks.amazonaws.com` principal) grants permissions to the ECS agent to pull container images from ECR, write logs to CloudWatch, and access secrets. The **task role** (`ecs-tasks.amazonaws.com` principal in the task definition) grants permissions to the application code running inside the container. According to the Agent Toolkit for AWS IAM guidance, the task execution role uses `AmazonECSTaskExecutionRolePolicy`, while the task role requires a custom policy based on your application's AWS API usage.

### Why do I need the aws:SourceAccount condition in trust policies?

The `aws:SourceAccount` condition prevents the **confused-deputy problem**, where a service might be tricked into accessing resources in a different account. By specifying `StringEquals: {aws:SourceAccount: "<ACCOUNT_ID>"}`, you ensure that only resources in your specific AWS account can assume the role through that service principal. This security control is emphasized in [`skills/core-skills/aws-iam/references/aws-iam-role-management.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-iam/references/aws-iam-role-management.md) as a best practice for all service roles.

### Can I use the same IAM role for multiple AWS services?

While technically possible, using the same role across multiple services violates the **principle of least privilege**. Each service (Glue, Lambda, ECS, Step Functions) requires different permissions and trust relationships. The Agent Toolkit reference implementations recommend creating service-specific roles (e.g., `MyApp-Glue-ServiceRole`, `MyApp-Lambda-ExecRole`) to minimize blast radius and maintain clear audit trails for each service's access patterns.

### How do I validate that my service role has the correct permissions?

Use the **IAM policy simulator** (`aws iam simulate-principal-policy`) to test whether your role can perform specific actions before deploying. Additionally, verify the trust relationship with `aws iam get-role --role-name <ROLE_NAME>` to confirm the service principal is correctly configured. For Glue-specific validation, reference [`skills/specialized-skills/storage-skills/creating-data-lake-table/references/table-creation-glue-etl.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/specialized-skills/storage-skills/creating-data-lake-table/references/table-creation-glue-etl.md) to ensure you have included `glue:GetCatalog`, `glue:GetDatabase`, and S3 Tables permissions for data lake workloads.