Skip to content

[📑 Docs]: Azure Emulator: Need to change role definition and role assignment articles #717

@paolosalvatori

Description

@paolosalvatori

What docs changes are you proposing?

Source: https://github.com/localstack/localstack-pro/pull/7451

Problem

Currently this sample app is only linked as a GitHub repo. Users must leave the docs to understand it.

Proposal

Currently, the Authorization service stores role definitions (548 built-ins) and role assignments but
never evaluates them, so any principal, including a managed identity with no assignment, behaves as
fully authorized and every operation on the LocalStack emulator succeeds regardless of the assigned
roles. By default, the operator identity running az CLI commands, SDKs operations, or IaC tooling is
modelled as the subscription Owner and Global Administrator of the virtual Microsoft Entra ID tenant.
As a result, the emulator hides authorization bugs that real Azure surfaces. For example, an App
Service managed identity that reads Blob Storage without the Storage Blob Data Contributor role
succeeds locally but fails on Azure.

This PR adds a generic Azure RBAC enforcement engine and wires it into the control plane (all ARM
services / resource types) and the data plane of the services that support Azure RBAC at the
data-plane level. Enforcement is opt-in and OFF by default: to enable it, set
LS_AZURE_ENFORCE_RBAC to true/yes/1 when starting the emulator (for the CLI you can use the
auto-loaded ~/.localstack/default.env profile; for Docker / Docker Compose pass it as an environment
variable). Because it must be enabled explicitly, existing setups (where Azure RBAC stays disabled)
are unaffected.

Two articles now describe behavior that is no longer accurate.

The Limitations section and Configuration should be updated in the light of the updates introduced by the PR.

What the PR changed and how

  • Opt-in, OFF by default. Enforcement is enabled by starting LocalStack with
    LS_AZURE_ENFORCE_RBAC=1. With the default (disabled), behavior is unchanged: assignments are
    stored but not evaluated and all operations succeed.
  • Control plane (ARM). A single generic gateway handler authorizes every resource-provider
    operation against the caller's role assignments, across all services. The principal needs a
    matching Actions permission (for example Reader, Contributor, Owner) at a scope that covers
    the target resource. Scope inheritance applies down the hierarchy (subscription, resource group,
    resource).
  • Data plane. Enforced for Azure Storage (Blob, Queue, Table), Azure Key Vault (vaults created
    with enableRbacAuthorization=true; secrets and certificates), and Azure Event Grid. The principal
    needs the matching DataActions, for example Storage Blob Data Reader/Contributor,
    Storage Queue Data Message Sender, Key Vault Secrets User/Secrets Officer.
  • The operator is never blocked. The identity running the Azure CLI, SDK, or IaC tooling is
    treated as Global Administrator and Owner, with full access on both planes, exactly as when
    enforcement is off. Only other principals (managed identities, workload service principals) are
    evaluated.
  • Denials match Azure. Requests without a sufficient role return the same error as real Azure:
    403 AuthorizationFailed (ARM control plane), 403 AuthorizationPermissionMismatch (Storage), and
    403 Forbidden with an inner ForbiddenByRbac code (Key Vault).
  • Validated against real Azure. The PR ships parity tests (with committed snapshots and validation
    files) that run unchanged against both LocalStack and real Azure.

Still not covered (these remain limitations): ABAC conditions, deny assignments,
management-group-scope assignments, group/transitive membership, and the data planes of Storage File,
Service Bus, and Cosmos DB. The relational databases (Azure SQL, PostgreSQL/MySQL flexible servers)
intentionally have no RBAC data actions (their data-plane authorization is Microsoft Entra database
authentication), so they are out of scope rather than a gap.

How the articles should change

Both articles currently share this Limitations block:

## Limitations

- **RBAC not enforced:** Role assignments are stored but not evaluated. All operations on LocalStack succeed regardless of assigned roles.
- **Condition-based assignments:** Attribute-based access control (ABAC) conditions in assignments are accepted at the model level but are not evaluated.
- **Deny assignments:** `Microsoft.Authorization/denyAssignments` are not supported.
- **Management group scopes:** Assignments at management group scope are not supported.

Replace it with a short enforcement section followed by a narrower limitations list:

## RBAC enforcement

By default, LocalStack stores role definitions and role assignments without evaluating them, so all
operations succeed regardless of assigned roles. This keeps existing setups working unchanged.

You can opt in to enforcement by setting `LS_AZURE_ENFORCE_RBAC` to `true`/`yes`/`1` when starting
the emulator. For the CLI (`localstack start`) you can put it in the auto-loaded
`~/.localstack/default.env` profile; for Docker / Docker Compose pass it as an environment variable.
When enabled:

- **Control plane (ARM):** every resource-provider operation is authorized against the caller's role
  assignments. The principal needs a matching `Actions` permission (for example `Reader`,
  `Contributor`, or `Owner`) at a scope that covers the target resource. Scope inheritance applies
  down the hierarchy (subscription, resource group, resource).
- **Data plane:** enforced for Azure Storage (Blob, Queue, Table), Azure Key Vault (vaults created
  with `enableRbacAuthorization=true`; secrets and certificates), and Azure Event Grid. The
  principal needs the matching `DataActions`, for example `Storage Blob Data Reader`/`Contributor`,
  `Storage Queue Data Message Sender`, `Key Vault Secrets User`/`Secrets Officer`.
- **The operator is never blocked.** The identity running the Azure CLI, SDK, or IaC tooling is
  treated as Global Administrator and Owner, with full access on both planes, exactly as when
  enforcement is off. Only other principals (managed identities, workload service principals) are
  evaluated.
- **Denials match Azure.** Requests without a sufficient role get the same error as real Azure:
  `403 AuthorizationFailed` (ARM control plane), `403 AuthorizationPermissionMismatch` (Storage),
  and `403 Forbidden` with an inner `ForbiddenByRbac` code (Key Vault).

## Limitations

- **Enforcement is opt-in.** RBAC is evaluated only when LocalStack is started with
  `LS_AZURE_ENFORCE_RBAC=1`. With the default (disabled), role assignments are stored but not
  evaluated and all operations succeed regardless of assigned roles.
- **Data-plane coverage is partial.** Enforced for Storage (Blob/Queue/Table), Key Vault, and Event
  Grid. Not yet enforced for Storage File, Service Bus (AMQP data plane), or Cosmos DB. Azure SQL
  Database and Azure Database for PostgreSQL/MySQL flexible servers do not use RBAC data actions
  (their data-plane authorization is Microsoft Entra database authentication), so they are out of
  scope for RBAC.
- **Key Vault keys.** Only the secrets and certificates data planes are enforced; the keys data
  plane is not yet implemented.
- **Condition-based assignments.** Attribute-based access control (ABAC) conditions in assignments
  are accepted at the model level but are not evaluated.
- **Deny assignments.** `Microsoft.Authorization/denyAssignments` are not supported.
- **Management group scopes.** Assignments at management group scope are not supported. Subscription,
  resource group, and resource scopes are supported, including inheritance down the hierarchy (a
  role assigned at a broader scope applies to narrower scopes beneath it).
- **Groups and transitive membership.** A role assigned to a group is not expanded to its members;
  only assignments made directly to the calling principal are evaluated.

Article-specific notes

  • The same block fits both articles. On the role-definition page, the "Key Vault keys" bullet is
    the most relevant extra (definitions for keys exist, but the keys data plane is not enforced yet).
  • On the role-assignment page, the enforcement section is the more important addition, since that
    is where readers look to understand whether an assignment actually grants or denies access.

### Code of Conduct

- [x] I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    azuredocumentationImprovements or additions to documentation
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions