Hello folks,
Microsoft introduced a new feature in Windows Server 2016 and later versions called PowerShell Direct. In this guide, we will deep dive into how to use PowerShell Direct in Hyper-V and provide an example of what you can do with it.
Table of Contents
What is PowerShell Direct?
PowerShell Direct allows you to use PowerShell directly between your host operating system and virtual machines guest operating system (Specifically Windows 10, Windows Server 2016) without having any network configuration or any type of network at all, and you don’t even need to have a vmNIC attached to your virtual machine, and without configuring WinRM. You can just use PowerShell directly to your virtual machine from your Hyper-V host operating system.
By leveraging the VMBus architecture of Hyper-V, we are literally bypassing all the requirements for networking, firewall, remote management, and access settings. It’s really a fantastic feature.
PowerShell Direct Syntax
Enter-PSSession -–VMName VMName –Credential
Invoke-Command –VMName VMName –Credential –ScriptBlock { Commands }
You can use either Enter-PSSession or Invoke-Command but instead of specifying the compute name, you can specify the virtual machine using two parameters –VMName or –VMGuid
PowerShell Direct Requirement
On the host side, you need to be a member of the Hyper-V Administrator group, because you want to have access to your virtual machines in the first place, you need to be Hyper-V admin, if you are able to run Get-VM on the host, then you can use PowerShell direct very simple. However on the guest operating side, you can use any credentials that are available on the guest OS, but obviously, you will have the correct limitation for those credentials, so you can run as Administrator or as a Standard user based on what you need to do.
One important point to mention, PowerShell Direct relies on PowerShell Remoting, so you do need to be able to run PowerShell Remoting in order to use PowerShell Direct.
Update: PowerShell Direct DOES NOT in any way require PowerShell Remoting. You can even stop the WinRM service on the host and in the guest and PowerShell Direct will continue work.
PowerShell Direct Limitation
You can use PowerShell directly to your virtual machine from your host operating system, but really we need to get things in and out of the virtual machine, so file copy is not available at the moment. Hopefully, this will change in the near future. Please use the user voice to vote for the VM file copy. What about Linux guests and SSH? As for now, you can use PowerShell Direct with Windows 10 or above as a guest OS.
Would you like to use PowerShell directly with Windows 8.1 and Windows Server 2012 R2? Please vote here.
What You Can Do With PowerShell Direct?
In short, you can do everything. You can script an entire environment end to end using PowerShell Direct.
In this quick demo, I will share with you on how to set up a new domain controller inside a virtual machine from the host using PowerShell Direct.
This script is based on a Sysprepped VM with no configuration.
$localCred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist "Administrator", (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force)
$domainCred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist "PoSH-Direct\Administrator", (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force)
$DCGuestOSName = "DC"
$VMName = "DC"
function rebootVM([string]$VMName) { Write-Output "[$($VMName)]:: Is Rebooting"; stop-vm $VMName; start-vm $VMName }
function waitForPSDirect([string]$VMName, $cred)
{
Write-Output "[$($VMName)]:: Waiting for PowerShell Direct (using $($cred.username))"
while ((Invoke-Command -VMName $VMName -Credential $cred -ScriptBlock { "Test" } -ea SilentlyContinue) -ne "Test") { Sleep -Seconds 1 }
}
# Wait for PowerShell Direct to respond
waitForPSDirect $VMName -cred $localCred
# Set IP address, rename guest
Invoke-Command -VMName $VMName -Credential $localCred -Scriptblock {
param ($VMName, $DCGuestOSName)
Rename-NetAdapter -InterfaceDescription "Microsoft Hyper-V Network Adapter" -NewName "MGMT"
New-NetIPAddress -InterfaceAlias "MGMT" -IPAddress 172.16.20.9 -AddressFamily IPv4 -DefaultGateway 172.16.20.1 -PrefixLength 24 | Out-Null
Set-DnsClientServerAddress -InterfaceAlias "MGMT" -ServerAddresses 127.0.0.1
Write-Output "[$($VMName)]:: Renaming OS to `"$($DCGuestOSName)`""
Rename-Computer -NewName $DCGuestOSName
} -ArgumentList $VMName, $DCGuestOSName
# Reboot domain controller VM
rebootVM $VMName
waitForPSDirect $VMName -cred $localCred
# Install AD Domain Services
Invoke-Command -VMName $VMName -Credential $localCred -Scriptblock {
param ($VMName)
Write-Output "[$($VMName)]:: Enabling AD"
Install-WindowsFeature AD-Domain-Services –IncludeManagementTools | out-null
} -ArgumentList $VMName
# Setup domain controller
Invoke-Command -VMName $VMName -Credential $localCred -ScriptBlock {
param ($VMName)
Write-Output "[$($VMName)]:: Installing Active Directory and promoting to domain controller"
Install-ADDSForest -DomainName PoSH-Direct.demo -InstallDNS -NoDNSonNetwork -NoRebootOnCompletion `
-SafeModeAdministratorPassword (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -confirm:$false
} -ArgumentList $VMName
# Reboot domain controller VM
rebootVM $VMName
waitForPSDirect $VMName -cred $domainCred
# Check Domain Controller
Invoke-Command -VMName $VMName -Credential $domainCred -ScriptBlock {Get-ADDomain | Select Name, DNSroot, PDCEmulator, DistinguishedName}
# Congrats! End Demo
The nifty waitForPSDirect function is borrowed from Mr. Hyper-V Ben Armstrong (Principal program manager lead for Hyper-V at Microsoft).
Here you go… 3 minutes later, and we have a cooked Domain Controller ready to serve
Protect VM from PowerShell Direct
PowerShell Direct is a fantastic feature! Why do you want to disable it for virtual machines?
Well in certain scenarios for example, the admin who manages the virtual machines is not the same who manages the fabric, or in a hosting environment where the tenant wants to block PowerShell Direct, but as I mentioned earlier in this post, you need to have guest credentials in order to use PowerShell direct.
Well, you can protect a Virtual Machine from PowerShell Direct by disabling the “Hyper-V VM Session Service” inside a virtual machine.
Let’s see this in action. I have a VM here called SCVMM-TP3. If we query all Hyper-V Services inside the guest from the host, we can see 8 services up and running. The service which leverages PowerShell Direct is highlighted in yellow as shown in the figure below.
I will disable and stop the Hyper-V VM Session Service by running the following cmdlet from the host.
Please note that it is not enough to stop the service only, because Hyper-V services inside the guest are set to Manual Trigger, so if you stop the service and try to use PowerShell Direct, the service will start again
Let’s try and query Hyper-V VM Session Service again after we stopped and disabled the service.
Did you notice something? The service is stopped, but we are still able to use PowerShell Direct, because it’s not enough to disable and stop the service, you need to restart the guest OS as well in order to disable PowerShell Direct completely. Let’s restart the guest OS and try the operation again.
PowerShell Direct is completely disabled now. If you enable and start the service again within the guest, you can start using PowerShell Direct without restarting the guest OS.
By disabling and stopping the Hyper-V VM Session Service, no one can access the virtual machine using PowerShell Direct even if the user credentials are compromised.
What about Shielded VMs, PowerShell direct is disabled by default on Shielded virtual machines at the time of writing this post.
Note: This is the current release of Windows Server 2016, please note that things might change in the next release.
Thanks to the Hyper-V team for delivering value-added services and capabilities on an ongoing basis.
Until then… enjoy your day!
__
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.
-Charbel Nemnom-