Azure Files with Active Directory authentication is great for file shares that need NTFS permissions. But the setup requires domain joining the storage account - and doing that in a pipeline is tricky.
Why Domain Join?
Without AD authentication, Azure Files only supports:
- Storage account key (shared key)
- Azure AD (Entra) authentication for specific scenarios
For NTFS permissions that work like traditional file servers, you need AD DS authentication.
The AzFilesHybrid Module
Microsoft provides the AzFilesHybrid PowerShell module to domain join storage accounts:
# Download and import
$url = "https://github.com/Azure-Samples/azure-files-samples/releases/latest/download/AzFilesHybrid.zip"
Invoke-WebRequest -Uri $url -OutFile AzFilesHybrid.zip
Expand-Archive -Path AzFilesHybrid.zip -DestinationPath .
Import-Module .\AzFilesHybrid\AzFilesHybrid.psd1
Pipeline Configuration
Create a pipeline that can authenticate to both Azure and AD:
trigger: none
pool:
vmImage: 'windows-latest'
variables:
storageAccountName: 'stfilesproduction'
resourceGroupName: 'rg-storage'
ouPath: 'OU=Storage,DC=corp,DC=local'
steps:
- task: AzurePowerShell@5
displayName: 'Domain Join Storage Account'
inputs:
azureSubscription: 'your-service-connection'
ScriptType: 'InlineScript'
Inline: |
# Download AzFilesHybrid
$url = "https://github.com/Azure-Samples/azure-files-samples/releases/latest/download/AzFilesHybrid.zip"
Invoke-WebRequest -Uri $url -OutFile AzFilesHybrid.zip
Expand-Archive -Path AzFilesHybrid.zip -DestinationPath . -Force
Import-Module .\AzFilesHybrid\AzFilesHybrid.psd1 -Force
# Join the storage account to AD
Join-AzStorageAccount `
-ResourceGroupName "$(resourceGroupName)" `
-StorageAccountName "$(storageAccountName)" `
-DomainAccountType "ComputerAccount" `
-OrganizationalUnitDistinguishedName "$(ouPath)"
azurePowerShellVersion: 'LatestVersion'
The Challenge: AD Credentials
The problem is Join-AzStorageAccount needs credentials that can create objects in AD. Your pipeline service connection authenticates to Azure, not AD.
Option 1: Hybrid Runbook Worker
Run the pipeline on a self-hosted agent that's domain joined:
pool:
name: 'OnPremAgents'
demands:
- Agent.OS -equals Windows_NT
The agent runs as a domain account with permission to create computer objects.
Option 2: AD Service Account
Store AD credentials in Key Vault and use them in the script:
- task: AzureKeyVault@2
inputs:
azureSubscription: 'your-service-connection'
KeyVaultName: 'kv-devops-secrets'
SecretsFilter: 'AD-Join-Username,AD-Join-Password'
RunAsPreJob: true
- task: PowerShell@2
displayName: 'Join Storage to AD'
inputs:
targetType: 'inline'
script: |
$username = "$(AD-Join-Username)"
$password = ConvertTo-SecureString "$(AD-Join-Password)" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $password)
# This requires line of sight to AD domain controller
Join-AzStorageAccount `
-ResourceGroupName "$(resourceGroupName)" `
-StorageAccountName "$(storageAccountName)" `
-DomainAccountType "ComputerAccount" `
-OrganizationalUnitDistinguishedName "$(ouPath)" `
-Domain "corp.local" `
-Credential $cred
Option 3: Azure Automation with Hybrid Worker
Use Azure Automation with a Hybrid Runbook Worker for the best of both:
# Automation Runbook
param(
[string]$StorageAccountName,
[string]$ResourceGroupName,
[string]$OUPath
)
Import-Module AzFilesHybrid
# Use managed identity for Azure auth
Connect-AzAccount -Identity
# AD auth happens automatically on domain-joined worker
Join-AzStorageAccount `
-ResourceGroupName $ResourceGroupName `
-StorageAccountName $StorageAccountName `
-DomainAccountType "ComputerAccount" `
-OrganizationalUnitDistinguishedName $OUPath
Verifying the Join
After joining, verify in the portal or with PowerShell:
$storageAccount = Get-AzStorageAccount `
-ResourceGroupName $resourceGroupName `
-Name $storageAccountName
$storageAccount.AzureFilesIdentityBasedAuth
# Should show:
# DirectoryServiceOptions : AD
# ActiveDirectoryProperties : ...
Setting NTFS Permissions
After domain join, set permissions on the share:
# Map with storage key first
$key = (Get-AzStorageAccountKey -ResourceGroupName $rg -AccountName $sa)[0].Value
net use Z: "\\$sa.file.core.windows.net\share" /user:Azure\$sa $key
# Set NTFS permissions
icacls Z: /grant "CORP\FileUsers:(M)"
icacls Z: /grant "CORP\FileAdmins:(F)"
Need help with Azure Files and hybrid identity? Get in touch - we help organisations integrate cloud storage with existing infrastructure.