IAM Policies for AI Agents
Create dedicated IAM roles with least-privilege permissions for AI coding agents. Learn to write deny policies that block destructive actions, set permission boundaries, and use condition keys to restrict access by IP, MFA, and time.
The Golden Rule: Dedicated IAM Roles for AI Agents
Never give an AI agent your personal AWS credentials or an admin role. Always create a dedicated IAM user or role specifically for the agent. This gives you a single point of control: you can audit, restrict, and revoke the agent's access without affecting your own.
Creating a Dedicated IAM Role for AI Agents
Start by creating an IAM role that your AI agent will assume. This role should have a trust policy that only allows the specific entity (your local machine, a CI/CD pipeline, etc.) to assume it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/developer-workstation"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "ai-agent-session-2026"
}
}
}
]
}
# Create the role
aws iam create-role \
--role-name AIAgentRole \
--assume-role-policy-document file://trust-policy.json \
--description "Restricted role for AI coding agents" \
--max-session-duration 3600 \
--tags Key=Purpose,Value=ai-agent Key=Environment,Value=development
# Verify the role was created
aws iam get-role --role-name AIAgentRole
Deny Policies: Explicitly Blocking Destructive Actions
The most critical IAM pattern for AI agent safety is the explicit deny. In AWS IAM, an explicit deny always overrides any allow. This means even if the agent somehow gets additional permissions (through another policy, group membership, or session policy), the deny will still block destructive actions.
Comprehensive Deny Policy for Destructive Actions
The following policy denies all common destructive actions across major AWS services:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyEC2Destruction",
"Effect": "Deny",
"Action": [
"ec2:TerminateInstances",
"ec2:DeleteVpc",
"ec2:DeleteSubnet",
"ec2:DeleteSecurityGroup",
"ec2:DeleteNatGateway",
"ec2:DeleteInternetGateway",
"ec2:DeleteRouteTable",
"ec2:DeleteVolume",
"ec2:DeleteKeyPair",
"ec2:DeleteSnapshot"
],
"Resource": "*"
},
{
"Sid": "DenyRDSDestruction",
"Effect": "Deny",
"Action": [
"rds:DeleteDBInstance",
"rds:DeleteDBCluster",
"rds:DeleteDBSnapshot",
"rds:DeleteDBClusterSnapshot",
"rds:DeleteGlobalCluster"
],
"Resource": "*"
},
{
"Sid": "DenyS3Destruction",
"Effect": "Deny",
"Action": [
"s3:DeleteBucket",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:DeleteBucketPolicy"
],
"Resource": "*"
},
{
"Sid": "DenyLambdaDestruction",
"Effect": "Deny",
"Action": [
"lambda:DeleteFunction",
"lambda:DeleteLayerVersion",
"lambda:DeleteEventSourceMapping"
],
"Resource": "*"
},
{
"Sid": "DenyEKSDestruction",
"Effect": "Deny",
"Action": [
"eks:DeleteCluster",
"eks:DeleteNodegroup",
"eks:DeleteFargateProfile"
],
"Resource": "*"
},
{
"Sid": "DenyDynamoDBDestruction",
"Effect": "Deny",
"Action": [
"dynamodb:DeleteTable",
"dynamodb:DeleteBackup"
],
"Resource": "*"
},
{
"Sid": "DenyCloudFormationDestruction",
"Effect": "Deny",
"Action": [
"cloudformation:DeleteStack",
"cloudformation:DeleteStackSet"
],
"Resource": "*"
},
{
"Sid": "DenyIAMDestruction",
"Effect": "Deny",
"Action": [
"iam:DeleteRole",
"iam:DeletePolicy",
"iam:DeleteUser",
"iam:DeleteGroup",
"iam:DeleteRolePolicy",
"iam:DeleteUserPolicy"
],
"Resource": "*"
}
]
}
# Create the policy
aws iam create-policy \
--policy-name DenyDestructiveActions \
--policy-document file://deny-destructive.json \
--description "Blocks all destructive actions for AI agents"
# Attach it to the AI agent role
aws iam attach-role-policy \
--role-name AIAgentRole \
--policy-arn arn:aws:iam::123456789012:policy/DenyDestructiveActions
Allow Policies: What AI Agents Should Be Able to Do
After blocking destructive actions, grant the agent permissions for the tasks it needs to perform. Here are practical examples:
EC2: Allow Describe and Create, Deny Terminate and Delete
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEC2ReadAndCreate",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:RunInstances",
"ec2:CreateTags",
"ec2:CreateSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:CreateSubnet",
"ec2:CreateVpc",
"ec2:CreateVolume",
"ec2:AttachVolume",
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:RebootInstances"
],
"Resource": "*"
}
]
}
S3: Allow Put and Get, Deny Delete
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3ReadWrite",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject",
"s3:ListBucket",
"s3:ListAllMyBuckets",
"s3:GetBucketLocation",
"s3:CreateBucket",
"s3:PutBucketTagging"
],
"Resource": [
"arn:aws:s3:::*",
"arn:aws:s3:::*/*"
]
}
]
}
Permission Boundaries for AI Agent Roles
A permission boundary is an advanced IAM feature that sets the maximum permissions a role can have. Even if someone accidentally attaches an AdministratorAccess policy to the AI agent role, the permission boundary will restrict it to only the actions you defined.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadAndCreateOnly",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:RunInstances",
"ec2:CreateTags",
"ec2:StartInstances",
"ec2:StopInstances",
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
"s3:ListAllMyBuckets",
"rds:Describe*",
"rds:ListTagsForResource",
"lambda:GetFunction",
"lambda:ListFunctions",
"lambda:CreateFunction",
"lambda:UpdateFunctionCode",
"lambda:InvokeFunction",
"logs:GetLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"cloudwatch:GetMetricData",
"cloudwatch:DescribeAlarms",
"sts:GetCallerIdentity"
],
"Resource": "*"
},
{
"Sid": "ExplicitDenyAllDestructive",
"Effect": "Deny",
"Action": [
"ec2:TerminateInstances",
"ec2:Delete*",
"rds:Delete*",
"s3:Delete*",
"lambda:DeleteFunction",
"dynamodb:DeleteTable",
"cloudformation:DeleteStack",
"eks:DeleteCluster",
"iam:Delete*",
"iam:Create*",
"iam:Attach*",
"iam:Detach*",
"iam:Put*"
],
"Resource": "*"
}
]
}
# Create the permission boundary policy
aws iam create-policy \
--policy-name AIAgentPermissionBoundary \
--policy-document file://permission-boundary.json
# Apply it to the role
aws iam put-role-permissions-boundary \
--role-name AIAgentRole \
--permissions-boundary arn:aws:iam::123456789012:policy/AIAgentPermissionBoundary
Condition Keys: Advanced Restrictions
IAM condition keys let you add additional constraints to policies. These are especially useful for AI agent scenarios:
Restrict by Source IP
Only allow the AI agent to make API calls from your office or VPN IP range:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyFromUnknownIPs",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"198.51.100.0/24"
]
}
}
}
]
}
Restrict by Time (Business Hours Only)
Prevent AI agents from making changes outside business hours when no one is monitoring:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideBusinessHours",
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"ec2:StopInstances",
"s3:PutObject",
"lambda:UpdateFunctionCode"
],
"Resource": "*",
"Condition": {
"DateGreaterThan": {
"aws:CurrentTime": "2026-01-01T18:00:00Z"
},
"DateLessThan": {
"aws:CurrentTime": "2026-01-02T09:00:00Z"
}
}
}
]
}
Require MFA for Sensitive Actions
Require that the session used by the AI agent was established with MFA:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyWithoutMFA",
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"rds:CreateDBInstance",
"s3:CreateBucket"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
AWS Organizations SCPs to Prevent Deletion Across Accounts
If you use AWS Organizations, you can apply Service Control Policies at the organization or OU level. SCPs restrict what IAM policies in member accounts can do — even if the account has an admin user.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyProductionDeletion",
"Effect": "Deny",
"Action": [
"ec2:TerminateInstances",
"rds:DeleteDBInstance",
"s3:DeleteBucket",
"lambda:DeleteFunction",
"eks:DeleteCluster",
"dynamodb:DeleteTable",
"cloudformation:DeleteStack"
],
"Resource": "*"
}
]
}
Testing Your IAM Policies
Always test your policies before deploying them to production. AWS provides several tools:
# Test if the AI agent role can terminate an EC2 instance
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/AIAgentRole \
--action-names ec2:TerminateInstances \
--output table
# Expected output: implicitDeny or explicitDeny
# Test if the AI agent role can describe EC2 instances
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/AIAgentRole \
--action-names ec2:DescribeInstances \
--output table
# Expected output: allowed
# Test multiple actions at once
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/AIAgentRole \
--action-names \
ec2:DescribeInstances \
ec2:RunInstances \
ec2:TerminateInstances \
s3:GetObject \
s3:DeleteBucket \
rds:DescribeDBInstances \
rds:DeleteDBInstance \
--output table
Summary
| Strategy | Purpose | When to Use |
|---|---|---|
| Dedicated IAM Role | Isolate agent permissions | Always |
| Explicit Deny Policy | Block destructive actions | Always |
| Permission Boundary | Cap maximum permissions | When multiple policies might be attached |
| IP Condition | Restrict by network | When agent runs from known IPs |
| Time Condition | Restrict by schedule | When agent should only run during business hours |
| MFA Condition | Require human verification | For sensitive create/modify actions |
| SCPs | Organization-wide guardrails | When using AWS Organizations |
Lilly Tech Systems