When working with Azure File Shares across multiple VMs, credential persistence becomes crucial for automated deployments. The standard approach using cmdkey
works perfectly in local PowerShell sessions but fails in remote scenarios with the frustrating "Credentials cannot be saved from this logon session" error.
The core issue stems from Windows security architecture. Remote PowerShell sessions operate under network logon (NewCredentials) rather than interactive logon, which restricts credential manager access. This affects:
- Azure File Share mounting via
net use
- Windows Update modules
- Any operation requiring persistent credentials
Here are three practical approaches I've validated in production environments:
1. Scheduled Task Method
Create a task that runs under SYSTEM context:
$Action = New-ScheduledTaskAction -Execute "cmdkey.exe" -Argument "/add:$Share /user:$AccountName /pass:$Key"
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -Action $Action -Principal $Principal -TaskName "PersistAzureCreds" -Description "Stores Azure File Share credentials"
Start-ScheduledTask -TaskName "PersistAzureCreds"
2. Custom PowerShell Module
Create a module that stores credentials in alternative storage:
function Save-AzureFileCredential {
param(
[string]$Share,
[string]$Username,
[string]$Password
)
$secureString = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($Username, $secureString)
$credential | Export-Clixml -Path "C:\Azure\FileShareCreds.xml"
}
3. Direct Registry Modification
For advanced scenarios, modify the Windows Credential Manager registry directly:
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains"
$null = New-ItemProperty -Path $regPath -Name $Share -PropertyType String -Value $Key -Force
When implementing this in Azure deployments:
- Always encrypt credentials using Azure Key Vault
- Use managed identities where possible
- Implement proper error handling for credential operations
After implementing any solution, verify with:
Invoke-Command -Session $Session -ScriptBlock {
cmdkey /list
Test-Path "C:\Azure\FileShareCreds.xml"
}
Remember that each approach has different security implications - choose based on your specific security requirements.
When working with Azure VMs and file shares, a common requirement is to persist credentials for accessing Azure File Shares using cmdkey
and net use
. While this works seamlessly in local PowerShell sessions, attempting the same operation through remote PowerShell sessions presents unexpected challenges.
The error message CMDKEY: Credentials cannot be saved from this logon session
occurs because Windows credential manager restricts credential storage operations from remote sessions due to security constraints. This limitation affects not just credential persistence but also other operations like Windows Update management through remote PowerShell.
Here are several methods to work around this limitation:
Method 1: Using Scheduled Tasks
Create a scheduled task that runs locally on the target VM:
$ScriptBlock = {
param($Share, $AccountName, $Key)
$Action = New-ScheduledTaskAction -Execute "cmdkey.exe" -Argument "/add:$Share /user:$AccountName /pass:$Key"
$Trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "PersistFileShareCreds" -Force
}
Invoke-Command -Session $Session -ScriptBlock $ScriptBlock -ArgumentList ($Share, $AccountName, $Key)
Method 2: Direct Registry Modification
Modify the Windows credential store directly through registry:
$ScriptBlock = {
param($TargetName, $UserName, $Password)
$keyPath = "Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
$regProps = @{
Path = "HKLM:\$keyPath"
Name = "DefaultUserName"
Value = $UserName
PropertyType = "String"
Force = $true
}
Set-ItemProperty @regProps
$regProps.Name = "DefaultPassword"
Set-ItemProperty @regProps
$regProps.Name = "DefaultDomainName"
$regProps.Value = $TargetName
Set-ItemProperty @regProps
}
Invoke-Command -Session $Session -ScriptBlock $ScriptBlock -ArgumentList ($Share, $AccountName, $Key)
Method 3: Using Azure VM Extensions
For Azure deployments, consider using Custom Script Extensions:
$ScriptSettings = @{
"fileUris" = @("https://storageaccount.blob.core.windows.net/scripts/SetCredentials.ps1")
"commandToExecute" = "powershell -ExecutionPolicy Unrestricted -File SetCredentials.ps1"
}
Set-AzVMCustomScriptExtension -ResourceGroupName $RGName
-VMName $VMName
-Location $Location
-Name "PersistCredentials"
-TypeHandlerVersion "1.1"
-Settings $ScriptSettings
When implementing credential persistence:
- Always use Azure Key Vault for storing sensitive credentials
- Limit credential scope using SAS tokens when possible
- Implement proper credential rotation policies
- Consider using Managed Identities for Azure resources where applicable
If you encounter issues:
- Verify the remote session has sufficient privileges (run as Administrator)
- Check if User Account Control (UAC) is interfering with credential operations
- Test with simpler commands first to validate the remote session
- Review Windows Event Logs for additional error details