Intermediate

Least Privilege for AI Agents

The single most effective way to prevent AI agent disasters is to limit what they can do. Never give an AI agent more permissions than it needs for the specific task at hand.

Why AI Agents Should NEVER Use Admin Credentials

Critical Rule: Never run an AI coding agent in a terminal session authenticated with admin, root, or Owner-level credentials. If your aws sts get-caller-identity returns an admin role, the agent can delete anything in your account. This is the number one cause of AI agent cloud disasters.

Most developers authenticate their local terminal with broad permissions for convenience. When you invoke an AI agent in that terminal, it inherits those permissions. The fix is simple: create dedicated, restricted credentials for agent sessions.

Creating Dedicated Service Accounts

  1. Create a Separate IAM Entity for Agent Use

    Do not reuse your personal credentials. Create a dedicated IAM user or role specifically for AI agent sessions with a clear naming convention like ai-agent-readonly or ai-agent-deploy-staging.

  2. Scope to Environment

    Create separate credentials for each environment. An agent working on staging should never have credentials that can touch production resources.

  3. Use Named Profiles

    Configure AWS CLI profiles, Azure subscriptions, or GCP configurations so you can explicitly switch contexts before launching an agent session.

AWS - Switching to a restricted profile before running an agent
# Set the agent to use a restricted profile
export AWS_PROFILE=ai-agent-staging-readonly

# Verify the identity (should show restricted role)
aws sts get-caller-identity
# {
#   "Arn": "arn:aws:iam::123456789012:role/ai-agent-staging-readonly"
# }

# Now launch your AI coding agent in this terminal
# The agent inherits ONLY the staging read-only permissions

Read-Only Access Patterns

For many AI agent tasks (code review, debugging, log analysis, architecture exploration), read-only access is sufficient:

AWS - Read-Only IAM Policy for AI Agents
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowReadOnly",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "s3:GetObject",
        "s3:ListBucket",
        "rds:Describe*",
        "logs:GetLogEvents",
        "logs:FilterLogEvents",
        "cloudwatch:GetMetricData",
        "iam:GetRole",
        "iam:ListRoles"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ExplicitlyDenyDestructive",
      "Effect": "Deny",
      "Action": [
        "ec2:TerminateInstances",
        "ec2:DeleteSecurityGroup",
        "s3:DeleteBucket",
        "s3:DeleteObject",
        "rds:DeleteDBInstance",
        "rds:DeleteDBCluster",
        "iam:Delete*",
        "iam:Put*",
        "cloudformation:DeleteStack"
      ],
      "Resource": "*"
    }
  ]
}

Time-Limited Credentials and Session Tokens

Even restricted credentials should be time-limited. If an agent session goes wrong, the damage window is capped:

AWS - Assume role with 1-hour session limit
# Assume a restricted role with a 1-hour session
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/ai-agent-deploy \
  --role-session-name "claude-code-session" \
  --duration-seconds 3600

# Export the temporary credentials
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."

# These credentials automatically expire after 1 hour
GCP - Time-limited access with impersonation
# Create a service account for agent use
gcloud iam service-accounts create ai-agent-deployer \
  --display-name="AI Agent Deployer (Staging Only)"

# Generate a short-lived access token (1 hour max)
gcloud auth print-access-token \
  --impersonate-service-account=ai-agent-deployer@project.iam.gserviceaccount.com \
  --lifetime=3600s

Permission Boundaries and Guardrails

Permission boundaries act as a ceiling on what any policy can grant. Even if an agent somehow escalates its permissions, the boundary prevents exceeding safe limits:

AWS - Permission Boundary that blocks all delete operations
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAllExceptDestructive",
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    },
    {
      "Sid": "DenyAllDestructiveActions",
      "Effect": "Deny",
      "Action": [
        "ec2:Terminate*",
        "rds:Delete*",
        "s3:Delete*",
        "dynamodb:Delete*",
        "cloudformation:Delete*",
        "eks:Delete*",
        "lambda:Delete*",
        "elasticache:Delete*",
        "es:Delete*",
        "iam:Delete*"
      ],
      "Resource": "*"
    }
  ]
}

Example IAM Policies by Cloud

Azure - Custom Role: Deploy but No Delete
{
  "Name": "AI Agent Deployer - No Delete",
  "Description": "Allows resource creation and updates but denies all delete operations",
  "Actions": [
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Compute/virtualMachines/write",
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Storage/storageAccounts/write",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write"
  ],
  "NotActions": [
    "*/delete",
    "Microsoft.Authorization/roleAssignments/write",
    "Microsoft.Authorization/roleDefinitions/write"
  ],
  "AssignableScopes": [
    "/subscriptions/{subscription-id}/resourceGroups/staging-rg"
  ]
}
GCP - Custom Role: Provisioning Without Deletion
# Create custom role that allows create/update but not delete
gcloud iam roles create aiAgentDeployer \
  --project=my-project \
  --title="AI Agent Deployer" \
  --description="Create and update resources, no delete" \
  --permissions=compute.instances.create,\
compute.instances.get,\
compute.instances.list,\
compute.instances.update,\
compute.instances.setMetadata,\
storage.buckets.create,\
storage.buckets.get,\
storage.buckets.list,\
storage.objects.create,\
storage.objects.get,\
storage.objects.list

# Note: compute.instances.delete is NOT included
# Note: storage.buckets.delete is NOT included
Best Practice: Start with zero permissions and add only what the agent needs for the specific task. It is always safer to grant additional permissions later than to revoke them after damage has been done.
💡
Next Up: Least privilege is your first line of defense, but some tasks genuinely require destructive permissions. The next lesson covers human-in-the-loop controls that add approval gates for those operations.