Persisting Azure File Share Credentials in Remote PowerShell Sessions: Solving “Credentials Cannot Be Saved” Error


2 views

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:

  1. Verify the remote session has sufficient privileges (run as Administrator)
  2. Check if User Account Control (UAC) is interfering with credential operations
  3. Test with simpler commands first to validate the remote session
  4. Review Windows Event Logs for additional error details