Intermediate

RBAC and Custom Roles for AI Agents

Azure Role-Based Access Control (RBAC) is your first line of defense. By creating custom roles that explicitly exclude destructive actions, you ensure AI agents can only perform safe operations — no matter what commands they attempt to run.

Azure RBAC Fundamentals for Agent Access

Azure RBAC works by assigning roles to security principals (users, groups, service principals, managed identities) at a specific scope (management group, subscription, resource group, or resource). Each role is a collection of allowed and denied actions.

💡
Key Concept: Azure RBAC evaluates permissions additively for allow actions — if any assigned role grants an action, the principal can perform it. However, deny assignments always take precedence over allow assignments. This is critical for AI agent safety: you can deny destructive actions even if another role grants them.

Built-in Roles: Reader vs Contributor vs Owner

Role Read Create/Update Delete AI Agent Suitability
Reader Yes No No Safe but too limited for provisioning
Contributor Yes Yes Yes Too permissive — allows delete operations
Owner Yes Yes Yes Never use for AI agents — can also manage access
Warning: The Contributor role is the most common mistake when granting AI agent access. It seems reasonable — "the agent needs to create resources" — but Contributor includes full delete permissions on every resource type. Always create a custom role instead.

Creating Custom Roles That Exclude Delete Actions

Custom roles let you grant exactly the permissions an AI agent needs while explicitly excluding destructive operations. Here is a JSON role definition for an "AI Agent Safe Deployer" role:

ai-agent-safe-deployer-role.json
{
  "Name": "AI Agent Safe Deployer",
  "IsCustom": true,
  "Description": "Allows AI agents to read and create Azure resources but denies all delete operations",
  "Actions": [
    "*/read",
    "Microsoft.Compute/virtualMachines/write",
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Compute/virtualMachines/restart/action",
    "Microsoft.Network/virtualNetworks/write",
    "Microsoft.Network/networkSecurityGroups/write",
    "Microsoft.Network/publicIPAddresses/write",
    "Microsoft.Network/networkInterfaces/write",
    "Microsoft.Storage/storageAccounts/write",
    "Microsoft.Storage/storageAccounts/listKeys/action",
    "Microsoft.Web/sites/write",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Sql/servers/write",
    "Microsoft.Sql/servers/databases/write",
    "Microsoft.ContainerService/managedClusters/write",
    "Microsoft.Resources/subscriptions/resourceGroups/write"
  ],
  "NotActions": [
    "*/delete",
    "Microsoft.Compute/virtualMachines/deallocate/action",
    "Microsoft.Compute/virtualMachines/powerOff/action",
    "Microsoft.Resources/subscriptions/resourceGroups/delete",
    "Microsoft.Authorization/*/write",
    "Microsoft.Authorization/*/delete",
    "Microsoft.Authorization/roleAssignments/write",
    "Microsoft.Authorization/roleDefinitions/write"
  ],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/YOUR-SUBSCRIPTION-ID"
  ]
}
Creating and assigning the custom role via Azure CLI
# Create the custom role
az role definition create --role-definition @ai-agent-safe-deployer-role.json

# Create a Managed Identity for the AI agent
az identity create \
  --name ai-agent-identity \
  --resource-group rg-shared-infra

# Assign the custom role to the Managed Identity
az role assignment create \
  --assignee $(az identity show --name ai-agent-identity \
    --resource-group rg-shared-infra --query principalId -o tsv) \
  --role "AI Agent Safe Deployer" \
  --scope /subscriptions/YOUR-SUBSCRIPTION-ID

Deny Assignments for Destructive Operations

Azure deny assignments explicitly block specific actions, even if a role grants them. While deny assignments are primarily managed through Azure Blueprints, you can also create them via the REST API:

💡
How Deny Assignments Work: When Azure evaluates permissions, it checks deny assignments first. If a deny assignment matches, the action is blocked regardless of any role assignments. This makes deny assignments the strongest form of access control in Azure.
Deny assignment JSON structure (applied via Blueprints or REST API)
{
  "properties": {
    "denyAssignmentName": "Deny Agent Delete Operations",
    "description": "Prevents AI agent identities from performing delete operations",
    "permissions": [
      {
        "actions": [
          "*/delete",
          "Microsoft.Resources/subscriptions/resourceGroups/delete"
        ],
        "notActions": [],
        "dataActions": [],
        "notDataActions": []
      }
    ],
    "scope": "/subscriptions/YOUR-SUBSCRIPTION-ID",
    "doNotApplyToChildScopes": false,
    "principals": [
      {
        "id": "AI-AGENT-MANAGED-IDENTITY-PRINCIPAL-ID",
        "type": "ServicePrincipal"
      }
    ],
    "excludePrincipals": []
  }
}

Managed Identities for AI Agent Workloads

Managed Identities eliminate the need for storing credentials in environment variables or configuration files. There are two types:

Type Lifecycle Best For
System-assigned Tied to the Azure resource (VM, App Service, etc.) Agent running on a single Azure resource
User-assigned Independent resource, can be shared across resources Agent identity used across multiple compute resources
Setting up a Managed Identity for an AI agent VM
# Enable system-assigned managed identity on a VM
az vm identity assign \
  --resource-group rg-ai-agents \
  --name vm-ai-agent-runner

# Or create a user-assigned identity for sharing across VMs
az identity create \
  --name uai-ai-agent \
  --resource-group rg-shared-infra

# Assign the safe deployer role to the managed identity
PRINCIPAL_ID=$(az identity show \
  --name uai-ai-agent \
  --resource-group rg-shared-infra \
  --query principalId -o tsv)

az role assignment create \
  --assignee $PRINCIPAL_ID \
  --role "AI Agent Safe Deployer" \
  --scope /subscriptions/YOUR-SUBSCRIPTION-ID

Conditional Access Policies

Azure AD Conditional Access can add additional guardrails based on context — location, device compliance, risk level, and more:

  1. Restrict Agent Access by Network Location

    Configure Conditional Access to only allow the AI agent's service principal to authenticate from specific IP ranges (e.g., your CI/CD pipeline's static IPs or your VNet's NAT gateway).

  2. Require Compliant Devices

    If agents run on developer workstations, require that the device is Intune-compliant. This prevents agents from operating on compromised or unmanaged machines.

  3. Sign-in Risk Assessment

    Azure AD Identity Protection can detect unusual sign-in patterns. If an agent's service principal suddenly authenticates from an unexpected location, Conditional Access can block the session.

PIM (Privileged Identity Management) for Just-in-Time Access

Azure AD PIM allows you to grant time-limited, approval-required role activations. This is ideal for cases where an AI agent occasionally needs elevated permissions:

PIM workflow for AI agent elevated access
# Step 1: AI agent has "Reader" role by default (safe baseline)
# Step 2: When delete permission is needed, a human activates PIM

# Using Azure CLI to check eligible role assignments
az rest --method GET \
  --url "https://management.azure.com/subscriptions/SUB-ID/providers/Microsoft.Authorization/roleEligibilityScheduleInstances?api-version=2020-10-01"

# PIM activation via REST API (would be triggered by human approval)
az rest --method PUT \
  --url "https://management.azure.com/subscriptions/SUB-ID/providers/Microsoft.Authorization/roleAssignmentScheduleRequests/REQUEST-ID?api-version=2020-10-01" \
  --body '{
    "properties": {
      "principalId": "AGENT-PRINCIPAL-ID",
      "roleDefinitionId": "/subscriptions/SUB-ID/providers/Microsoft.Authorization/roleDefinitions/CONTRIBUTOR-ROLE-ID",
      "requestType": "SelfActivate",
      "scheduleInfo": {
        "startDateTime": "2026-03-20T10:00:00Z",
        "expiration": {
          "type": "AfterDuration",
          "duration": "PT1H"
        }
      },
      "justification": "Approved cleanup of deprecated dev resources"
    }
  }'

# After 1 hour, the elevated role automatically deactivates
# Agent returns to Reader-only access
Best Practice: Configure PIM with the following settings for AI agent roles: maximum activation duration of 1 hour, require approval from a security team member, require justification for activation, and send notification emails on activation. This ensures every elevation is time-limited, justified, and auditable.