How to deploy a VM template for PAW


Continuing with the PAW series, after you followed the previous blog to build the PAW device, you can now deploy PAW VMs on it. There are two types of VMs you can create:

  • Desktop VM: this is a standard VM, dedicated for user productivity workload. It is typically joined to your org production domain. You can use the same image for deploying the user desktop for this VM.
  • PAW VM: this is a shielded VM, used for secure workload, such as server administration. This image needs to be prepared, such that, any tampering to the image will render the image invalid, and fail to deploy new VMs. The image should contain all the applications, and the OS can be locked down to run only those applications.

If you are part of the PAW TAP program, you can download a couple of templates I created for evaluation.

This blog post walks you through step-by-step on how to deploy a shielded VM template on a PAW device.

Important: you will need a different machine (physical or virtual) to create the template disk and other necessary files. The machine should run Windows 10 1709 client. You can download and installed the RSAT package from here, make sure you select this file: WindowsTH-RSAT_WS2016-x64.msu. (Note that WindowsTH-RSAT_WS_1709-*.msu package will not work).

Once RSAT is installed, these features are added in the start menu: Template Disk Wizard and Shielding Data File Wizard. You can use the Template Disk Wizard to create the VM template disk, and the Shielded Data File Wizard to create the PDK file.

Pre-requisites

You need a template disk created by following this article, which provides the details of how the template disk works to prevent any tampering. The section "Sign and protect the VHDX with the template disk wizard" in the article has the instructions of how to build a template disk.

Creating shielding data file (PDK)

The shielding data file is an encrypted file that the admin creates to protect sensitive information used during deployment, such as user passwords. When provisioning a shielded VM, it requires this file. If you are not familiar with the concept of shielding data file, you can find more details here.

This section illustrates the process specific for a PAW solution.

Prepare necessary files

The PAW PDK files requires the following files:

  • HGS Guardian
  • Windows Unattend file
  • Template disk volume signature

HGS guardian

HGS guardian contains the public key used to encrypt the data on the PAW device. You will need to retrieve the information from the HGS server which the PAW device is attested to. You can run the following PowerShell command on any machine that can connect to the HGS server:

Invoke-WebRequest http://<HGSServer">FQDN>/KeyProtection/service/metadata/2014-07/metadata.xml -OutFile C:\HGSGuardian.xml

If you are using the TAP evaluation image, you can get the PartnerPAWPoCGuardian,xml file from the Yammer group.

Windows Unattend file

Unattend file is critical for provisioning a Shielded VMs, where the VM can only be connected through RDP. In testing, I recommend using Encryption supported policy. You can find the differences between Encryption supported and shielded on "Security level for VMs".

Unattend file varies slightly from different Windows released versions, to make it easy, we created a base unattend file and a cmdlet which can modify it based on the Windows version you want to run. You can get the module from the Powershell Gallery. I attached a copy of sample unattend for Windows client 1709 Enterprise at the end of the blog post, make sure you modify it before use it.

Template disk volume signature

At deployment time, the template disk will be checked against the signature to validate its integrity. If the template has been tampered with, PAW VM creation will fail. The template disk volume signature file captures the disk signature and package it into the PDK file.

You can run the following cmdlet to create the template disk volume signature file:

Save-VolumeSignatureCatalog -TemplateDiskPath <templatefilename.vhdx> -VolumeSignatureCatalogPath <templatefilename.vsc>

As part of TAP, you can download the vsc files through the Yammer group. Be sure the include the right VSC file for the matching template VHDX file, otherwise, VM creation will fail.

Create PDK

You can use the Shielding Data File Wizard to create the PDK file, or using the following cmdlet:

$Owner = New-HgsGuardian -Name 'Owner' -GenerateCertificates
# Import the HGS guardian
$Guardian = Import-HgsGuardian -Path <path to the HGSGuardian.xml> -Name 'PAWHGS' -AllowUntrustedRoot
# Create the PDK file
New-ShieldingDataFile -ShieldingDataFilePath "<name and path of the PDK file, i.e. PAW.pdk>" -Owner $Owner -Guardian $guardian -VolumeIDQualifier (New-VolumeIDQualifier -VolumeSignatureCatalogFilePath "<template disk vsc file>" -VersionRule Equals) -WindowsUnattendFile '<unattend file>' -policy Encryptionsupported

Create PAW VM

Copy the template disk VHDX and the PDK file on the PAW device in the same folder, and run the PAWClientApp to create the VM. You can see the video on how its done here:

If you are using the TAP images, you should place the template disk on the D drive, and make sure you open the Storage setting page of the PAWClientApp, and change the default a location on D.

If you don't have the PAWClientApp, we are releasing a cmdlet module in a couple of weeks to make the shielded VM creation easy.

 

Conclusion

As always, you feedback and questions will help us to make this better. Feel free to share your comment below or email us.

Appendix - Sample unattend.xml

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
  <settings pass="specialize">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ComputerName>@ComputerName@</ComputerName>
    </component>
    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Description>Removes copies of the unattend file to avoid information disclosure. This should be the second to last command to run.</Description>
          <Path>cmd.exe /c "echo del %WINDIR%\Panther\unattend.xml %SYSTEMDRIVE%\unattend.xml /s /f %gt;%gt; %WINDIR%\Setup\Scripts\SetupComplete.cmd"</Path>
        </RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add">
          <Order>2</Order>
          <Description>Shuts down the VM after it has finished provisioning. This should be the last command to run.</Description>
          <Path>cmd.exe /c "echo shutdown /s /f" %gt;%gt; %WINDIR%\Setup\Scripts\SetupComplete.cmd</Path>
          <WillReboot>OnRequest</WillReboot>
        </RunSynchronousCommand>
      </RunSynchronous>
    </component>
    <component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <fDenyTSConnections>false</fDenyTSConnections>
    </component>
    <component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <FirewallGroups>
        <FirewallGroup wcm:action="add" wcm:keyValue="RDGroup">
          <Active>true</Active>
          <Group>@FirewallAPI.dll,-28752</Group>
          <Profile>all</Profile>
        </FirewallGroup>
      </FirewallGroups>
    </component>
    <component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <UserAuthentication>0</UserAuthentication>
    </component>
  </settings>
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <HideLocalAccountScreen>true</HideLocalAccountScreen>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <NetworkLocation>Work</NetworkLocation>
        <SkipUserOOBE>true</SkipUserOOBE>
        <SkipMachineOOBE>true</SkipMachineOOBE>
      </OOBE>
      <UserAccounts>
                <LocalAccounts>
                    <LocalAccount wcm:action="add">
                        <Name>AddValue</Name>
                        <Password>
                            <Value>AddValue</Value>
                            <PlainText>true</PlainText>
                        </Password>
                        <Description>AddValue</Description>
                        <DisplayName>AddValue</DisplayName>
                        <Group>administrators</Group>
                    </LocalAccount>
                </LocalAccounts>
      </UserAccounts>
    </component>
    <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <UserLocale>en-US</UserLocale>
      <SystemLocale>en-US</SystemLocale>
      <UILanguage>en-US</UILanguage>
    </component>
  </settings>
</unattend>

 


Comments (0)

Skip to main content