AZ-104 Refresher Chapter 7 Β· Storage

Chapter 7

Storage: accounts, access, networking, Blob and Files

πŸ“– Theory 55 minπŸ›  Lab 30 minStorage Β· 15–20%

Storage is one of the five exam areas on its own, and it has many small settings that each get a question. Take this chapter in two sittings if you like: accounts, redundancy and access first, then networking, Blob and Files. In the lab, your storage account becomes reachable from the web VMs through a service endpoint and a private endpoint.

Part A

Theory

Storage accounts

A storage account is the container for four data services, each with its own endpoint:

The account name becomes part of a public DNS name, so it must be globally unique, 3 to 24 characters, lowercase letters and numbers only.

Account types

TypePerformanceServicesRedundancy
Standard general-purpose v2Standard (HDD-based)Blob, Files, Queues, TablesLRS, ZRS, GRS, RA-GRS, GZRS, RA-GZRS
Premium block blobsPremium (SSD)Block and append blobsLRS, ZRS
Premium file sharesPremium (SSD)Files (SMB and NFS)LRS, ZRS
Premium page blobsPremium (SSD)Page blobs onlyLRS, ZRS

Standard GPv2 is the default answer unless the question asks for low latency (Premium) or NFS file shares (Premium file shares). The performance tier can't be changed after creation; you'd create a new account and copy the data.

Settings worth knowing

Redundancy

Azure Storage always keeps at least three copies of your data. The redundancy option decides where those copies are:

LRS1 datacenter Β· 11 nines primary region Β· 1 DC Lost if the datacenteris lost ZRS3 zones Β· 12 nines primary region Survives a zone failure,synchronous writes GRS / RA-GRS16 nines primary Β· LRS async paired region Β· LRS RA-: read the secondaryat <acct>-secondary GZRS / RA-GZRS16 nines primary Β· ZRS paired region Β· LRS Zone + region protection
Green: synchronous copies in the primary region. Orange: asynchronous copies in the secondary (paired) region.

How to choose:

Failover to the secondary region is customer-initiated (you start it). Because replication is asynchronous, the most recent writes may be lost; the Last Sync Time property tells you up to when data is safe. After an unplanned failover the account is LRS in the new primary region until you re-enable geo-redundancy.

You can change redundancy later. Moving between LRS, GRS and RA-GRS is a simple setting. Adding zone redundancy (LRS β†’ ZRS) is a conversion that runs in the background, or a manual migration.

Exam trap

"Data must be readable even if the primary region is down, without waiting for a failover." Only RA-GRS or RA-GZRS qualify. Also: Premium accounts support only LRS and ZRS.

Authorising access to data

There are four ways to get at data in a storage account. Know when to use which:

MethodHow it worksUse it for
Microsoft Entra ID (recommended)Users, groups, managed identities with data roles like Storage Blob Data ReaderApps with managed identity, admins, people
Shared Key (account keys)Two 512-bit keys that give full access to everything in the accountLegacy tools; avoid where possible
Shared access signature (SAS)A signed URL token with limited permissions and an expiryGiving temporary, limited access to a client or partner
Anonymous public readNo authentication at all, per containerPublic website assets only

Access keys

Every account has two keys (key1 and key2) so you can rotate without downtime:

  1. Switch all apps to key2.
  2. Regenerate key1.
  3. Switch apps back to key1, then regenerate key2 (next rotation).

Better still: store keys in Key Vault, set a key expiration policy with reminders, or disable Shared Key altogether and use Entra ID. Remember: regenerating a key invalidates every SAS signed with it.

Shared access signatures

A SAS is a query string you append to a URL. It has three flavours:

The parameters in a SAS token you should be able to read:

?sv=2022-11-02          signed version
&ss=bf  &srt=co          services (blob, file) and resource types (container, object) β€” account SAS
&sp=rl                   permissions: read, list (also a, c, w, d …)
&st=2026-11-13T09:00Z    start
&se=2026-11-14T09:00Z    expiry
&sip=198.51.100.10       allowed client IP(s)
&spr=https               allowed protocol
&si=read-1day            stored access policy (if used)
&sig=…                   the signature

Stored access policies

The problem with an ad-hoc SAS is that you can't revoke it, except by rotating the key that signed it (which breaks every other SAS too). A stored access policy fixes that:

Exam trap

"Partners use SAS tokens. You must be able to revoke a partner's access without affecting others." Give each partner a SAS based on their own stored access policy. Rotating the account key would revoke everyone. (User delegation SAS can't use stored access policies.)

Networking: firewall, service endpoints and private endpoints

By default a storage account accepts connections from any network (they still need authorisation). The Networking blade lets you restrict that. Public network access has three settings:

Some details that come up in questions:

Service endpoint snet-web vm-web1 Microsoft.Storage on backbone storagepublic IP20.x.x.x β€’ DNS still resolves to the public IP β€’ Firewall allows the subnet by name β€’ Free Β· only from that VNet (not on-prem) β€’ Per service, whole region (all accounts) Private endpoint vnet-spoke vm-web1 snet-dataPE NIC10.20.2.4 storagefile sub-resource β€’ DNS: privatelink.file.core.windows.net β†’ 10.20.2.4 β€’ Works from peered VNets and on-premises β€’ One account + one sub-resource per PE β€’ Costs per hour and per GB Β· public access can be off
Service endpoints secure the route to a public endpoint; private endpoints bring the service into your network.

Service endpoints

You enable a service endpoint (e.g. Microsoft.Storage) on a subnet. Traffic from that subnet to Azure Storage then travels over the Azure backbone and arrives with the subnet's identity, so the storage firewall can say "allow snet-web". The storage account keeps its public IP. Service endpoints are free, but don't help on-premises clients. Service endpoint policies can restrict a subnet to specific storage accounts (prevents data exfiltration to other accounts).

Private endpoints

A private endpoint is a NIC in your subnet with a private IP that maps to one sub-resource (blob, file, queue, table, dfs, web) of one storage account. It's part of Azure Private Link, which works the same for SQL, Key Vault, App Service and many others.

DNS is the part people get wrong. The public name staz104xx01.file.core.windows.net becomes a CNAME to staz104xx01.privatelink.file.core.windows.net. For clients to get the private IP, a private DNS zone privatelink.file.core.windows.net with an A record must be linked to their VNet (or on-premises DNS must forward to Azure DNS, e.g. via the DNS Private Resolver). Without it, clients resolve the public IP and get blocked by the firewall.

Exam trap

"On-premises servers connected via VPN must reach a storage account privately." Service endpoints don't work from on-premises. Use a private endpoint plus DNS forwarding.

Encryption

All data in Azure Storage is encrypted at rest with 256-bit AES (Storage Service Encryption). You can't turn it off. What you choose is who manages the key:

Two more options: encryption scopes let different containers or blobs use different keys in one account, and infrastructure encryption adds a second layer of encryption (must be enabled at account creation).

Blob storage

Blobs live in containers inside the account. There are three blob types: block blobs (files, most data), append blobs (logs that only grow) and page blobs (random-access disks, like old unmanaged VHDs).

Access tiers

Block blobs have an access tier that trades storage cost against access cost:

Hotfrequent accessno minimum Coolinfrequentmin 30 days Coldraremin 90 days Archiveoffline Β· rehydrate firstmin 180 days Storage cost per GB goes down →← access and read cost go up
Moving or deleting a blob before its minimum duration costs an early deletion fee for the remaining days.

Lifecycle management

A lifecycle management policy moves or deletes blobs automatically. It's a JSON list of rules, each with filters (blob type, prefix like logs/, blob index tags) and actions on the base blob, snapshots and versions:

{ "rules": [ { "name": "logs-tiering", "enabled": true, "type": "Lifecycle",
  "definition": {
    "filters": { "blobTypes": [ "blockBlob" ], "prefixMatch": [ "images/logs/" ] },
    "actions": {
      "baseBlob": {
        "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
        "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
        "delete":        { "daysAfterModificationGreaterThan": 365 } },
      "version": { "delete": { "daysAfterCreationGreaterThan": 30 } } } } } ] }

Note that prefixMatch starts with the container name. Rules can also use daysAfterLastAccessTimeGreaterThan if you enable last access time tracking. The policy runs once a day, so changes can take up to 24–48 hours to show.

Data protection for blobs

Object replication

Object replication copies block blobs asynchronously from a container in one account to a container in another account (any region). Uses: lower read latency in another region, or a copy for analytics. Requirements: versioning on both accounts and change feed on the source. Hierarchical namespace isn't supported. You create a replication policy with rules (source container β†’ destination container, optional prefix filter, and whether to copy existing blobs).

Azure Files

Azure Files offers fully managed file shares over SMB 3.x (Windows, Linux, macOS; port 445) and NFS 4.1 (Linux; Premium only, private network only). Use it to replace file servers, share config between VMs, or "lift and shift" apps that expect a share.

Port 445 is often blocked by ISPs, so on-premises access usually goes over VPN/ExpressRoute with a private endpoint, or through Azure File Sync, which caches the share on a Windows Server and can tier cold files to the cloud.

Identity-based access for Azure Files

With SMB you can mount a share with the storage account key (full access, like being root) or with user identities. Identity-based access has two layers, like a Windows file server:

  1. Enable an identity source on the storage account (one at a time):
    • On-premises AD DS: the storage account is joined to your domain (with the AzFilesHybrid PowerShell module). Users must be synced to Entra ID.
    • Microsoft Entra Domain Services: managed domain in Azure.
    • Microsoft Entra Kerberos: for hybrid users on Entra-joined or hybrid-joined clients, without line of sight to a domain controller.
  2. Share-level permissions with Azure RBAC roles: Storage File Data SMB Share Reader, Contributor, Elevated Contributor (can also change NTFS permissions). You can also set a default share-level permission for all authenticated users.
  3. Directory and file-level permissions: normal Windows ACLs (NTFS), set with File Explorer or icacls.

Effective access is the most restrictive combination of share-level and file-level permissions.

Exam trap

"Users get access denied on the share even though NTFS permissions allow them." Check the share-level RBAC role first: without one (and without a default share-level permission), nobody gets in with their identity.

Tools for moving data

AZ-305 link

AZ-305 "design data storage" questions combine everything in this chapter: which redundancy for a given RPO/availability need, which tier and lifecycle for cost, which access method (managed identity + RBAC over keys), and private endpoints + DNS for network isolation. Learn the redundancy figure by heart.

Self-check

1. A storage account must survive a zone outage and a regional disaster, and apps must read from the secondary region at any time. What do you choose?

C. Zones + secondary region + read access.

2. You gave a partner a service SAS based on stored access policy "partner-a". How do you revoke it immediately without affecting other partners?

A. Regenerating keys would revoke every SAS signed with them.

3. VMs in a VNet reach a storage account through a private endpoint, but nslookup returns a public IP. What's missing?

D. Without the private DNS zone link, the CNAME chain resolves to the public endpoint.

4. Which tier makes a blob unreadable until it is rehydrated?

B. Archive is offline; Cold is online but expensive to read.

5. What must be enabled to configure object replication?

C. HNS isn't supported for object replication.

6. Users with Entra Kerberos authentication can mount a share but can't open any folder. NTFS ACLs grant them Modify. What's the likely cause?

A. Both layers must allow access. (Strictly, without a share-level role they usually can't mount either, which is exactly why this is the first thing to check.)

Part B

Lab: a protected, private storage account

You create staz104xx01, protect its data, share it with a SAS, automate tiering, and finally close it to the internet so that only snet-web (service endpoint), a private endpoint in snet-data and your browser can reach it. The order matters: the firewall comes last so that your Linux VM can still upload data in the earlier steps. Paste the variables first:

RG=rg-az104-lab; LOC=westeurope; LOC2=northeurope; INIT=xx
ST=staz104${INIT}01; MYIP=$(curl -s https://api.ipify.org)
mkdir -p ~/az104 && cd ~/az104
  1. Task

    Create the storage account

    Create staz104xx01 in rg-az104-lab: Standard general-purpose v2, LRS, default tier Hot, TLS 1.2 minimum, no anonymous blob access, public network access from all networks (for now).

    Done when
    • The account exists. On its Overview, find the endpoints for blob and file.
    Solution Β· Portal

    Create a resource β†’ Storage account. Basics: name, region, primary service Azure Blob Storage or Azure Data Lake Storage Gen 2 (or leave empty), performance Standard, redundancy LRS. Advanced: untick Allow enabling anonymous access on individual containers, minimum TLS 1.2, access tier Hot. Review + create.

    Solution Β· Azure CLI
    az storage account create -g $RG -n $ST -l $LOC --sku Standard_LRS --kind StorageV2 \
      --access-tier Hot --min-tls-version TLS1_2 --allow-blob-public-access false
    STID=$(az storage account show -g $RG -n $ST --query id -o tsv)
    az storage account show -g $RG -n $ST --query primaryEndpoints
  2. Task

    Survive a regional disaster

    Change the redundancy so the data survives the loss of the whole region and can be read from the other region at any time, without a failover.

    Done when
    • The account shows the new redundancy, a secondary location, and a secondary blob endpoint ending in -secondary.blob.core.windows.net.
    Solution Β· Portal

    Storage account β†’ Data management β†’ Redundancy β†’ Read-access geo-redundant storage (RA-GRS) β†’ Save. The page shows the primary and secondary regions.

    Solution Β· Azure CLI
    az storage account update -g $RG -n $ST --sku Standard_RAGRS
    az storage account show -g $RG -n $ST --query "{sku:sku.name, secondary:secondaryLocation, ep:secondaryEndpoints.blob}"
  3. Task

    Give yourself data access, then protect the blobs

    You're Owner of the subscription. Make sure you can upload blobs with your Entra identity (not a key). Then turn on versioning, blob soft delete (7 days) and container soft delete (7 days), and create a private container images.

    Upload a small text file hello.txt, change it and upload it again, then delete it and get it back.

    Done when
    • hello.txt exists again and has two versions.
    • You can explain why Owner alone wasn't enough.
    Hint

    The role you need is a data role on the storage account: Storage Blob Data Contributor. Role assignments can take a few minutes.

    Solution Β· Portal
    1. Storage account β†’ Access control (IAM) β†’ Add role assignment β†’ Storage Blob Data Contributor β†’ yourself.
    2. Data management β†’ Data protection: tick Enable versioning for blobs, Enable soft delete for blobs (7), Enable soft delete for containers (7). Save.
    3. Data storage β†’ Containers β†’ + Container: images, private.
    4. Open images β†’ Upload hello.txt; change it locally and upload again with Overwrite. The blob's Versions tab shows two.
    5. Delete it, turn on Show deleted blobs, right-click β†’ Undelete.

    Owner is a control-plane role. Reading/writing blob data with Entra ID needs a data-plane role (chapter 2).

    Solution Β· Azure CLI
    ME=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --assignee-object-id $ME --assignee-principal-type User \
      --role "Storage Blob Data Contributor" --scope $STID
    
    az storage account blob-service-properties update -g $RG -n $ST --enable-versioning true \
      --enable-delete-retention true --delete-retention-days 7 \
      --enable-container-delete-retention true --container-delete-retention-days 7
    
    az storage container create --account-name $ST -n images --auth-mode login
    echo "version 1" > hello.txt; az storage blob upload --account-name $ST -c images -n hello.txt -f hello.txt --auth-mode login --overwrite
    echo "version 2" > hello.txt; az storage blob upload --account-name $ST -c images -n hello.txt -f hello.txt --auth-mode login --overwrite
    az storage blob delete   --account-name $ST -c images -n hello.txt --auth-mode login
    az storage blob undelete --account-name $ST -c images -n hello.txt --auth-mode login
    az storage blob list --account-name $ST -c images --include v --auth-mode login \
      --query "[].{name:name, version:versionId, current:isCurrentVersion}" -o table
  4. Task

    Share with a SAS you can revoke

    Create a stored access policy read-1day on images that allows read and list for one day. Create a SAS based on it, download hello.txt with curl using only that URL, then revoke the SAS without touching the account keys.

    Done when
    • The first curl returns the file content.
    • After revoking, the same URL returns 403 (allow up to 30 seconds).
    Solution Β· Portal
    1. Container images β†’ Settings β†’ Access policy β†’ Add policy: identifier read-1day, permissions Read, List, expiry tomorrow. Save.
    2. Open hello.txt β†’ Generate SAS β†’ signing method Account key, Stored access policy read-1day β†’ Generate. Copy the Blob SAS URL and curl it on your Linux VM.
    3. Back to Access policy, delete read-1day, Save, and curl again.
    Solution Β· Azure CLI
    EXP=$(date -u -d '+1 day' +%Y-%m-%dT%H:%MZ)
    az storage container policy create --account-name $ST -c images -n read-1day --permissions rl --expiry $EXP
    SAS=$(az storage blob generate-sas --account-name $ST -c images -n hello.txt --policy-name read-1day -o tsv)
    curl -s "https://$ST.blob.core.windows.net/images/hello.txt?$SAS"
    
    az storage container policy delete --account-name $ST -c images -n read-1day
    sleep 30; curl -s -o /dev/null -w "%{http_code}\n" "https://$ST.blob.core.windows.net/images/hello.txt?$SAS"
  5. Task

    Bulk upload with AzCopy and automate tiering

    Create five small log files and upload them with AzCopy (using your Entra identity, no SAS) to images/logs/. Then add a lifecycle management rule for blobs under that prefix: Cool after 30 days, Archive after 90, delete after 365 since last modification, and delete previous versions after 30 days.

    Done when
    • The five files are in images/logs/.
    • The Lifecycle management blade shows your rule (its effect only shows after a day, of course).
    Hint

    AzCopy can reuse your az login: export AZCOPY_AUTO_LOGIN_TYPE=AZCLI. The lifecycle prefix includes the container name.

    Solution Β· Portal (lifecycle)

    Storage account β†’ Data management β†’ Lifecycle management β†’ Add a rule: name logs-tiering, scope Limit blobs with filters, blob type Block, subtypes Base blobs and Versions. Base blobs: Last modified more than 30 days β†’ Move to cool; + 90 β†’ Move to archive; + 365 β†’ Delete. Versions: more than 30 days β†’ Delete. Filter set: prefix images/logs/.

    Solution Β· Azure CLI
    mkdir -p logs; for i in 1 2 3 4 5; do echo "log line $i $(date)" > logs/app$i.log; done
    export AZCOPY_AUTO_LOGIN_TYPE=AZCLI
    azcopy copy "logs" "https://$ST.blob.core.windows.net/images/" --recursive
    
    cat > policy.json <<'EOF'
    { "rules": [ { "name": "logs-tiering", "enabled": true, "type": "Lifecycle",
      "definition": {
        "filters": { "blobTypes": [ "blockBlob" ], "prefixMatch": [ "images/logs/" ] },
        "actions": {
          "baseBlob": {
            "tierToCool":    { "daysAfterModificationGreaterThan": 30 },
            "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
            "delete":        { "daysAfterModificationGreaterThan": 365 } },
          "version": { "delete": { "daysAfterCreationGreaterThan": 30 } } } } } ] }
    EOF
    az storage account management-policy create -g $RG --account-name $ST --policy @policy.json
  6. Task

    Create a file share with a snapshot

    Create an SMB file share share1 with a 10 GiB quota in the Hot tier. Make sure a deleted share can be recovered for 7 days, and take a snapshot of the share.

    Done when
    • share1 has one snapshot.
    • File share soft delete is on with 7 days.
    Solution Β· Portal
    1. Data storage β†’ File shares β†’ + File share: share1, tier Hot, then set quota 10 GiB (share β†’ Edit quota).
    2. File shares page β†’ Soft delete setting β†’ enabled, 7 days.
    3. share1 β†’ Operations β†’ Snapshots β†’ + Add snapshot.
    Solution Β· Azure CLI
    az storage share-rm create -g $RG --storage-account $ST -n share1 --quota 10 --access-tier Hot
    az storage account file-service-properties update -g $RG -n $ST --enable-delete-retention true --delete-retention-days 7
    az storage share-rm snapshot -g $RG --storage-account $ST -n share1
    az storage share-rm list -g $RG --storage-account $ST --include-snapshot -o table
  7. Task

    Close the account to the internet

    Change the storage firewall so that the account is reachable only from:

    • snet-web, through a service endpoint;
    • your browser's public IP (so the portal's storage browser keeps working), not the Linux VM's;
    • trusted Azure services (chapter 10's Backup needs this).

    Then add a private endpoint pe-st-file in snet-data for the file service, with private DNS so that both VNets resolve the share to its private IP.

    Done when
    • Networking shows Enabled from selected virtual networks and IP addresses with snet-web and your IP.
    • Private DNS zone privatelink.file.core.windows.net has an A record pointing to a 10.20.2.x address and is linked to both VNets.
    • From your Linux VM, az storage blob list --auth-mode login on images now fails, even though you are Owner. Why?
    Hint

    The portal's private endpoint wizard can create and link the privatelink DNS zone for you, but only to the endpoint's own VNet. Add the hub link yourself.

    Solution Β· Portal
    1. Storage account β†’ Security + networking β†’ Networking β†’ Firewalls and virtual networks: Enabled from selected virtual networks and IP addresses. + Add existing virtual network β†’ vnet-spoke / snet-web (the portal enables the Microsoft.Storage service endpoint). Tick Add your client IP address. Under Exceptions keep Allow Azure services on the trusted services list. Save.
    2. Private endpoint connections β†’ + Private endpoint: name pe-st-file, target sub-resource file, VNet vnet-spoke, subnet snet-data, Integrate with private DNS zone: Yes.
    3. Open Private DNS zones β†’ privatelink.file.core.windows.net β†’ Virtual Network Links β†’ Add β†’ vnet-hub, no auto-registration.

    The VM's requests come from its AWS address ($MYIP), which isn't in the allow list, so the data plane rejects them with AuthorizationFailure (a 403). The firewall is checked before RBAC: being Owner doesn't help. Managing the account (control plane) from the VM still works.

    Solution Β· Azure CLI
    # service endpoint + firewall
    az network vnet subnet update -g $RG --vnet-name vnet-spoke -n snet-web --service-endpoints Microsoft.Storage
    az storage account network-rule add -g $RG --account-name $ST --vnet-name vnet-spoke --subnet snet-web
    az storage account network-rule add -g $RG --account-name $ST --ip-address <your-browser-ip>
    az storage account update -g $RG -n $ST --default-action Deny --bypass AzureServices
    
    # test from the Linux VM (allow up to a minute for the rules to apply)
    az storage blob list --account-name $ST -c images --auth-mode login -o table   # AuthorizationFailure
    az storage account show -g $RG -n $ST --query networkRuleSet.defaultAction     # control plane still works
    
    # private endpoint for the file service
    az network private-endpoint create -g $RG -n pe-st-file -l $LOC --vnet-name vnet-spoke --subnet snet-data \
      --private-connection-resource-id $STID --group-id file --connection-name pe-st-file-conn
    az network private-dns zone create -g $RG -n privatelink.file.core.windows.net
    az network private-dns link vnet create -g $RG -z privatelink.file.core.windows.net -n link-spoke -v vnet-spoke -e false
    az network private-dns link vnet create -g $RG -z privatelink.file.core.windows.net -n link-hub   -v vnet-hub   -e false
    az network private-endpoint dns-zone-group create -g $RG --endpoint-name pe-st-file -n default \
      --private-dns-zone privatelink.file.core.windows.net --zone-name file
    az network private-dns record-set a list -g $RG -z privatelink.file.core.windows.net -o table

    Find your browser's public IP by searching "what is my IP" in it. It differs from $MYIP, the AWS VM's address.

  8. Task

    Use the storage account from vm-web1

    From vm-web1 (Bastion or Run command):

    • Look up the blob and the file host names of your account. One resolves to a public IP, one to a private IP. Explain why.
    • Mount share1 at /mnt/share1 over SMB 3.1.1 and write a file from-vm.txt to it.
    Done when
    • Blob β†’ public IP (service endpoint), file β†’ 10.20.2.x (private endpoint).
    • from-vm.txt is visible in the portal under share1.
    Hint

    The file share's Connect button in the portal generates a Linux mount script. The VM needs the cifs-utils package; it can download it through the load balancer's outbound rule from chapter 6.

    Solution Β· Portal + Bastion
    1. Bastion SSH to vm-web1: nslookup staz104xx01.blob.core.windows.net and nslookup staz104xx01.file.core.windows.net. The file name goes through privatelink to 10.20.2.4.
    2. sudo apt-get install -y cifs-utils
    3. Portal: share1 β†’ Connect β†’ Linux β†’ Show script, copy it into the Bastion session (change the mount point to /mnt/share1 if you like).
    4. echo hello | sudo tee /mnt/share1/from-vm.txt, then check share1 in the portal.
    Solution Β· Azure CLI
    KEY=$(az storage account keys list -g $RG -n $ST --query "[0].value" -o tsv)
    az vm run-command invoke -g $RG -n vm-web1 --command-id RunShellScript --scripts "
    nslookup $ST.blob.core.windows.net | tail -3
    nslookup $ST.file.core.windows.net | tail -3
    apt-get install -y -q cifs-utils >/dev/null
    mkdir -p /mnt/share1
    mount -t cifs //$ST.file.core.windows.net/share1 /mnt/share1 \
      -o vers=3.1.1,username=$ST,password=$KEY,serverino,dir_mode=0777,file_mode=0777
    echo hello-from-\$(hostname) > /mnt/share1/from-vm.txt
    df -h /mnt/share1" --query "value[0].message" -o tsv

    Mounting with the account key gives full access. In production you'd use identity-based access (AD DS or Entra Kerberos) and RBAC share-level roles.

Cost

A few MB in RA-GRS cost practically nothing. The private endpoint costs about €0.01/hour. Nothing here needs stopping between sessions.

Checkpoint
  • staz104xx01 (RA-GRS) with container images (versioning, soft delete, lifecycle rule) and share share1 (snapshot, soft delete).
  • Firewall: only snet-web, your IP and trusted services. Private endpoint pe-st-file in snet-data with private DNS.
  • share1 is mounted on vm-web1 (until the next reboot; it isn't in /etc/fstab).