azure | AZ-104AZ-305 | | 28 views

Securing Azure Storage: Access Keys, SAS, and Entra ID

  • identity
  • microsoft-entra-id
  • security
  • storage

Every request to a storage account is authorised one of four ways, and the differences between them are mostly about what happens when something goes wrong. An account key that leaks grants total access to everything. A SAS token that leaks can't be individually revoked. Understanding those failure modes up front is what separates a storage account you can secure from one you can only hope about.

Access keys

Every storage account has two access keys, and each grants full administrative access to all data in the account. Anyone holding a key and the endpoint can perform any operation. Treat them as the most sensitive credential the account has.

The two keys exist specifically to make rotation possible without downtime: move clients to the second key, then regenerate the first. That's the whole design intent, a single key would mean choosing between rotating and staying up.

They're found under Security + networking > Access keys on the storage account.

Shared access signatures

A SAS is a URI granting restricted, time-bound access to specific resources without sharing the account key. A token specifies permissions, a validity window, allowed IP ranges, and allowed protocols.

The parameters worth knowing by name:

Parameter Required Purpose
SignedServices (ss) Yes Which services the SAS covers: blob, queue, table, file
SignedResourceTypes (srt) Yes Whether it applies to services, containers, or objects
SignedStart (st) No When the SAS becomes valid; defaults to when the service receives the request
SignedIP (sip) No The range of IP addresses requests are accepted from

Permissions compose in ways worth being deliberate about. Granting Read and List lets the holder enumerate and download blobs in a container and nothing else. Read allows downloading, List allows enumerating. Granting Read alone means a client that knows a blob's exact name can fetch it but can't discover what else is there.

The revocation problem

Here's the limitation that shapes everything else: SAS tokens aren't stored or named in Azure. The service validates the signature on arrival, it holds no record of the tokens you've issued.

The consequence is that a leaked token can't be individually revoked. The only way to invalidate one is to regenerate the account key that signed it. However, this invalidates every other token signed with that key at the same time. One compromised token, and every integration using that key breaks together.

That failure mode is the reason the next feature exists.

Stored access policies

A stored access policy is a container-level object defining permissions, a start time, and an expiry time. SAS tokens generated against a policy inherit its settings, and because the policy can be edited afterwards, this is the one way to change or revoke a SAS after issuing it.

That's the real distinction between the two:

  • A bare SAS token is immutable. Its settings are fixed at creation. You cannot change its expiry, narrow its permissions, or revoke it.
  • A policy-backed SAS is mutable, because the policy behind it can be changed without reissuing the token.

A container supports up to five stored access policies, which is a low enough ceiling that they need to be designed as a small set of access patterns rather than one per consumer.

Two operational notes: if you can't edit the start date, end date, or permissions while generating a SAS in the portal, it's because no stored access policy is selected. That's the immutability above, working as designed. And after changing a policy, allow a few minutes for propagation. If the change still isn't reflected, verify the token was genuinely generated using the policy rather than independently.

Microsoft Entra ID and RBAC

Account keys are simple but coarse: one credential, total access, no identity, no audit trail tying an action to a person. Microsoft Entra ID with managed identities is what Microsoft recommends instead for blob, queue, and table data. Fine-grained access for users, groups, or applications through Azure RBAC, with no secret to leak or rotate.

RBAC ensures resources in the account are reachable only by the users and applications you've granted access to, with roles scoped to the storage account.

Legacy applications tend to depend on keys because that's what existed when they were written. Anything new should be using Entra, and the migration path for the old ones is usually the highest-value security work available on a storage account.

Anonymous access

Anonymous read access is always prohibited by default, and turning it on takes two deliberate settings:

  1. The account's AllowBlobPublicAccess property must permit it.
  2. The individual container's access level must then change from Private to either Blob (anonymous read of blobs, no enumeration) or Container (anonymous read plus enumeration).

Disallowing it at the account level overrides every container setting beneath it, which makes it a genuinely effective single control. Microsoft recommends disallowing it outright unless you're specifically serving static web content.

One exception worth knowing: disallowing anonymous access doesn't affect a static website hosted in the account, because the $web container is always publicly accessible. And after changing the setting, allow up to 30 seconds for it to propagate.

The four strategies compared

Strategy Description
Microsoft Entra ID Fine-grained access for users, groups, or applications via role-based access control.
Shared Key Relies on the account access keys plus other parameters to produce an encrypted signature string, passed in the request's Authorisation header.
Shared access signatures Delegates access to a particular resource with specified permissions for a specified time interval.
Anonymous access Blob resources made public at container or blob level; read requests need no authorisation at all.

The ordering is roughly the security ordering. Entra ID first, SAS where you need to delegate to something that can't hold an identity, Shared Key where nothing else will do, and anonymous access only for content you'd be comfortable seeing indexed by a search engine.

Troubleshooting common issues

  • PublicAccessNotPermitted error message means that the request arrived without valid authorisation. Check the access key or SAS token.
  • AuthenticationFailed after key rotation means that the SAS was signed with a key that has since been rotated. Expected behaviour, and exactly what rotation is for when responding to a leak.
  • A SAS token you can't edit, no stored access policy was selected at creation.
  • Policy changes not taking effect: allow a few minutes, then confirm the token was generated against the policy.

Sources