Azure Azure Migrate Hyper-V PowerShell

Azure Migrate: Source validation of a standalone non-domain joined Hyper-V host fails with error “Access is denied”


While deploying an Azure Migrate virtual appliance to perform an Azure VM assessment for Hyper-V virtual machines (VMs) running on a standalone non-domain joined Hyper-V host, I received the following error during the source discovery:

Status: Validation failed

Looking into the details of the validation error, I could see that “Access was denied” and that the credentials provided for discovery needed to be verified.



After some troubleshooting, I ruled out that the credentials used were correct and that the Hyper-V host could be contacted from the appliance. I also checked whether the user used had local Administrator rights (Administrator access) on the Hyper-V host. Which was also the case.


Check if the Hyper-V host is reachable from the appliance.

ping <IP Address Hyper-V host>


Check if the Hyper-V host is accessible over port 5985 (WinRM).

telnet <IP Address Hyper-V host> 5985


Check if you can access the Hyper-V host with RDP and logon with the specific (local) username.

mstsc /v: <IP Address Hyper-V host>


List all groups the local user is a member of (run on the Hyper-V host).

net user <username>


After doing some more troubleshooting, and reading trough the Microsoft docs, I finally figured out the issue. On a stand-alone non-domain joined Hyper-V host the user used for the discovery does not only needs to be a member of the Local Administrators group, but also of the Hyper-V Administrators, Performance Monitor Users and Remote Management Users groups.


After adding the user to all these groups the validation was successful (after revalidation) and I could start with the discovery.



To ease up the whole process in case I need to discover VMs on another stand alone non-domain joined Hyper-V host, I wrote the below PowerShell script, which creates a Local Admin belonging to all necessary groups on the Hyper-V host.

This PowerShell script will do all of the following:

  • Check if PowerShell is running as Administrator, otherwise close the PowerShell window.
  • Create a secure password for the Local Admin account (save variable as a secure string).
  • Create the Local Admin account and set the password to the one stored in the secure string.
  • Specifies the Full Name and Description parameters for the Local Admin account.
  • Also sets the following attributes for the Local Admin account: User cannot change password and Password never expires.
  • Add the Local Admin account to the required groups: Hyper-V Administrators, Remote Management Users, and Performance Monitor User.


PowerShell script: Create Azure Migrate Local Admin on Hyper-V

To use the script copy and save it as Create_Azure_Migrate_Local_Admin_on_Hyper-V.ps1 or download it from GitHub. First adjust all variables to your use and afterwards run the script with Administrator privileges from Windows PowerShell or Windows Terminal.



<#
.SYNOPSIS

A script used to create an Azure Migrate Local Admin account on a standalone non-domain joined Hyper-V host

.DESCRIPTION

A script used to create an Azure Migrate Local Admin account on a standalone non-domain joined Hyper-V host.
This Local Admin account will also added to the following groups: Hyper-V Administrators, Remote Management Users, and Performance Monitor Users.

.NOTES

Filename:       Create_Azure_Migrate_Local_Admin_on_Hyper-V.ps1
Created:        03/12/2020
Last modified:  04/12/2020
Author:         Wim Matthyssen
PowerShell:     5.1
Action:         Change variables were needed to fit your needs.
Disclaimer:     This script is provided "As IS" with no warranties.

.EXAMPLE

.\Create_Azure_Migrate_Local_Admin_on_Hyper-V.ps1

.LINK

#>

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Variables

$global:currenttime= Set-PSBreakpoint -Variable currenttime -Mode Read -Action {$global:currenttime= Get-Date -UFormat "%A %m/%d/%Y %R"}
$foregroundColor1 = "Red"
$writeEmptyLine = "`n"
$writeSeperatorSpaces = " - "


$localUserName = "aa_azmig"

$localUserFullName = $localUserName
$localUserDescription = "Azure Migrate Adminstrator account"


$administratorsGroup = "Administrators"
$hvAdministratorsGroup = "Hyper-V Administrators"
$remoteManagementUsersGroup = "Remote Management Users"
$performanceMonitorUsersGroup = "Performance Monitor Users"

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Prerequisites

## Check if running as Administrator, otherwise close the PowerShell window

$CurrentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$IsAdministrator = $CurrentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($IsAdministrator -eq $false) {
    Write-Host ($writeEmptyLine + "# Please run PowerShell as Administrator" + $writeSeperatorSpaces + $currentTime)`
    -foregroundcolor $foregroundColor1 $writeEmptyLine
    Start-Sleep -s 5
    exit
}

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create a secure password for the Local Admin account

$secPassword = Read-Host " # Type in a password for the Local Admin account" $localUserName "which meets the complexity requirements" –AsSecureString 

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create Local Admin account

New-LocalUser -Name $localUserName -Password $secPassword -FullName $localUserFullName -Description $localUserDescription -UserMayNotChangePassword -PasswordNeverExpires –Verbose

Write-Host ($writeEmptyLine + " # Local Admin Account " + $localUserName + " created" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Add Local Admin account to the required groups

Add-LocalGroupMember -Group $administratorsGroup -Member $localUserName –Verbose
Add-LocalGroupMember -Group $hvAdministratorsGroup -Member $localUserName –Verbose
Add-LocalGroupMember -Group $remoteManagementUsersGroup -Member $localUserName –Verbose
Add-LocalGroupMember -Group $performanceMonitorUsersGroup -Member $localUserName –Verbose

Write-Host ($writeEmptyLine + " # Local Admin Account " + $localUserName + " added to the required groups" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



Conclusion

When assessing VMs running on a standalone non-domain joined Hyper-V host, the Local Admin account used for the discovery, also needs to be a member of the Hyper-V Administrators, Performance Monitor Users and Remote Management Users group. Otherwise the discovery will fail with a validation failed error.


%d bloggers like this: