---
cuppy_hub: azure
cuppy_path: reference/storage/network-and-firewall.md
cuppy_section: docs
cuppy_doc: X03P-XYC6
cuppy_doc_uuid: 4bf377c3-d4bd-4e8e-b229-8b5bf25c939d
cuppy_permalink: https://cuppy.io/azure/d/X03P-XYC6
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/reference/storage/network-and-firewall
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 96aa0b1a0a3540ba0ac6c4effce61529b9f2a6454d7ba3504b67dfb2ea1c0fcf
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Storage network access

**Network rules decide whether a request reaches the account at all; authorization comes after.** A request the network refuses gets 403 `AuthorizationFailure` `This request is not authorized to perform this operation.`, whatever role the caller holds. Firewall rules apply to the **data plane** only: control-plane calls (create a container through ARM, change settings, list keys) aren't filtered, which is why the portal can list containers it can't open.

## The settings

| Property | Values | Effect |
|---|---|---|
| `publicNetworkAccess` | `Enabled`, `Disabled`, `SecuredByPerimeter` | `Disabled`: only private endpoints (and previously configured resource instances and trusted-service exceptions, which **stay in effect**). `SecuredByPerimeter`: the network security perimeter's rules decide |
| `networkAcls.defaultAction` | `Allow` (spec default), `Deny` | `Deny` turns the firewall on: only listed IPs, subnets, resource instances and bypassed services get in |
| `networkAcls.bypass` | `AzureServices` (default), `Logging`, `Metrics`, `None` | Exceptions for trusted services and for reading logs and metrics |
| `networkAcls.ipRules` | Public IPv4 addresses or CIDR | See restrictions below |
| `networkAcls.virtualNetworkRules` | Subnet IDs | The subnet needs the `Microsoft.Storage` service endpoint; any subscription or tenant |
| `networkAcls.resourceAccessRules` | Resource ID + tenant ID | Admits one Azure resource (or all of a type in a tenant, subscription or group) through the firewall |

**A template that sets `publicNetworkAccess: Disabled` but leaves `defaultAction: Allow`** is closed (public network access wins), but Defender for Storage and Advisor still flag it. Set `defaultAction: Deny` too; the portal, CLI and PowerShell do that for you.

## IP rules: restrictions that cause most 403s

- **Public internet addresses only.** RFC 1918 ranges (10.x, 172.16–31.x, 192.168.x) aren't allowed.
- **No /31 or /32 prefixes:** add those addresses individually. IPv4 only in Learn's rules (CLI 2.91 shows `--ipv6-address` as preview).
- **IP rules have no effect on callers in the same Azure region.** Same-region services reach the account over private Azure addresses, so you can't admit (or block) App Service, Functions or a VM in that region by its public outbound IP. Use a **VNet rule** (VNet-integrated app, subnet with the service endpoint) or a **private endpoint**.
- Clients in the **paired region** inside a VNet with a service endpoint also bypass IP rules.

Field report, consistent with this: a 403 `AuthorizationFailure` where the logs showed the caller as a 10.x address that no IP rule could cover.

## Who else gets in

- **Resource instance rules** admit a resource's network traffic, not its data: the resource's **system-assigned managed identity** still needs a data role.
- **Trusted Azure services** (`bypass: AzureServices`): a fixed list of services registered in **the same Entra tenant**, for listed operations (Azure Backup, Data Box, Data Explorer, Event Grid, Event Hubs Capture, File Sync and others). App Service and Functions aren't on it.
- **SAS IP restrictions** (`sip`) narrow a SAS; they never grant access the firewall denies.

**Fixed limits** per account: 400 IP rules, 400 virtual network rules, 200 resource instance rules.

## Private endpoints

- **One private endpoint per target sub-resource**: Blobs, Data Lake Storage, Files, Queues, Tables or Static Websites. For read access to a geo-redundant secondary, a separate endpoint for the secondary instance; failover needs none, the endpoint follows the new primary.
- **ADLS Gen2 needs both `blob` and `dfs`.** Some operations (managing ACLs, creating and deleting directories) need the `dfs` endpoint.
- DNS: the public name gets a CNAME to `<acct>.privatelink.<service>.core.windows.net`; the private DNS zone (`privatelink.blob.core.windows.net`, `privatelink.dfs.core.windows.net`, `privatelink.file.core.windows.net`, `privatelink.queue.core.windows.net`, `privatelink.table.core.windows.net`) must be linked to every VNet that resolves it, or custom DNS must forward to it. Clients keep using the normal `<acct>.blob.core.windows.net` URL.
- Private endpoints aren't affected by firewall rules. Don't cache the account's IP address, and honour DNS TTLs.
- DNS failures look like timeouts, not 403s: the networking family covers diagnosis.

## Network security perimeter

`publicNetworkAccess: SecuredByPerimeter` puts the account under a perimeter's inbound and outbound rules. In **Enforced** mode only HTTPS works: NFS, SMB and SFTP are blocked. Not supported with a perimeter: **object replication**, **static website**, **Azure Backup**, unmanaged disks. For customer-managed keys the Key Vault must be reachable from inside the perimeter. In **Transition** mode the firewall still applies as a fallback, so success there doesn't prove the perimeter allows the traffic.

## CLI

```bash
# Turn the firewall on, then admit a subnet (service endpoint required) and a public IP
az storage account update -n <acct> -g <rg> --default-action Deny --bypass AzureServices
az storage account network-rule add -n <acct> -g <rg> --vnet-name <vnet> --subnet <subnet>
az storage account network-rule add -n <acct> -g <rg> --ip-address <public-ip>
az storage account network-rule list -n <acct> -g <rg>
```

These change what can reach the account's data: confirm with your human before running them on a live account.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 107 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/azure/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
