Hyper-V and PowerShell: Shielded Virtual Machines

In Windows Server 2016, Microsoft have implemented a strong security concept called Shielded Virtual Machines. Shielded VMs have been improved in the Windows Server 2019 release. In the second part of this series, Nicolas describes what Shielded Virtual Machines are and how to configure them using PowerShell.

The series so far:

  1. Hyper-V and PowerShell: The Basics
  2. Hyper-V and PowerShell: Shielded Virtual Machines

In Windows Server 2016, Microsoft implemented a strong security concept called Shielded VMs. Shielded VMs have been improved in the Windows Server 2019 release. In the second part of this series, Nicolas describes what Shielded Virtual Machines are and how to configure them using PowerShell.

One key investment area that Microsoft improves in every Windows Server release is security. Whether you work for a small company or a multinational company, security is essential. But sometimes, it can be hard to secure your machines. If you work with physical machines, then you simply put these machines in a secure datacenter with padlocks and provide access only to authorized administrators. On top of that you could have security guards in front of the datacenter. With Virtual Machines, you don’t have this security perimeter because many administrators can access these VMs, such as: Hyper-V administrators, backup administrators, storage administrators, or maybe network administrators. These administrators can access your virtual machines because they need access to VMs in order to do their jobs! Thus, they must be able to access the VHD disks.

What are the security risks?

The first risk that you can encounter is, for example, that your storage administrator with access to Hyper-V, will copy and paste one or many VHD disks to a USB device. The reason why Hyper-V presents such a huge risk has to do with Hyper-V anatomy. A virtual machine is a VHD disk which is nothing more than a file. Rather than booting the virtual machine, anyone could simply mount the VHD disk on a different Windows Server, thus giving the administrator access to the full contents of the VHD disk. In a better case, you will be notified that a copy has been made to an external drive; in the worst case you will have no awareness that your data has been compromised. Another risk is a malware attack. Imagine your Hyper-V host is compromised; all your VHD disks will be vulnerable and the malware will have full access to your Virtual Machines.

To reduce such risks, Microsoft has introduced Shielded Virtual Machines.

How Do Shielded Virtual Machines Work?

Shielded Virtual Machines are based on the following concepts:

  • Code integrity: Code integrity checks whether the Hyper-V hosts meet the criteria to run Shielded Virtual Machines.
  • Virtual Trusted Platform Module (TPM v2): vTPM will allow BitLocker encryption of the VM’s disks. A vTPM device is encrypted with a transport key. Thanks to vTPM, the TPM technology can be used even if the hardware Hyper-V host does not have a physical TPM.
  • Host Guardian Service (HGS): The Host Guardian Service exists in Windows Server 2016. The Host Guardian Service is a host level component that provides two services – attestation and key protection. When a Shielded Virtual Machine is turned on, HGS will check to see if the host is eligible to run the Shielded VM or not.

Shielded VMs offer protection for virtual machines and will ensure that your Hyper-V environment running your Virtual Machines (such as: Domain Controller, SharePoint, Exchange, SQL Server, and so on…) is safe. Moreover, Shielded VMs will only run on an infrastructure you designate.

A picture is worth more than a thousand words; this image from TechNet provides an overview of the full process:

Shielded Virtual Machines in Practice

Let’s see how to implement Shielded VMs in a test environment. This is the environment used in the example explained in this article:

  • DC1: This VM is the Domain Controller for the following AD Forest: GET-CMD.local. The IP Address is 10.0.0.6
  • HYPV1: This is the Hyper-V host that will become a Guarded Host. The IP Address is 10.0.0.5
  • HGS01: This is a standalone HGS Server that will be unclustered because this is a test environment. The IP Address is 10.0.0.4. HGS Will create a standalone Active Directory Forest. In my case, the forest will be named: GET-CMD-HGS.local.
  • Shielded-WinServer2019: This is the Shielded VM based on Windows Server 2019 that will be deployed on the HYPV1 host.

The figure below explains the lab environment for this article.

If you lack sufficient resources to test on your laptop or your server, you can use your Azure subscription. That’s what I did to create my lab environment, and, thanks to Nested Virtualization, it works like a charm. Just remember to use at least Standard Ds_v3 VM size for your Hyper-V host.

Deploying Active Directory and a Guarded Host

Begin this deployment by installing DC1 with an Active Directory domain called GET-CMD.local. I will not provide the PowerShell commands because that is not the goal of this article, but you can easily retrieve the commands on the Internet. Once your AD forest has been successfully created, you must install the Hyper-V role on your Hyper-V host. On HYPV1, run the following command:

If you need more information about PowerShell and Hyper-V, refer to the following article: https://www.red-gate.com/simple-talk/sysadmin/powershell/hyper-v-powershell-basics/

Next, join your Hyper-V host to your AD domain.

Deploying HGS Server

Connect to your HGS Server called HGS1 and install the Host Guardian Server role:

Install the Host Guardian Service by running the following commands. This cmdlet will create a standalone Active Directory Forest with your HGS Server as a primary Domain Controller. You can join this server to an existing AD Domain, but the best practice is to create a new one:

The machine will reboot. Log in with the domain account which is your local administrator account with the same password. Now, you need to generate some certificates in order to initialize the HGS node. In a test environment, consider generating self-signed certificates:

Two certificates have been generated:

  • HGSCert.pfx: This is the certificate for signing
  • encryptCert.pfx: This is the certificate for encryption

Initialize HGS Server

The next step is the initialization process. The Initialize-HGSServer cmdlet will check the status of the Active Directory domain controller and configure both certificates previously created:

You can check to see if the HGS server exists in your AD Domain:

Set the HGS server configuration by switching to the Active Directory Mode:

Note: You could also configure the HGS server to be accessible over HTTPS. You can now create a conditional forwarding that point to the first AD domain:

Create a One-Way trust relationship from the HGS Domain to the Corporate AD Domain:

Confirm that the outbound trust relationship has been created on HGS1:

As expected, the inbound trust relationship exists on DC1 as well.

Configure the Guarded Host – Part 1

Connect to DC1 and create a group called GuardedHosts with Global scope and a Security type. Then add the guarded host server to the newly created group:

You must add conditional forwarding to the HGS domain name. The next task is to get the SID for this AD Group. Run the following command and copy/paste this SID in notepad:

Configure HGS Server – Part 1

Switch back to HGS1 and run the Add-HgsAttestationHostGroup cmdlet:

This command adds the host group called GuardedHosts from the get-cmd.local Active Directory fabric to the Attestation service on HGS1. The Identifier parameter specifies the SID previously stored in notepad. After you run this command, the Attestation service trusts all hosts that belong to this group to host Shielded Virtual Machines. You can check the HGS Attestation Group:

Ok great! AD and HGS are configured. You can now connect to the guarded host.

Configure the Guarded Host – Part 2

You need to create the Code Integrity Policy. This policy will be applied to every machine with the same configuration and is used to prevent unauthorized software from running on the host. First, you need to scan a reference system to create an XML policy file. This should capture most files that Windows needs to boot and run. In my case, the Guarded Host is a fresh and clean install, so I will scan the whole system. Doing so may take a while. If you add or change something on the host, you must start a new scan to update the policy

Then, you will convert the XML file into a .p7b file. If you just want to scan and restrict to a single directory, remember to add the –ScanPath parameter. This command will create the XML file that you will convert into a Device Guard Policy using the the ConvertFrom-CIPolicy cmdlet:

Note: If this cmdlet cannot generate a rule at the specified level, in my case at the FilePublisher level, then this cmdlet attempts to generate it at a fallback level (in my case at the hash level).

Once the binary has been created, copy this file to HGS1.

Configure HGS Server – Part2

On HGS1, run the following command to add the Code Integrity policy to the Attestation service, based on the specified .p7b file.

You must retrieve the AttestationUrl and KeyProtectionUrl to configure the Guarded Host:

Configure the Guarded Host – Part3

Switch back to HYPV1 and configure it to use the Host Guardian Service. This command configures the URLs used by the attestation client and the key protection client:

HYPV1 has switched from HostGuarded:False to HostGuarded:True. It means that you can create and run Shielded VMs on this host. To validate the HGS deployment, run the Get-HgsTrace cmdlet.

Deploy shielded VMs

To confirm that this works, deploy a simple Virtual Machine. Enable the Remote Desktop Protocol because after enabling Shielded Mode on this VM, you will not be able to access to this VM, except through RDP:

After creating a simple VM called Shielded-WinServer2019, confirm that Shielded Mode is disabled:

Enable Shielded Mode on this Virtual Machine:

The VM has been started, and you can confirm that it can’t be accessed to through VMConnect:

Open the settings for this Virtual Machine and confirm that Enable Shielding is selected. At this step, you cannot modify the security settings because the VM is running in a guarded fabric.

What’s new in Windows Server 2019?

Microsoft states that the Shielded VMs concept in Windows Server 2016 was well received by customers, so in Windows Server 2019, Microsoft has extended the Shielded Virtual Machine concept to encompass Linux Virtual Machines. Windows Server 2019 also includes the ability to encrypt network segments. Microsoft has improved troubleshooting of Shielded VMs for Windows Server and Linux. You can for example use PowerShell Direct to connect to Shielded VMs even if you’ve lost network connectivity to these VMs.

Conclusion

In my point of view, Shielded VMs are not very well documented. If you want to implement Shielded VMs in your environment, be sure that all the prerequisites are satisfied, and, if it’s possible, use a testing environment before implementing in production.

Even though it is possible to run the Host Guardian Service on a standalone server, I should advise you to only use Shielded VMs within Hyper-V clusters. Otherwise, in case of a host level failure, the Shielded Virtual Machines could be permanently inaccessible. For those of you who want to test Shielded VMs, you can use nested Hyper-V for testing but not in production. To finish, remember that a shielded VM can exist only on a guarded host, and a shielded VM cannot run on a normal Hyper-V Host. But a normal Virtual Machine, without encryption, can coexist with Shielded VMs on guarded Hyper-V Hosts.