0

Tried running a PowerShell script to remediate virtual machines in our Azure tenant. Our VMs need to have Encryption at Host enabled.

I wrote a script to get all VMs, check if they had encryption enabled, stop the VM, update the property, then restart the VM (if it was running). I had about 30 VMs that didn't remediate, but some VMs did even in the same subscription. I modified the code to try and force the VMs that didn't remediate to update their settings as follows:

$subscriptionID = "mysubid"
Set-AzContext $subscriptionID

# List remaining non-compliant VMs
$subVMs = ("list of vm names")

foreach ($name in $subVMs) {
    $vm = Get-AZVM -Name $name
    $thisVm = Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status
    $powerState = $thisVm.Statuses.DisplayStatus

    Stop-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force

    $vm.Name
    $vm.SecurityProfile.EncryptionAtHost = $true
    Update-AzVM -ResourceGroupName $vm.ResourceGroupName -vm $vm

    if ($powerState -eq "VM running") {
        Start-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name
    }
}

The problem I'm running into is I get this error for each of these VMs that didn't originally remediate.

"The property 'EncryptionAtHost' cannot be found on this object. Verify that the property exists and can be set."

I have double checked that the feature is registered at the subscription levels with:

Get-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute"

And the subscriptions have the feature enabled.

I know VM size can be an issue but we have VMs on the same OS with the same size, one is encrypted at host, the other gives me the error. Looking for a workaround that doesn't involve just manually changing all of the VMs.

Edit: Let me clarify more the issue I'm running into. It's not that I don't know which VMs are non-compliant, it's that when I run the script to change them, the script isn't recognizing that the VM even has the property to change. I ran this code to see if I could figure out why:

foreach ($name in $subVMs) {
    $vm = Get-AZVM -Name $name

    $vm.Name
        
    if ($vm.SecurityProfile.EncryptionAtHost -eq $true) {
        Write-Output "Already Encrypted"
    }

    if ($vm.SecurityProfile.EncryptionAtHost -eq $false){
        Write-Output "Not Encrypted"
    }

    Write-Output ""
}

This returned an output similar to the following:

VM1 Not Encrypted

VM2 Already Encrypted

VM3

VM4 Already Encrypted

See how VM3 doesn't have either output message? These are the VMs that are returning that the property cannot be found on the object. I'm trying to figure out why so that I can adjust my script to change these VMs as well.

Edit: After running the Get-AZVM command for a specific VM that is not encrypting. Get-AZVM Output

1 Answer 1

0

Looking for a workaround that doesn't involve just manually changing all of the VMs.

You can use the PowerShell script below to check all the recommended steps to enable EncryptionAtHost for all the VMs in the subscription. It will create an Excel file listing any failures to update, along with error details, so you can easily identify non-compliant VMs without manual effort.

The script will check the below configurations

  • Registers EncryptionAtHost if needed
  • Enables EncryptionAtHostonly if not already enabled
  • Starts the VM if it’s deallocated — even when encryption is already enabled.
  • Tracks failures with encryption state
    Exports a CSV report only if there are any failures

Here is the updated Powershell script

$subscriptionID = "your-subscription-id"
Set-AzContext -SubscriptionId $subscriptionID

$failures = @()

$feature = Get-AzProviderFeature -ProviderNamespace "Microsoft.Compute" -FeatureName "EncryptionAtHost"
if ($feature.RegistrationState -ne "Registered") {
    Write-Host "EncryptionAtHost is not registered. Registering now..." -ForegroundColor Yellow
    Register-AzProviderFeature -ProviderNamespace "Microsoft.Compute" -FeatureName "EncryptionAtHost"

    do {
        Start-Sleep -Seconds 15
        $feature = Get-AzProviderFeature -ProviderNamespace "Microsoft.Compute" -FeatureName "EncryptionAtHost"
        Write-Host "Waiting for registration... Current state: $($feature.RegistrationState)"
    } while ($feature.RegistrationState -ne "Registered")

    Register-AzResourceProvider -ProviderNamespace "Microsoft.Compute"
    Write-Host "EncryptionAtHost feature is now registered and ready." -ForegroundColor Green
} else {
    Write-Host "EncryptionAtHost is already registered. Proceeding..." -ForegroundColor Green
}

# List of VMs
$subVMs = @(
    "Venkat-Vm"
)

$resourceGroup = "VENKAT-RG"

foreach ($vmName in $subVMs) {
    try {
        Write-Host "`n🔄 Checking VM: ${vmName}..." -ForegroundColor Cyan

        $statusVm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Status
        if (-not $statusVm -or -not $statusVm.Statuses) {
            throw "VM '$vmName' not found or 'Statuses' not available."
        }

        $resourceGroup = $statusVm.ResourceGroupName
        $powerState = ($statusVm.Statuses | Where-Object { $_.Code -like "PowerState/*" }).DisplayStatus
        $vm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -ErrorAction Stop

        $existingEncryption = if ($vm.SecurityProfile) { $vm.SecurityProfile.EncryptionAtHost } else { $false }

        if ($existingEncryption -eq $true) {
            Write-Host "Already encrypted: $vmName" -ForegroundColor Green

            if ($powerState.Trim().ToLower() -eq "vm deallocated") {
                Write-Host "Starting previously deallocated VM: $vmName"
                Start-AzVM -ResourceGroupName $resourceGroup -Name $vmName -ErrorAction Stop
            }

            continue
        }

        if ($powerState.Trim().ToLower() -ne "vm deallocated") {
            Write-Host "Stopping VM: $vmName"
            Stop-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Force -ErrorAction Stop

            do {
                Start-Sleep -Seconds 10
                $vmState = (Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Status).Statuses |
                           Where-Object { $_.Code -like "PowerState/*" } |
                           Select-Object -ExpandProperty DisplayStatus
                Write-Host "Current state: $vmState"
            } while ($vmState.Trim().ToLower() -ne "vm deallocated")
        }

        $vm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -ErrorAction Stop

        if (-not $vm.SecurityProfile) {
            $vm.SecurityProfile = New-Object -TypeName Microsoft.Azure.Management.Compute.Models.SecurityProfile
        }

        $vm.SecurityProfile.EncryptionAtHost = $true
        Write-Host "Enabling EncryptionAtHost on $vmName"
        Update-AzVM -ResourceGroupName $resourceGroup -VM $vm -ErrorAction Stop

        Write-Host "Encryption enabled on $vmName" -ForegroundColor Green
        Start-AzVM -ResourceGroupName $resourceGroup -Name $vmName -ErrorAction Stop
    }

    catch {
        try {
            $vmTry = Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -Status -ErrorAction Stop
            $encryptionState = if ($vmTry.SecurityProfile) { $vmTry.SecurityProfile.EncryptionAtHost } else { "NotSet" }
            $rg = $vmTry.ResourceGroupName
        }
        catch {
            $encryptionState = "Unknown"
            $rg = "Unknown"
        }

        Write-Host " Failed: $vmName - $($_.Exception.Message)" -ForegroundColor Red

        $failures += [PSCustomObject]@{
            VMName                  = $vmName
            ResourceGroup           = $rg
            CurrentEncryptionAtHost = $encryptionState
            ErrorMessage            = $_.Exception.Message
        }
    }
}


if ($failures.Count -gt 0) {
    $failures | Export-Csv -Path "./encryptionAtHostFailures.csv" -NoTypeInformation
    Write-Host "Exported failed VM details to encryptionAtHostFailures.csv" -ForegroundColor Cyan
} else {
    Write-Host "All VMs processed successfully." -ForegroundColor Green
}

Output:

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

Your script is very nice but unfortunately not what I need. I clarified my issue more in my question.
Could you please check the status of VM3 by running the command manually? Get-AzVM -ResourceGroupName $resourceGroup -Name $vmName -ErrorAction Stop and share the result screenshot.
I updated my question to include this output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.