Build a Windows 10 image with Packer using VMware Workstation

Most of the time I use Packer against a VMware vSphere and Microsoft Azure environment. But sometimes it’s useful to use VMware Workstation for local testing purposes. For building Windows 10 images with Packer and using VMware Workstation there is not much information available. In this blog post, I show how to build a Windows 10 image with Packer and VMware Workstation.

With Packer, the vmware-iso builder is used for creating images with VMware Workstation/Fusion.  In this example I create a Windows 10 image with the latest VMware Tools installed, the installation of the Evergreen module, and automatically install the latest Windows updates.

Pre-requisites

  • Windows a 10 ISO file. You can use this link for downloading the latest Windows 10 ISO for example
  • Install VMware Workstation. I use VMware Workstation Pro 16.x
  • The newly created image must be able to access the internet for  downloading the latest VMware Tools version
  • During my first deployment, the following build issue occurred Build “Could not determine network mappings from files in the path: C:/Program Files (x86)/VMware/VMware Workstation“. Colin Westwater of vGemba.net has blogged about a solution that can be found here, link.
  • Use NAT in VMware Workstation.

Steps

  • Run the following PowerShell script (link). This script does the following things:
    • Create a download folder such as c:\Packer (line 6-17)
    • Download the latest Packer version and unzip the package (line 19-30)
    • Download my Github Packer repository to the local download folder (line 35-39)
    • Create within the download folder the Packer folder structure (line 41-45)
# $ErrorActionPreference = "SilentlyContinue"
# Enable TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Variables
$downloadfolder = 'C:\packer\'
$github = 'https://github.com/ibeerens/Packer/archive/refs/heads/main.zip'

# Create Folder
$checkdir = Test-Path -Path $downloadfolder
if ($checkdir -eq $false){
    Write-Verbose "Creating '$downloadfolder' folder"
    New-Item -Path $downloadfolder -ItemType Directory | Out-Null
}
else {
    Write-Verbose "Folder '$downloadfolder' already exists."
}

# Download the latest Packer version
$product='packer'
$packurl = Invoke-WebRequest -Uri https://www.$product.io/downloads.html | Select-Object -Expand links | Where-Object href -match "//releases\.hashicorp\.com/$product/\d.*/$product_.*_windows_amd64\.zip$" | Select-Object -Expand href
$packdown = $packurl | Split-Path -Leaf
$packdownload = $downloadfolder + $packdown
$webclient = New-object -TypeName System.Net.WebClient
$webclient.DownloadFile($packurl, $packdownload)

# Unzip Packer
Expand-Archive $packdownload -DestinationPath $downloadfolder
# Remove the Packer ZIP file
Remove-Item $packdownload

# Go to the Packer download folder
Set-Location $downloadfolder

# Download Github files
Invoke-WebRequest -Uri $github -OutFile ${downloadfolder}packer.zip
Expand-Archive ${downloadfolder}packer.zip -DestinationPath $downloadfolder
# Remove the packer.zip
Remove-Item -Path ${downloadfolder}packer.zip 

# Create the folder structure
Move-Item ${downloadfolder}Packer-main\workstation\windows10\setup -Destination $downloadfolder
Move-Item ${downloadfolder}Packer-main\workstation\windows10\*.* -Destination $downloadfolder
# Remove the Github structure
Remove-Item -Path ${downloadfolder}Packer-main -Recurse -Confirm:$false -Force
  • Browse to the download folder
  • Open the “win10-std-.auto-pkvars.hcl” file and edit the variables for your needs such as:
    • Line 2: The VM name
    • Line 17: The ISO location
    • Line 19: The ISO checksum. Use the PowerShell Get-Filehash command to get the checksum of the ISO
// VM
vm_name					= 	"GI-W10-001" 
operating_system_vm 	= 	"windows9-64"
vm_firmware				=	"bios"
vm_cdrom_type			=	"ide"
vm_cpus					= 	"2"
vm_cores				= 	"1"
vm_memory				= 	"2048"
vm_disk_controller_type = 	"nvme"
vm_disk_size			= 	"32768"
vm_network_adapter_type =   "e1000e"
// Use the NAT Network
vm_network              =   "VMnet8"
vm_hardwareversion 		= 	"19"

// Removeable media
win10_iso				= 	"c:/iso/en-us_windows_10_business_editions_version_21h2_x64_dvd_ce067768.iso"
// In Powershell use the "get-filehash" command to find the checksum of the ISO
win10_iso_checksum      =   "1323FD1EF0CBFD4BF23FA56A6538FF69DD410AD49969983FEE3DF936A6C811C5"
  • Open the “autounattend.xml” file in the setup folder and check and edit the following lines as needed:
    • Language and keyboard settings
    • Line 84: Administrator Password (must be the same as the winrm_password)
    • Line 92: Autologon Password (must be the same as the winrm_password)
    • Line 141: The ComputerName
  • Edit the build.ps1 file and check the following lines:
    • Line 2: Packer folder location
    • Line 14: The winrm_password matches the administrator password in the autounattended.xml file
# Variables
$downloadfolder = 'C:\packer\'

# Go to the Packer download folder
Set-Location $downloadfolder

# Show Packer Version
.\packer.exe -v

# Download Packer plugins
.\packer.exe init "${downloadfolder}windows.json.pkr.hcl"

# Packer build
.\packer.exe build -force -var-file="${downloadfolder}win10-std.auto.pkrvars.hcl" -var "winrm_username=administrator" -var "winrm_password=ThisisagoodPassword!" "${downloadfolder}windows.json.pkr.hcl"
  • Execute the “build.ps1” file with PowerShell to start the Packer image build process.

  • After a while, the build process finishes and you have a new Windows 10 image deployed with Packer in VMware Workstation.

 

Packer has now virtual TPM (vTPM) device support

In an earlier blogpost called “Use Packer to install Windows 11 and enable vTPM and VBS” I highlighted a workaround for adding a virtual TPM (vTPM) device to a VM in a VMware vSphere environment. A vTPM device is needed for running Windows 11 (without using registry hacks to bypass the TPM device check).

The latest Packer Plugin for VMware vSphere (V1.0.3) has now support for adding a vTPM device. Default a vTPM device is not added to the VM deployed with Packer. So if you want to create a Windows 11 Golden Image for example you can use Packer with the VMware vSphere plugin with a vTPM device.

Here are the high over steps outlined to add a vTPM device when provisioning a new VM with Packer.

    • Download Packer 1.7.9  or later (https://www.packer.io/downloads).
    • Add the VMware vSphere plugin to the HCL configuration file (https://github.com/hashicorp/packer-plugin-vsphere)
packer {
  required_version = ">= 0.0.1"
  required_plugins {
    vsphere = {
      version = ">= 0.0.1"
      source  = "github.com/hashicorp/vsphere"
    }
  }
}
  • Add a variable to enable vTPM
variable "vm_tpm" {
  type = string
  default = "true"
}
  • In the vsphere-iso section, add the vTPM configuration parameter that uses the vm_tpm variable to enable the vTPM device (more options can be found here, link)
source "vsphere-iso" "win11basic" {
  vTPM = "${var.vm_tpm}"
}
  • Perform a packer init command to download the Packer plugin binaries define in the config file
    • packer init config.pkr.hcl
  • Run the packer build command to create the VM
    • packer build config.pkr.hcl

The VM will be created with a vTPM device.

With Packer and the VMware vSphere plugin, it is now possible to create a VM with a vTPM device which is needed for deploying Windows 11 VMs. This is a great improvement!

Use Packer to install Windows 11 and enable vTPM and VBS

I use Packer for building images for VMware VDI environments. With the latest version (when writing this blog Packer version 1.7.7 is the latest version) it is not possible to configure a TPM in the Hashicorp Configuration Languag (HCL) config file. TPM 2.0 is required to install Windows 11. A vTPM emulates a physical TPM 2.0 and is available in VMware vSphere.

Update: January 27, 2022: Packer with the VMware vSphere plugin ((V1.0.3) has now support for adding a vTPM device. More information can be found here: link.

You can install Windows 11 using a registry hack (link) to bypass the TPM check:

reg ADD "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassSecureBootCheck /t REG_DWORD /d 1

vCommunity member Sidney Laan from vEUCaddict wrote a nice blog about using Packer to install Windows 11 using this registry hack (link). When using this hack, it doesn’t enable vTPM or VBS.

For LAB environments, this is no issue but for production, environments you want to have a vTPM enabled and even Virtualization-Based Security (VBS) depending on the security requirements.

So what are TPM and VBS?

TPM

Trusted Platform Module (TPM) technology is designed to provide hardware-based, security-related functions. A TPM chip is a secure crypto-processor that helps you with actions such as generating, storing, and limiting the use of cryptographic keys.

VBS

Virtualization-based security, or VBS, uses hardware virtualization features to create and isolate a secure region of memory from the normal operating system. Windows can use this “virtual secure mode” to host a number of security solutions, providing them with greatly increased protection from vulnerabilities in the operating system, and preventing the use of malicious exploits which attempt to defeat protections.

source link

After the Windows 11 installation with Packer, it is possible to add a vTPM and even enable Virtualization-Based Security (VBS)  by using VMware PowerCLI.

Requirements

  • Use vCenter Server system versions 6.7 or later
  • Add a Key Provider (link)
  • Install PowerCLI by using the following command in PowerShell:
    • Install-Module VMware.PowerCLI -Scope CurrentUser
  • The Windows 11 VM must be powered off
  • Use VM hardware version 14 or higher
  • Don’t create a snapshot with Packer (create_snapshot = false)

PowerCLI Script

The following PowerCLI script can be executed after the Packer Windows 11 deployment. This script adds vTPM, enables VBS support, and creates a snapshot.

  • Change the variables for your environment.

# Import PowerCLI 
Import-Module VMware.PowerCLI

# Variables
$vcentername = "vcentername"
$VMTempName = "VMname"
$snapname = "v0.1"
$snapdescription = "Packer deployement with vTPM and VBS enabled"

# Connect to vCenter Server
Connect-VIServer -Server $vcentername

# Add vTPM
Write-Host 'Set vTPM' 
New-VTpm -VM $VMTempName

# Enable Virtualization Based Security (VBS)
Write-Host 'Enable VBS' 
$vm = Get-VM $VMTempName
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.Firmware = [VMware.Vim.GuestOsDescriptorFirmwareType]::efi
$spec.NestedHVEnabled = $true
$boot = New-Object VMware.Vim.VirtualMachineBootOptions
$boot.EfiSecureBootEnabled = $true
$spec.BootOptions = $boot
$flags = New-Object VMware.Vim.VirtualMachineFlagInfo
$flags.VbsEnabled = $true
$flags.VvtdEnabled = $true
$spec.flags = $flags
$vm.ExtensionData.ReconfigVM($spec)

# Create Snapshot
Write-Host 'Create snapshot' -ForegroundColor green
Get-VM -Name $VMTempName | New-Snapshot -Name $snapname -Description $snapdescription
    
# Disconnect vCenter Server
Disconnect-VIServer -Server * -Confirm:$false
  • When the script is finished, vTPM and VBS support is added
  • Start the VM
  • Check if a TPM is displayed in Device Manager and with the TPM.MSC command

  • Using Powershell the command “Get-TPM” can check the presence of the TPM

    • For Enabling VBS (*1) go to “Device security” in Windows 11, select “Core isolation details” and enable “Memory Integrity”
        • Enabling VBS can also be done by using the following registry settings
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard" /v "EnableVirtualizationBasedSecurity" /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard" /v "RequirePlatformSecurityFeatures" /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard" /v "Locked" /t REG_DWORD /d 0 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity" /v "Enabled" /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity" /v "Locked"

More info: Link

(*1) Adding VBS in Windows 11 can have a performance impact on the VM

  • Reboot the VM

  • When the VM is restarted run “msinfo32”
  • Scroll down and check if “Virtualization-Based Security” is running

Adding the PowerCLI script after the Packer deployment will enable vTPM and VBS for the Windows 11 VM. I hope the vTPM and VBS options will be added soon in Packer so we use the HCL config file without the need for an extra PowerCLI script.