├── .gitignore ├── LICENSE ├── README.md ├── azure-pipelines.yml ├── scripts ├── disable-network-discovery.cmd ├── disable-screensaver.ps1 ├── enable-rdp.cmd ├── enable-winrm.bat ├── enable-winrm.ps1 ├── install-vm-tools.cmd ├── microsoft-updates.bat ├── set-temp.ps1 └── win-updates.ps1 ├── variables.json ├── w2016.base ├── Server2016_vsphere.json └── autounattend.xml ├── w2019.base ├── Server2019_vsphere.json ├── autounattend.xml └── scripts │ ├── disable-network-discovery.cmd │ ├── disable-screensaver.ps1 │ ├── enable-rdp.cmd │ ├── enable-winrm.bat │ ├── enable-winrm.ps1 │ ├── install-vm-tools.cmd │ ├── microsoft-updates.bat │ ├── set-temp.ps1 │ └── win-updates.ps1 └── win10.base ├── Win10_vsphere.json └── autounattend.xml /.gitignore: -------------------------------------------------------------------------------- 1 | variables_* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 thomaspreischl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vpshere_packer_deployments 2 | this repository contains packer scripts to automatically create, preconfigure and deploy vm templates in vmware vsphere 3 | 4 | The Templates for your OS will also prepared for Ansible (WinRM Connection) and updated from Microsoft Update. 5 | 6 | 7 | ## Reqirements 8 | 9 | Before you can create your vmware vsphere templates with this packer deployment scripts, you have to install packer and the required plugins. 10 | 11 | Folow the steps at https://chocolatey.org/install to install chocolatey. 12 | 13 | If you have installed chocolatey, you can install the reqired packages for packer. 14 | 15 | execute the following commands in your Powershell 16 | 17 | `cinst packer -y` 18 | 19 | `choco install Packer-provisioner-windows-update` 20 | 21 | If the required Packages are installed. You can go on with the next steps 22 | 23 | ## Prepare the scripts to make an automated deployment of your vmware vsphere Templates 24 | 25 | 1. Clone the Repository 26 | 2. Upload the desired ISO Files to a Datastore of your vcenter/ vsphere environment 27 | 3. copy the variables.json file and change the setting for your environment 28 | 3. change the password for your autounattend.xml files 29 | 30 | ` YOUR PASSWORD true</PlainText> </Password>` 31 | 32 | and 33 | 34 | `<AdministratorPassword> <Value> YOUR PASSWORD </Value> <PlainText>true</PlainText> </AdministratorPassword>` 35 | 36 | ## Execute the Scripts 37 | 38 | go to the *w***.base* folder 39 | 40 | Execute the scripts as followed: 41 | 42 | `packer build -var-file ..\variables_YOUR_VARFILE.json .\Server2019_vsphere.json` 43 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | # Start with a minimal pipeline that you can customize to build and deploy your code. 3 | # Add steps that build, run tests, deploy, and more: 4 | # https://aka.ms/yaml 5 | 6 | trigger: 7 | branches: 8 | include: 9 | - master 10 | paths: 11 | include: 12 | - vsphere_packer_templates/* 13 | 14 | schedules: 15 | - cron: "0 1 * * 0" 16 | displayName: Weekly Sunday build 17 | branches: 18 | include: 19 | - master 20 | always: true 21 | 22 | pool: 23 | 24 | name: Default 25 | 26 | steps: 27 | 28 | - task: CopyFiles@2 29 | 30 | displayName: 'Copy Packer Files to Artifacts' 31 | 32 | inputs: 33 | 34 | SourceFolder: vsphere_packer_templates 35 | 36 | TargetFolder: '$(Build.ArtifactStagingDirectory)' 37 | cleanTargetFolder: true 38 | 39 | 40 | - task: PublishPipelineArtifact@1 41 | inputs: 42 | targetPath: '$(Build.ArtifactStagingDirectory)' 43 | artifact: PackerConfig -------------------------------------------------------------------------------- /scripts/disable-network-discovery.cmd: -------------------------------------------------------------------------------- 1 | reg ADD HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff /f 2 | netsh advfirewall firewall set rule group="Network Discovery" new enable=No -------------------------------------------------------------------------------- /scripts/disable-screensaver.ps1: -------------------------------------------------------------------------------- 1 | Write-Host "Disabling Screensaver" 2 | Set-ItemProperty "HKCU:\Control Panel\Desktop" -Name ScreenSaveActive -Value 0 -Type DWord 3 | & powercfg -x -monitor-timeout-ac 0 4 | & powercfg -x -monitor-timeout-dc 0 5 | -------------------------------------------------------------------------------- /scripts/enable-rdp.cmd: -------------------------------------------------------------------------------- 1 | netsh advfirewall firewall add rule name="Open Port 3389" dir=in action=allow protocol=TCP localport=3389 2 | reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f -------------------------------------------------------------------------------- /scripts/enable-winrm.bat: -------------------------------------------------------------------------------- 1 | rem Enable-NetFirewallRule for WinRM 2 | netsh advfirewall firewall add rule name="Port 5985" dir=in action=allow protocol=TCP localport=5985 3 | sc.exe config winrm start= auto 4 | -------------------------------------------------------------------------------- /scripts/enable-winrm.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 3.0 2 | 3 | # Configure a Windows host for remote management with Ansible 4 | # ----------------------------------------------------------- 5 | # 6 | # This script checks the current WinRM (PS Remoting) configuration and makes 7 | # the necessary changes to allow Ansible to connect, authenticate and 8 | # execute PowerShell commands. 9 | # 10 | # All events are logged to the Windows EventLog, useful for unattended runs. 11 | # 12 | # Use option -Verbose in order to see the verbose output messages. 13 | # 14 | # Use option -CertValidityDays to specify how long this certificate is valid 15 | # starting from today. So you would specify -CertValidityDays 3650 to get 16 | # a 10-year valid certificate. 17 | # 18 | # Use option -ForceNewSSLCert if the system has been SysPreped and a new 19 | # SSL Certificate must be forced on the WinRM Listener when re-running this 20 | # script. This is necessary when a new SID and CN name is created. 21 | # 22 | # Use option -EnableCredSSP to enable CredSSP as an authentication option. 23 | # 24 | # Use option -DisableBasicAuth to disable basic authentication. 25 | # 26 | # Use option -SkipNetworkProfileCheck to skip the network profile check. 27 | # Without specifying this the script will only run if the device's interfaces 28 | # are in DOMAIN or PRIVATE zones. Provide this switch if you want to enable 29 | # WinRM on a device with an interface in PUBLIC zone. 30 | # 31 | # Use option -SubjectName to specify the CN name of the certificate. This 32 | # defaults to the system's hostname and generally should not be specified. 33 | 34 | # Written by Trond Hindenes <trond@hindenes.com> 35 | # Updated by Chris Church <cchurch@ansible.com> 36 | # Updated by Michael Crilly <mike@autologic.cm> 37 | # Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com> 38 | # Updated by Nicolas Simond <contact@nicolas-simond.com> 39 | # Updated by Dag Wieërs <dag@wieers.com> 40 | # Updated by Jordan Borean <jborean93@gmail.com> 41 | # Updated by Erwan Quélin <erwan.quelin@gmail.com> 42 | # Updated by David Norman <david@dkn.email> 43 | # 44 | # Version 1.0 - 2014-07-06 45 | # Version 1.1 - 2014-11-11 46 | # Version 1.2 - 2015-05-15 47 | # Version 1.3 - 2016-04-04 48 | # Version 1.4 - 2017-01-05 49 | # Version 1.5 - 2017-02-09 50 | # Version 1.6 - 2017-04-18 51 | # Version 1.7 - 2017-11-23 52 | # Version 1.8 - 2018-02-23 53 | # Version 1.9 - 2018-09-21 54 | 55 | # Support -Verbose option 56 | [CmdletBinding()] 57 | 58 | Param ( 59 | [string]$SubjectName = $env:COMPUTERNAME, 60 | [int]$CertValidityDays = 1095, 61 | [switch]$SkipNetworkProfileCheck, 62 | $CreateSelfSignedCert = $true, 63 | [switch]$ForceNewSSLCert, 64 | [switch]$GlobalHttpFirewallAccess, 65 | [switch]$DisableBasicAuth = $false, 66 | [switch]$EnableCredSSP 67 | ) 68 | 69 | Function Write-Log 70 | { 71 | $Message = $args[0] 72 | Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message 73 | } 74 | 75 | Function Write-VerboseLog 76 | { 77 | $Message = $args[0] 78 | Write-Verbose $Message 79 | Write-Log $Message 80 | } 81 | 82 | Function Write-HostLog 83 | { 84 | $Message = $args[0] 85 | Write-Output $Message 86 | Write-Log $Message 87 | } 88 | 89 | Function New-LegacySelfSignedCert 90 | { 91 | Param ( 92 | [string]$SubjectName, 93 | [int]$ValidDays = 1095 94 | ) 95 | 96 | $hostnonFQDN = $env:computerName 97 | $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname 98 | $SignatureAlgorithm = "SHA256" 99 | 100 | $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" 101 | $name.Encode("CN=$SubjectName", 0) 102 | 103 | $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" 104 | $key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider" 105 | $key.KeySpec = 1 106 | $key.Length = 4096 107 | $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" 108 | $key.MachineContext = 1 109 | $key.Create() 110 | 111 | $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" 112 | $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") 113 | $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" 114 | $ekuoids.Add($serverauthoid) 115 | $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" 116 | $ekuext.InitializeEncode($ekuoids) 117 | 118 | $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" 119 | $cert.InitializeFromPrivateKey(2, $key, "") 120 | $cert.Subject = $name 121 | $cert.Issuer = $cert.Subject 122 | $cert.NotBefore = (Get-Date).AddDays(-1) 123 | $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) 124 | 125 | $SigOID = New-Object -ComObject X509Enrollment.CObjectId 126 | $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value) 127 | 128 | [string[]] $AlternativeName += $hostnonFQDN 129 | $AlternativeName += $hostFQDN 130 | $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames 131 | 132 | foreach ($AN in $AlternativeName) 133 | { 134 | $AltName = New-Object -ComObject X509Enrollment.CAlternativeName 135 | $AltName.InitializeFromString(0x3,$AN) 136 | $IAlternativeNames.Add($AltName) 137 | } 138 | 139 | $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames 140 | $SubjectAlternativeName.InitializeEncode($IAlternativeNames) 141 | 142 | [String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment") 143 | $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage 144 | $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage)) 145 | $KeyUsageObj.Critical = $true 146 | 147 | $cert.X509Extensions.Add($KeyUsageObj) 148 | $cert.X509Extensions.Add($ekuext) 149 | $cert.SignatureInformation.HashAlgorithm = $SigOID 150 | $CERT.X509Extensions.Add($SubjectAlternativeName) 151 | $cert.Encode() 152 | 153 | $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" 154 | $enrollment.InitializeFromRequest($cert) 155 | $certdata = $enrollment.CreateRequest(0) 156 | $enrollment.InstallResponse(2, $certdata, 0, "") 157 | 158 | # extract/return the thumbprint from the generated cert 159 | $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 160 | $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata)) 161 | 162 | return $parsed_cert.Thumbprint 163 | } 164 | 165 | Function Enable-GlobalHttpFirewallAccess 166 | { 167 | Write-Verbose "Forcing global HTTP firewall access" 168 | # this is a fairly naive implementation; could be more sophisticated about rule matching/collapsing 169 | $fw = New-Object -ComObject HNetCfg.FWPolicy2 170 | 171 | # try to find/enable the default rule first 172 | $add_rule = $false 173 | $matching_rules = $fw.Rules | Where-Object { $_.Name -eq "Windows Remote Management (HTTP-In)" } 174 | $rule = $null 175 | If ($matching_rules) { 176 | If ($matching_rules -isnot [Array]) { 177 | Write-Verbose "Editing existing single HTTP firewall rule" 178 | $rule = $matching_rules 179 | } 180 | Else { 181 | # try to find one with the All or Public profile first 182 | Write-Verbose "Found multiple existing HTTP firewall rules..." 183 | $rule = $matching_rules | ForEach-Object { $_.Profiles -band 4 }[0] 184 | 185 | If (-not $rule -or $rule -is [Array]) { 186 | Write-Verbose "Editing an arbitrary single HTTP firewall rule (multiple existed)" 187 | # oh well, just pick the first one 188 | $rule = $matching_rules[0] 189 | } 190 | } 191 | } 192 | 193 | If (-not $rule) { 194 | Write-Verbose "Creating a new HTTP firewall rule" 195 | $rule = New-Object -ComObject HNetCfg.FWRule 196 | $rule.Name = "Windows Remote Management (HTTP-In)" 197 | $rule.Description = "Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]" 198 | $add_rule = $true 199 | } 200 | 201 | $rule.Profiles = 0x7FFFFFFF 202 | $rule.Protocol = 6 203 | $rule.LocalPorts = 5985 204 | $rule.RemotePorts = "*" 205 | $rule.LocalAddresses = "*" 206 | $rule.RemoteAddresses = "*" 207 | $rule.Enabled = $true 208 | $rule.Direction = 1 209 | $rule.Action = 1 210 | $rule.Grouping = "Windows Remote Management" 211 | 212 | If ($add_rule) { 213 | $fw.Rules.Add($rule) 214 | } 215 | 216 | Write-Verbose "HTTP firewall rule $($rule.Name) updated" 217 | } 218 | 219 | # Setup error handling. 220 | Trap 221 | { 222 | $_ 223 | Exit 1 224 | } 225 | $ErrorActionPreference = "Stop" 226 | 227 | # Get the ID and security principal of the current user account 228 | $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() 229 | $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) 230 | 231 | # Get the security principal for the Administrator role 232 | $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator 233 | 234 | # Check to see if we are currently running "as Administrator" 235 | if (-Not $myWindowsPrincipal.IsInRole($adminRole)) 236 | { 237 | Write-Output "ERROR: You need elevated Administrator privileges in order to run this script." 238 | Write-Output " Start Windows PowerShell by using the Run as Administrator option." 239 | Exit 2 240 | } 241 | 242 | $EventSource = $MyInvocation.MyCommand.Name 243 | If (-Not $EventSource) 244 | { 245 | $EventSource = "Powershell CLI" 246 | } 247 | 248 | If ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False) 249 | { 250 | New-EventLog -LogName Application -Source $EventSource 251 | } 252 | 253 | # Detect PowerShell version. 254 | If ($PSVersionTable.PSVersion.Major -lt 3) 255 | { 256 | Write-Log "PowerShell version 3 or higher is required." 257 | Throw "PowerShell version 3 or higher is required." 258 | } 259 | 260 | # Find and start the WinRM service. 261 | Write-Verbose "Verifying WinRM service." 262 | If (!(Get-Service "WinRM")) 263 | { 264 | Write-Log "Unable to find the WinRM service." 265 | Throw "Unable to find the WinRM service." 266 | } 267 | ElseIf ((Get-Service "WinRM").Status -ne "Running") 268 | { 269 | Write-Verbose "Setting WinRM service to start automatically on boot." 270 | Set-Service -Name "WinRM" -StartupType Automatic 271 | Write-Log "Set WinRM service to start automatically on boot." 272 | Write-Verbose "Starting WinRM service." 273 | Start-Service -Name "WinRM" -ErrorAction Stop 274 | Write-Log "Started WinRM service." 275 | 276 | } 277 | 278 | # WinRM should be running; check that we have a PS session config. 279 | If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener))) 280 | { 281 | If ($SkipNetworkProfileCheck) { 282 | Write-Verbose "Enabling PS Remoting without checking Network profile." 283 | Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop 284 | Write-Log "Enabled PS Remoting without checking Network profile." 285 | } 286 | Else { 287 | Write-Verbose "Enabling PS Remoting." 288 | Enable-PSRemoting -Force -ErrorAction Stop 289 | Write-Log "Enabled PS Remoting." 290 | } 291 | } 292 | Else 293 | { 294 | Write-Verbose "PS Remoting is already enabled." 295 | } 296 | 297 | # Ensure LocalAccountTokenFilterPolicy is set to 1 298 | # https://github.com/ansible/ansible/issues/42978 299 | $token_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" 300 | $token_prop_name = "LocalAccountTokenFilterPolicy" 301 | $token_key = Get-Item -Path $token_path 302 | $token_value = $token_key.GetValue($token_prop_name, $null) 303 | if ($token_value -ne 1) { 304 | Write-Verbose "Setting LocalAccountTOkenFilterPolicy to 1" 305 | if ($null -ne $token_value) { 306 | Remove-ItemProperty -Path $token_path -Name $token_prop_name 307 | } 308 | New-ItemProperty -Path $token_path -Name $token_prop_name -Value 1 -PropertyType DWORD > $null 309 | } 310 | 311 | # Make sure there is a SSL listener. 312 | $listeners = Get-ChildItem WSMan:\localhost\Listener 313 | If (!($listeners | Where-Object {$_.Keys -like "TRANSPORT=HTTPS"})) 314 | { 315 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 316 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 317 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 318 | 319 | # Create the hashtables of settings to be used. 320 | $valueset = @{ 321 | Hostname = $SubjectName 322 | CertificateThumbprint = $thumbprint 323 | } 324 | 325 | $selectorset = @{ 326 | Transport = "HTTPS" 327 | Address = "*" 328 | } 329 | 330 | Write-Verbose "Enabling SSL listener." 331 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 332 | Write-Log "Enabled SSL listener." 333 | } 334 | Else 335 | { 336 | Write-Verbose "SSL listener is already active." 337 | 338 | # Force a new SSL cert on Listener if the $ForceNewSSLCert 339 | If ($ForceNewSSLCert) 340 | { 341 | 342 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 343 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 344 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 345 | 346 | $valueset = @{ 347 | CertificateThumbprint = $thumbprint 348 | Hostname = $SubjectName 349 | } 350 | 351 | # Delete the listener for SSL 352 | $selectorset = @{ 353 | Address = "*" 354 | Transport = "HTTPS" 355 | } 356 | Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset 357 | 358 | # Add new Listener with new SSL cert 359 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 360 | } 361 | } 362 | 363 | # Check for basic authentication. 364 | $basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object {$_.Name -eq "Basic"} 365 | 366 | If ($DisableBasicAuth) 367 | { 368 | If (($basicAuthSetting.Value) -eq $true) 369 | { 370 | Write-Verbose "Disabling basic auth support." 371 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $false 372 | Write-Log "Disabled basic auth support." 373 | } 374 | Else 375 | { 376 | Write-Verbose "Basic auth is already disabled." 377 | } 378 | } 379 | Else 380 | { 381 | If (($basicAuthSetting.Value) -eq $false) 382 | { 383 | Write-Verbose "Enabling basic auth support." 384 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true 385 | Write-Log "Enabled basic auth support." 386 | } 387 | Else 388 | { 389 | Write-Verbose "Basic auth is already enabled." 390 | } 391 | } 392 | 393 | # If EnableCredSSP if set to true 394 | If ($EnableCredSSP) 395 | { 396 | # Check for CredSSP authentication 397 | $credsspAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object {$_.Name -eq "CredSSP"} 398 | If (($credsspAuthSetting.Value) -eq $false) 399 | { 400 | Write-Verbose "Enabling CredSSP auth support." 401 | Enable-WSManCredSSP -role server -Force 402 | Write-Log "Enabled CredSSP auth support." 403 | } 404 | } 405 | 406 | If ($GlobalHttpFirewallAccess) { 407 | Enable-GlobalHttpFirewallAccess 408 | } 409 | 410 | # Configure firewall to allow WinRM HTTPS connections. 411 | $fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" 412 | $fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any 413 | If ($fwtest1.count -lt 5) 414 | { 415 | Write-Verbose "Adding firewall rule to allow WinRM HTTPS." 416 | netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow 417 | Write-Log "Added firewall rule to allow WinRM HTTPS." 418 | } 419 | ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5)) 420 | { 421 | Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile." 422 | netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any 423 | Write-Log "Updated firewall rule to allow WinRM HTTPS for any profile." 424 | } 425 | Else 426 | { 427 | Write-Verbose "Firewall rule already exists to allow WinRM HTTPS." 428 | } 429 | 430 | # Test a remoting connection to localhost, which should work. 431 | $httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue 432 | $httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck 433 | 434 | $httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue 435 | 436 | If ($httpResult -and $httpsResult) 437 | { 438 | Write-Verbose "HTTP: Enabled | HTTPS: Enabled" 439 | } 440 | ElseIf ($httpsResult -and !$httpResult) 441 | { 442 | Write-Verbose "HTTP: Disabled | HTTPS: Enabled" 443 | } 444 | ElseIf ($httpResult -and !$httpsResult) 445 | { 446 | Write-Verbose "HTTP: Enabled | HTTPS: Disabled" 447 | } 448 | Else 449 | { 450 | Write-Log "Unable to establish an HTTP or HTTPS remoting session." 451 | Throw "Unable to establish an HTTP or HTTPS remoting session." 452 | } 453 | Write-VerboseLog "PS Remoting has been successfully configured for Ansible." -------------------------------------------------------------------------------- /scripts/install-vm-tools.cmd: -------------------------------------------------------------------------------- 1 | @rem Silent mode, basic UI, no reboot 2 | e:\setup64 /s /v "/qb REBOOT=R" -------------------------------------------------------------------------------- /scripts/microsoft-updates.bat: -------------------------------------------------------------------------------- 1 | net stop wuauserv 2 | 3 | reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v EnableFeaturedSoftware /t REG_DWORD /d 1 /f 4 | 5 | reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v IncludeRecommendedUpdates /t REG_DWORD /d 1 /f 6 | 7 | echo Set ServiceManager = CreateObject("Microsoft.Update.ServiceManager") > A:\temp.vbs 8 | echo Set NewUpdateService = ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",7,"") >> A:\temp.vbs 9 | 10 | cscript A:\temp.vbs 11 | 12 | net start wuauserv 13 | -------------------------------------------------------------------------------- /scripts/set-temp.ps1: -------------------------------------------------------------------------------- 1 | # Set Temp Variable using PowerShell 2 | 3 | $TempFolder = "C:\TEMP" 4 | New-Item -ItemType Directory -Force -Path $TempFolder 5 | [Environment]::SetEnvironmentVariable("TEMP", $TempFolder, [EnvironmentVariableTarget]::Machine) 6 | [Environment]::SetEnvironmentVariable("TMP", $TempFolder, [EnvironmentVariableTarget]::Machine) 7 | [Environment]::SetEnvironmentVariable("TEMP", $TempFolder, [EnvironmentVariableTarget]::User) 8 | [Environment]::SetEnvironmentVariable("TMP", $TempFolder, [EnvironmentVariableTarget]::User) -------------------------------------------------------------------------------- /scripts/win-updates.ps1: -------------------------------------------------------------------------------- 1 | param($global:RestartRequired=0, 2 | $global:MoreUpdates=0, 3 | $global:MaxCycles=5, 4 | $MaxUpdatesPerCycle=500, 5 | $BeginWithRestart=0) 6 | 7 | $Logfile = "C:\Windows\Temp\win-updates.log" 8 | 9 | function LogWrite { 10 | Param ([string]$logstring) 11 | $now = Get-Date -format s 12 | Add-Content $Logfile -value "$now $logstring" 13 | Write-Output $logstring 14 | } 15 | 16 | function Check-ContinueRestartOrEnd() { 17 | $RegistryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 18 | $RegistryEntry = "InstallWindowsUpdates" 19 | switch ($global:RestartRequired) { 20 | 0 { 21 | $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry 22 | if ($prop) { 23 | LogWrite "Restart Registry Entry Exists - Removing It" 24 | Remove-ItemProperty -Path $RegistryKey -Name $RegistryEntry -ErrorAction SilentlyContinue 25 | } 26 | 27 | LogWrite "No Restart Required" 28 | Check-WindowsUpdates 29 | 30 | if (($global:MoreUpdates -eq 1) -and ($script:Cycles -le $global:MaxCycles)) { 31 | Install-WindowsUpdates 32 | } elseif ($script:Cycles -gt $global:MaxCycles) { 33 | LogWrite "Exceeded Cycle Count - Stopping" 34 | & "a:\enable-winrm.ps1" 35 | } else { 36 | LogWrite "Done Installing Windows Updates" 37 | & "a:\enable-winrm.ps1" 38 | } 39 | } 40 | 1 { 41 | $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry 42 | if (-not $prop) { 43 | LogWrite "Restart Registry Entry Does Not Exist - Creating It" 44 | Set-ItemProperty -Path $RegistryKey -Name $RegistryEntry -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File $($script:ScriptPath) -MaxUpdatesPerCycle $($MaxUpdatesPerCycle)" 45 | } else { 46 | LogWrite "Restart Registry Entry Exists Already" 47 | } 48 | 49 | LogWrite "Restart Required - Restarting..." 50 | Restart-Computer 51 | } 52 | default { 53 | LogWrite "Unsure If A Restart Is Required" 54 | break 55 | } 56 | } 57 | } 58 | 59 | function Install-WindowsUpdates() { 60 | $script:Cycles++ 61 | LogWrite "Evaluating Available Updates with limit of $($MaxUpdatesPerCycle):" 62 | $UpdatesToDownload = New-Object -ComObject 'Microsoft.Update.UpdateColl' 63 | $script:i = 0; 64 | $CurrentUpdates = $SearchResult.Updates 65 | while($script:i -lt $CurrentUpdates.Count -and $script:CycleUpdateCount -lt $MaxUpdatesPerCycle) { 66 | $Update = $CurrentUpdates.Item($script:i) 67 | if ($null -ne $Update) { 68 | [bool]$addThisUpdate = $false 69 | if ($Update.InstallationBehavior.CanRequestUserInput) { 70 | LogWrite "> Skipping: $($Update.Title) because it requires user input" 71 | } else { 72 | if (!($Update.EulaAccepted)) { 73 | LogWrite "> Note: $($Update.Title) has a license agreement that must be accepted. Accepting the license." 74 | $Update.AcceptEula() 75 | [bool]$addThisUpdate = $true 76 | $script:CycleUpdateCount++ 77 | } else { 78 | [bool]$addThisUpdate = $true 79 | $script:CycleUpdateCount++ 80 | } 81 | } 82 | 83 | if ([bool]$addThisUpdate) { 84 | LogWrite "Adding: $($Update.Title)" 85 | $UpdatesToDownload.Add($Update) |Out-Null 86 | } 87 | } 88 | $script:i++ 89 | } 90 | 91 | if ($UpdatesToDownload.Count -eq 0) { 92 | LogWrite "No Updates To Download..." 93 | } else { 94 | LogWrite 'Downloading Updates...' 95 | $ok = 0; 96 | while (! $ok) { 97 | try { 98 | $Downloader = $UpdateSession.CreateUpdateDownloader() 99 | $Downloader.Updates = $UpdatesToDownload 100 | $Downloader.Download() 101 | $ok = 1; 102 | } catch { 103 | LogWrite $_.Exception | Format-List -force 104 | LogWrite "Error downloading updates. Retrying in 30s." 105 | $script:attempts = $script:attempts + 1 106 | Start-Sleep -s 30 107 | } 108 | } 109 | } 110 | 111 | $UpdatesToInstall = New-Object -ComObject 'Microsoft.Update.UpdateColl' 112 | [bool]$rebootMayBeRequired = $false 113 | LogWrite 'The following updates are downloaded and ready to be installed:' 114 | foreach ($Update in $SearchResult.Updates) { 115 | if (($Update.IsDownloaded)) { 116 | LogWrite "> $($Update.Title)" 117 | $UpdatesToInstall.Add($Update) |Out-Null 118 | 119 | if ($Update.InstallationBehavior.RebootBehavior -gt 0){ 120 | [bool]$rebootMayBeRequired = $true 121 | } 122 | } 123 | } 124 | 125 | if ($UpdatesToInstall.Count -eq 0) { 126 | LogWrite 'No updates available to install...' 127 | $global:MoreUpdates=0 128 | $global:RestartRequired=0 129 | & "a:\enable-winrm.ps1" 130 | break 131 | } 132 | 133 | if ($rebootMayBeRequired) { 134 | LogWrite 'These updates may require a reboot' 135 | $global:RestartRequired=1 136 | } 137 | 138 | LogWrite 'Installing updates...' 139 | 140 | $Installer = $script:UpdateSession.CreateUpdateInstaller() 141 | $Installer.Updates = $UpdatesToInstall 142 | $InstallationResult = $Installer.Install() 143 | 144 | LogWrite "Installation Result: $($InstallationResult.ResultCode)" 145 | LogWrite "Reboot Required: $($InstallationResult.RebootRequired)" 146 | LogWrite 'Listing of updates installed and individual installation results:' 147 | if ($InstallationResult.RebootRequired) { 148 | $global:RestartRequired=1 149 | } else { 150 | $global:RestartRequired=0 151 | } 152 | 153 | for($i=0; $i -lt $UpdatesToInstall.Count; $i++) { 154 | New-Object -TypeName PSObject -Property @{ 155 | Title = $UpdatesToInstall.Item($i).Title 156 | Result = $InstallationResult.GetUpdateResult($i).ResultCode 157 | } 158 | LogWrite "Item: $($UpdatesToInstall.Item($i).Title)" 159 | LogWrite "Result: $($InstallationResult.GetUpdateResult($i).ResultCode)" 160 | } 161 | 162 | Check-ContinueRestartOrEnd 163 | } 164 | 165 | function Check-WindowsUpdates() { 166 | LogWrite "Checking For Windows Updates" 167 | $Username = $env:USERDOMAIN + "\" + $env:USERNAME 168 | LogWrite "Script: $script:ScriptPath `nScript User: $Username `nStarted: $(Get-Date)" 169 | 170 | $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher() 171 | $script:successful = $FALSE 172 | $script:attempts = 0 173 | $script:maxAttempts = 12 174 | while(-not $script:successful -and $script:attempts -lt $script:maxAttempts) { 175 | try { 176 | $script:SearchResult = $script:UpdateSearcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0") 177 | $script:successful = $TRUE 178 | } catch { 179 | LogWrite $_.Exception | Format-List -force 180 | LogWrite "Search call to UpdateSearcher was unsuccessful. Retrying in 10s." 181 | $script:attempts = $script:attempts + 1 182 | Start-Sleep -s 10 183 | } 184 | } 185 | 186 | if ($SearchResult.Updates.Count -ne 0) { 187 | $Message = "There are " + $SearchResult.Updates.Count + " more updates." 188 | LogWrite $Message 189 | try { 190 | for($i=0; $i -lt $script:SearchResult.Updates.Count; $i++) { 191 | LogWrite $script:SearchResult.Updates.Item($i).Title 192 | LogWrite $script:SearchResult.Updates.Item($i).Description 193 | LogWrite $script:SearchResult.Updates.Item($i).RebootRequired 194 | LogWrite $script:SearchResult.Updates.Item($i).EulaAccepted 195 | } 196 | $global:MoreUpdates=1 197 | } catch { 198 | LogWrite $_.Exception | Format-List -force 199 | LogWrite "Showing SearchResult was unsuccessful. Rebooting." 200 | $global:RestartRequired=1 201 | $global:MoreUpdates=0 202 | Check-ContinueRestartOrEnd 203 | LogWrite "Show never happen to see this text!" 204 | Restart-Computer 205 | } 206 | } else { 207 | LogWrite 'There are no applicable updates' 208 | $global:RestartRequired=0 209 | $global:MoreUpdates=0 210 | } 211 | } 212 | 213 | $script:ScriptName = $MyInvocation.MyCommand.ToString() 214 | $script:ScriptPath = $MyInvocation.MyCommand.Path 215 | $script:UpdateSession = New-Object -ComObject 'Microsoft.Update.Session' 216 | $script:UpdateSession.ClientApplicationID = 'Packer Windows Update Installer' 217 | $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher() 218 | $script:SearchResult = New-Object -ComObject 'Microsoft.Update.UpdateColl' 219 | $script:Cycles = 0 220 | $script:CycleUpdateCount = 0 221 | 222 | if ($BeginWithRestart) { 223 | $global:RestartRequired = 1 224 | Check-ContinueRestartOrEnd 225 | } 226 | 227 | Check-WindowsUpdates 228 | if ($global:MoreUpdates -eq 1) { 229 | Install-WindowsUpdates 230 | } else { 231 | Check-ContinueRestartOrEnd 232 | } 233 | -------------------------------------------------------------------------------- /variables.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | 4 | "vsphere-server": "192.168.2.3", 5 | "vsphere-user": "administrator@vsphere.local", 6 | "vsphere-password": "YOUR_Password", 7 | 8 | "vsphere-datacenter": "YOUR_Dataceneter", 9 | "vsphere-cluster": "YOUR_Cluster", 10 | "vsphere-network": "YOUR_Network", 11 | "vsphere-datastore": "Your_Datastore", 12 | "vsphere-folder": "Your_vmfolder", 13 | 14 | "vm-name": "Win2019-Template-Base", 15 | "vm-cpu-num": "2", 16 | "vm-mem-size": "4096", 17 | "vm-disk-size": "40960", 18 | "winadmin-password": "Your WindowsPassword", 19 | "os_iso_path": "[VNX5300_Auto-Tier_LUN1] ISO/Windows Server 2019/SW_DVD9_Win_Server_STD_CORE_2019_64Bit_German_DC_STD_MLF_X21-96583.ISO", 20 | "winrm_username": "Administrator" 21 | 22 | 23 | 24 | } -------------------------------------------------------------------------------- /w2016.base/Server2016_vsphere.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | 4 | "sensitive-variables": ["vsphere_password", "winadmin_password"], 5 | 6 | "builders": [ 7 | { 8 | "type": "vsphere-iso", 9 | 10 | "vcenter_server": "{{user `vsphere-server`}}", 11 | "username": "{{user `vsphere-user`}}", 12 | "password": "{{user `vsphere-password`}}", 13 | "insecure_connection": "true", 14 | 15 | "datacenter": "{{user `vsphere-datacenter`}}", 16 | "cluster": "{{user `vsphere-cluster`}}", 17 | "network": "{{user `vsphere-network`}}", 18 | "datastore": "{{user `vsphere-datastore`}}", 19 | "folder": "{{user `vsphere-folder`}}", 20 | 21 | "communicator": "winrm", 22 | "winrm_use_ssl":"true", 23 | "winrm_insecure": "true", 24 | "winrm_username": "{{user `winrm_username`}}", 25 | "winrm_password": "{{user `winadmin-password`}}", 26 | 27 | "convert_to_template": "true", 28 | 29 | "vm_name": "{{user `vm-name`}}", 30 | "guest_os_type": "windows9Server64Guest", 31 | 32 | "CPUs": "{{user `vm-cpu-num`}}", 33 | "RAM": "{{user `vm-mem-size`}}", 34 | "RAM_reserve_all": true, 35 | "firmware": "bios", 36 | 37 | "disk_controller_type": "lsilogic-sas", 38 | "disk_size": "{{user `vm-disk-size`}}", 39 | "disk_thin_provisioned": true, 40 | 41 | "network_card": "vmxnet3", 42 | 43 | "iso_paths": [ 44 | "{{user `os_iso_path`}}", 45 | "[] /vmimages/tools-isoimages/windows.iso" 46 | ], 47 | 48 | "floppy_files": [ 49 | "autounattend.xml", 50 | "../scripts/disable-network-discovery.cmd", 51 | "../scripts/enable-rdp.cmd", 52 | "../scripts/enable-winrm.ps1", 53 | "../scripts/install-vm-tools.cmd", 54 | "../scripts/set-temp.ps1", 55 | "../scripts/microsoft-updates.bat", 56 | "../scripts/win-updates.ps1", 57 | "../scripts/disable-screensaver.ps1" 58 | ] 59 | } 60 | 61 | ], 62 | "provisioners": [ 63 | { 64 | "type": "windows-restart", 65 | "restart_timeout": "30m" 66 | }, 67 | 68 | { 69 | "type": "windows-update", 70 | "search_criteria": "IsInstalled=0", 71 | "filters": [ 72 | "exclude:$_.Title -like '*Preview*'", 73 | "exclude:$_.Title -like '*Cumulative*'", 74 | "exclude:$_.Title -like '*Kumulatives*'", 75 | "exclude:$_.Title -like '*VMware*'", 76 | "exclude:$_.Title -like '*Defender*'", 77 | "include:$true" 78 | ], 79 | "pause_before": "30s" 80 | }, 81 | { 82 | "type": "windows-restart" 83 | } 84 | 85 | 86 | ] 87 | 88 | 89 | } -------------------------------------------------------------------------------- /w2016.base/autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <settings pass="windowsPE"> 4 | <component name="Microsoft-Windows-International-Core-WinPE" 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"> 5 | <SetupUILanguage> 6 | <UILanguage>de-DE</UILanguage> 7 | </SetupUILanguage> 8 | <InputLocale>de-DE</InputLocale> 9 | <SystemLocale>de-DE</SystemLocale> 10 | <UILanguage>de-DE</UILanguage> 11 | <UserLocale>de-DE</UserLocale> 12 | </component> 13 | <component name="Microsoft-Windows-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"> 14 | <DiskConfiguration> 15 | <Disk wcm:action="add"> 16 | <CreatePartitions> 17 | <CreatePartition wcm:action="add"> 18 | <Order>1</Order> 19 | <Size>500</Size> 20 | <Type>Primary</Type> 21 | </CreatePartition> 22 | <CreatePartition wcm:action="add"> 23 | <Order>2</Order> 24 | <Extend>true</Extend> 25 | <Type>Primary</Type> 26 | </CreatePartition> 27 | </CreatePartitions> 28 | <ModifyPartitions> 29 | <ModifyPartition wcm:action="add"> 30 | <Order>1</Order> 31 | <PartitionID>1</PartitionID> 32 | <Format>NTFS</Format> 33 | <Label>Boot</Label> 34 | <Active>true</Active> 35 | </ModifyPartition> 36 | <ModifyPartition wcm:action="add"> 37 | <Order>2</Order> 38 | <PartitionID>2</PartitionID> 39 | <Format>NTFS</Format> 40 | <Label>System</Label> 41 | </ModifyPartition> 42 | </ModifyPartitions> 43 | <DiskID>0</DiskID> 44 | <WillWipeDisk>true</WillWipeDisk> 45 | </Disk> 46 | </DiskConfiguration> 47 | <ImageInstall> 48 | <OSImage> 49 | <InstallFrom> 50 | <MetaData wcm:action="add"> 51 | <Key>/IMAGE/NAME</Key> 52 | <Value>Windows Server 2016 SERVERSTANDARD</Value> 53 | </MetaData> 54 | </InstallFrom> 55 | <InstallTo> 56 | <DiskID>0</DiskID> 57 | <PartitionID>2</PartitionID> 58 | </InstallTo> 59 | <WillShowUI>OnError</WillShowUI> 60 | <InstallToAvailablePartition>false</InstallToAvailablePartition> 61 | </OSImage> 62 | </ImageInstall> 63 | <UserData> 64 | <AcceptEula>true</AcceptEula> 65 | </UserData> 66 | </component> 67 | </settings> 68 | <settings pass="specialize"> 69 | <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"> 70 | <TimeZone>W. Europe Standard Time</TimeZone> 71 | </component> 72 | <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"> 73 | <RunSynchronous> 74 | <RunSynchronousCommand wcm:action="add"> 75 | <Order>1</Order> 76 | <Description>Disable Network Discovery</Description> 77 | <Path>cmd.exe /c a:\disable-network-discovery.cmd</Path> 78 | </RunSynchronousCommand> 79 | </RunSynchronous> 80 | </component> 81 | </settings> 82 | <settings pass="oobeSystem"> 83 | <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"> 84 | <AutoLogon> 85 | <Password> 86 | <Value>Lab2020</Value> 87 | <PlainText>true</PlainText> 88 | </Password> 89 | <LogonCount>2</LogonCount> 90 | <Username>Administrator</Username> 91 | <Enabled>true</Enabled> 92 | </AutoLogon> 93 | <FirstLogonCommands> 94 | <SynchronousCommand wcm:action="add"> 95 | <Order>1</Order> 96 | <Description>Set Execution Policy 64 Bit</Description> 97 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 98 | <RequiresUserInput>true</RequiresUserInput> 99 | </SynchronousCommand> 100 | <SynchronousCommand wcm:action="add"> 101 | <Order>2</Order> 102 | <Description>Set Execution Policy 32 Bit</Description> 103 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 104 | <RequiresUserInput>true</RequiresUserInput> 105 | </SynchronousCommand> 106 | <SynchronousCommand wcm:action="add"> 107 | <Order>3</Order> 108 | <Description>Disable WinRM</Description> 109 | <CommandLine>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\disable-winrm.ps1</CommandLine> 110 | <RequiresUserInput>true</RequiresUserInput> 111 | </SynchronousCommand> 112 | <SynchronousCommand wcm:action="add"> 113 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 114 | <Order>4</Order> 115 | <Description>Show file extensions in Explorer</Description> 116 | </SynchronousCommand> 117 | <SynchronousCommand wcm:action="add"> 118 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> 119 | <Order>5</Order> 120 | <Description>Enable QuickEdit mode</Description> 121 | </SynchronousCommand> 122 | <SynchronousCommand wcm:action="add"> 123 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> 124 | <Order>6</Order> 125 | <Description>Show Run command in Start Menu</Description> 126 | </SynchronousCommand> 127 | <SynchronousCommand wcm:action="add"> 128 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> 129 | <Order>7</Order> 130 | <Description>Show Administrative Tools in Start Menu</Description> 131 | </SynchronousCommand> 132 | <SynchronousCommand wcm:action="add"> 133 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 134 | <Order>8</Order> 135 | <Description>Zero Hibernation File</Description> 136 | </SynchronousCommand> 137 | <SynchronousCommand wcm:action="add"> 138 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 139 | <Order>9</Order> 140 | <Description>Disable Hibernation Mode</Description> 141 | </SynchronousCommand> 142 | <SynchronousCommand wcm:action="add"> 143 | <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> 144 | <Order>10</Order> 145 | <Description>Disable password expiration for Administrator user</Description> 146 | </SynchronousCommand> 147 | <SynchronousCommand wcm:action="add"> 148 | <CommandLine>cmd.exe /c a:\install-vm-tools.cmd</CommandLine> 149 | <Order>14</Order> 150 | <Description>Install VMware Tools</Description> 151 | </SynchronousCommand> 152 | <SynchronousCommand wcm:action="add"> 153 | <CommandLine>cmd.exe /c a:\enable-rdp.cmd</CommandLine> 154 | <Order>12</Order> 155 | <Description>Enable RDP</Description> 156 | </SynchronousCommand> 157 | <SynchronousCommand wcm:action="add"> 158 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\set-temp.ps1</CommandLine> 159 | <Order>13</Order> 160 | <Description>Set Temp Folders</Description> 161 | </SynchronousCommand> 162 | 163 | 164 | <SynchronousCommand wcm:action="add"> 165 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\enable-winrm.ps1</CommandLine> 166 | <Description>Enable WinRM</Description> 167 | <Order>16</Order> 168 | </SynchronousCommand> 169 | 170 | </FirstLogonCommands> 171 | <OOBE> 172 | <HideEULAPage>true</HideEULAPage> 173 | <HideLocalAccountScreen>true</HideLocalAccountScreen> 174 | <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> 175 | <HideOnlineAccountScreens>true</HideOnlineAccountScreens> 176 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 177 | <NetworkLocation>Home</NetworkLocation> 178 | <ProtectYourPC>1</ProtectYourPC> 179 | </OOBE> 180 | 181 | <UserAccounts> 182 | <AdministratorPassword> 183 | <Value>Lab2020</Value> 184 | <PlainText>true</PlainText> 185 | </AdministratorPassword> 186 | </UserAccounts> 187 | </component> 188 | </settings> 189 | <cpi:offlineImage cpi:source="wim:c:/wim/install.wim#Windows Server 2019 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> 190 | </unattend> -------------------------------------------------------------------------------- /w2019.base/Server2019_vsphere.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | 4 | "sensitive-variables": ["vsphere_password", "winadmin_password"], 5 | 6 | "builders": [ 7 | { 8 | "type": "vsphere-iso", 9 | 10 | "vcenter_server": "{{user `vsphere-server`}}", 11 | "username": "{{user `vsphere-user`}}", 12 | "password": "{{user `vsphere-password`}}", 13 | "insecure_connection": "true", 14 | 15 | "datacenter": "{{user `vsphere-datacenter`}}", 16 | "cluster": "{{user `vsphere-cluster`}}", 17 | "network": "{{user `vsphere-network`}}", 18 | "datastore": "{{user `vsphere-datastore`}}", 19 | "folder": "{{user `vsphere-folder`}}", 20 | 21 | "communicator": "winrm", 22 | "winrm_use_ssl":"true", 23 | "winrm_insecure": "true", 24 | "winrm_username": "{{user `winrm_username`}}", 25 | "winrm_password": "{{user `winadmin-password`}}", 26 | 27 | "convert_to_template": "true", 28 | 29 | "vm_name": "{{user `vm-name`}}", 30 | "guest_os_type": "windows9Server64Guest", 31 | 32 | "CPUs": "{{user `vm-cpu-num`}}", 33 | "RAM": "{{user `vm-mem-size`}}", 34 | "RAM_reserve_all": true, 35 | "firmware": "bios", 36 | 37 | "disk_controller_type": "lsilogic-sas", 38 | "disk_size": "{{user `vm-disk-size`}}", 39 | "disk_thin_provisioned": true, 40 | 41 | "network_card": "vmxnet3", 42 | 43 | "iso_paths": [ 44 | "{{user `os_iso_path`}}", 45 | "[] /vmimages/tools-isoimages/windows.iso" 46 | ], 47 | 48 | "floppy_files": [ 49 | "{{template_dir}}/autounattend.xml", 50 | "{{template_dir}}/scripts/disable-network-discovery.cmd", 51 | "{{template_dir}}/scripts/enable-rdp.cmd", 52 | "{{template_dir}}/scripts/enable-winrm.ps1", 53 | "{{template_dir}}/scripts/install-vm-tools.cmd", 54 | "{{template_dir}}/scripts/set-temp.ps1", 55 | "{{template_dir}}/scripts/microsoft-updates.bat", 56 | "{{template_dir}}/scripts/win-updates.ps1", 57 | "{{template_dir}}/scripts/disable-screensaver.ps1" 58 | ] 59 | } 60 | ], 61 | "provisioners": [ 62 | { 63 | "type": "windows-restart", 64 | "restart_timeout": "30m" 65 | }, 66 | 67 | { 68 | "type": "windows-update", 69 | "search_criteria": "IsInstalled=0", 70 | "filters": [ 71 | "exclude:$_.Title -like '*Preview*'", 72 | "exclude:$_.Title -like '*Cumulative*'", 73 | "exclude:$_.Title -like '*Kumulatives*'", 74 | "exclude:$_.Title -like '*VMware*'", 75 | "exclude:$_.Title -like '*Defender*'", 76 | "include:$true" 77 | ], 78 | "pause_before": "30s" 79 | }, 80 | { 81 | "type": "windows-restart" 82 | } 83 | 84 | 85 | ] 86 | 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /w2019.base/autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <settings pass="windowsPE"> 4 | <component name="Microsoft-Windows-International-Core-WinPE" 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"> 5 | <SetupUILanguage> 6 | <UILanguage>de-DE</UILanguage> 7 | </SetupUILanguage> 8 | <InputLocale>de-DE</InputLocale> 9 | <SystemLocale>de-DE</SystemLocale> 10 | <UILanguage>de-DE</UILanguage> 11 | <UserLocale>de-DE</UserLocale> 12 | </component> 13 | <component name="Microsoft-Windows-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"> 14 | <DiskConfiguration> 15 | <Disk wcm:action="add"> 16 | <CreatePartitions> 17 | <CreatePartition wcm:action="add"> 18 | <Order>1</Order> 19 | <Size>500</Size> 20 | <Type>Primary</Type> 21 | </CreatePartition> 22 | <CreatePartition wcm:action="add"> 23 | <Order>2</Order> 24 | <Extend>true</Extend> 25 | <Type>Primary</Type> 26 | </CreatePartition> 27 | </CreatePartitions> 28 | <ModifyPartitions> 29 | <ModifyPartition wcm:action="add"> 30 | <Order>1</Order> 31 | <PartitionID>1</PartitionID> 32 | <Format>NTFS</Format> 33 | <Label>Boot</Label> 34 | <Active>true</Active> 35 | </ModifyPartition> 36 | <ModifyPartition wcm:action="add"> 37 | <Order>2</Order> 38 | <PartitionID>2</PartitionID> 39 | <Format>NTFS</Format> 40 | <Label>System</Label> 41 | </ModifyPartition> 42 | </ModifyPartitions> 43 | <DiskID>0</DiskID> 44 | <WillWipeDisk>true</WillWipeDisk> 45 | </Disk> 46 | </DiskConfiguration> 47 | <ImageInstall> 48 | <OSImage> 49 | <InstallFrom> 50 | <MetaData wcm:action="add"> 51 | <Key>/IMAGE/NAME</Key> 52 | <Value>Windows Server 2019 SERVERSTANDARD</Value> 53 | </MetaData> 54 | </InstallFrom> 55 | <InstallTo> 56 | <DiskID>0</DiskID> 57 | <PartitionID>2</PartitionID> 58 | </InstallTo> 59 | <WillShowUI>OnError</WillShowUI> 60 | <InstallToAvailablePartition>false</InstallToAvailablePartition> 61 | </OSImage> 62 | </ImageInstall> 63 | <UserData> 64 | <AcceptEula>true</AcceptEula> 65 | </UserData> 66 | </component> 67 | </settings> 68 | <settings pass="specialize"> 69 | <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"> 70 | <TimeZone>Romance Standard Time</TimeZone> 71 | </component> 72 | <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"> 73 | <RunSynchronous> 74 | <RunSynchronousCommand wcm:action="add"> 75 | <Order>1</Order> 76 | <Description>Disable Network Discovery</Description> 77 | <Path>cmd.exe /c a:\disable-network-discovery.cmd</Path> 78 | </RunSynchronousCommand> 79 | </RunSynchronous> 80 | </component> 81 | </settings> 82 | <settings pass="oobeSystem"> 83 | <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"> 84 | <AutoLogon> 85 | <Password> 86 | <Value>Lab2020</Value> 87 | <PlainText>true</PlainText> 88 | </Password> 89 | <LogonCount>2</LogonCount> 90 | <Username>Administrator</Username> 91 | <Enabled>true</Enabled> 92 | </AutoLogon> 93 | <FirstLogonCommands> 94 | <SynchronousCommand wcm:action="add"> 95 | <Order>1</Order> 96 | <Description>Set Execution Policy 64 Bit</Description> 97 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 98 | <RequiresUserInput>true</RequiresUserInput> 99 | </SynchronousCommand> 100 | <SynchronousCommand wcm:action="add"> 101 | <Order>2</Order> 102 | <Description>Set Execution Policy 32 Bit</Description> 103 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 104 | <RequiresUserInput>true</RequiresUserInput> 105 | </SynchronousCommand> 106 | <SynchronousCommand wcm:action="add"> 107 | <Order>3</Order> 108 | <Description>Disable WinRM</Description> 109 | <CommandLine>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\disable-winrm.ps1</CommandLine> 110 | <RequiresUserInput>true</RequiresUserInput> 111 | </SynchronousCommand> 112 | <SynchronousCommand wcm:action="add"> 113 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 114 | <Order>4</Order> 115 | <Description>Show file extensions in Explorer</Description> 116 | </SynchronousCommand> 117 | <SynchronousCommand wcm:action="add"> 118 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> 119 | <Order>5</Order> 120 | <Description>Enable QuickEdit mode</Description> 121 | </SynchronousCommand> 122 | <SynchronousCommand wcm:action="add"> 123 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> 124 | <Order>6</Order> 125 | <Description>Show Run command in Start Menu</Description> 126 | </SynchronousCommand> 127 | <SynchronousCommand wcm:action="add"> 128 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> 129 | <Order>7</Order> 130 | <Description>Show Administrative Tools in Start Menu</Description> 131 | </SynchronousCommand> 132 | <SynchronousCommand wcm:action="add"> 133 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 134 | <Order>8</Order> 135 | <Description>Zero Hibernation File</Description> 136 | </SynchronousCommand> 137 | <SynchronousCommand wcm:action="add"> 138 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 139 | <Order>9</Order> 140 | <Description>Disable Hibernation Mode</Description> 141 | </SynchronousCommand> 142 | <SynchronousCommand wcm:action="add"> 143 | <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> 144 | <Order>10</Order> 145 | <Description>Disable password expiration for Administrator user</Description> 146 | </SynchronousCommand> 147 | <SynchronousCommand wcm:action="add"> 148 | <CommandLine>cmd.exe /c a:\install-vm-tools.cmd</CommandLine> 149 | <Order>12</Order> 150 | <Description>Install VMware Tools</Description> 151 | </SynchronousCommand> 152 | <SynchronousCommand wcm:action="add"> 153 | <CommandLine>cmd.exe /c a:\enable-rdp.cmd</CommandLine> 154 | <Order>13</Order> 155 | <Description>Enable RDP</Description> 156 | </SynchronousCommand> 157 | <SynchronousCommand wcm:action="add"> 158 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\set-temp.ps1</CommandLine> 159 | <Order>14</Order> 160 | <Description>Set Temp Folders</Description> 161 | </SynchronousCommand> 162 | 163 | 164 | <SynchronousCommand wcm:action="add"> 165 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File a:\enable-winrm.ps1</CommandLine> 166 | <Description>Enable WinRM</Description> 167 | <Order>11</Order> 168 | </SynchronousCommand> 169 | 170 | 171 | </FirstLogonCommands> 172 | <OOBE> 173 | <HideEULAPage>true</HideEULAPage> 174 | <HideLocalAccountScreen>true</HideLocalAccountScreen> 175 | <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> 176 | <HideOnlineAccountScreens>true</HideOnlineAccountScreens> 177 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 178 | <NetworkLocation>Home</NetworkLocation> 179 | <ProtectYourPC>1</ProtectYourPC> 180 | </OOBE> 181 | 182 | <UserAccounts> 183 | <AdministratorPassword> 184 | <Value>Lab2020</Value> 185 | <PlainText>true</PlainText> 186 | </AdministratorPassword> 187 | </UserAccounts> 188 | </component> 189 | </settings> 190 | <cpi:offlineImage cpi:source="wim:c:/wim/install.wim#Windows Server 2019 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> 191 | </unattend> -------------------------------------------------------------------------------- /w2019.base/scripts/disable-network-discovery.cmd: -------------------------------------------------------------------------------- 1 | reg ADD HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff /f 2 | netsh advfirewall firewall set rule group="Network Discovery" new enable=No -------------------------------------------------------------------------------- /w2019.base/scripts/disable-screensaver.ps1: -------------------------------------------------------------------------------- 1 | Write-Host "Disabling Screensaver" 2 | Set-ItemProperty "HKCU:\Control Panel\Desktop" -Name ScreenSaveActive -Value 0 -Type DWord 3 | & powercfg -x -monitor-timeout-ac 0 4 | & powercfg -x -monitor-timeout-dc 0 5 | -------------------------------------------------------------------------------- /w2019.base/scripts/enable-rdp.cmd: -------------------------------------------------------------------------------- 1 | netsh advfirewall firewall add rule name="Open Port 3389" dir=in action=allow protocol=TCP localport=3389 2 | reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f -------------------------------------------------------------------------------- /w2019.base/scripts/enable-winrm.bat: -------------------------------------------------------------------------------- 1 | rem Enable-NetFirewallRule for WinRM 2 | netsh advfirewall firewall add rule name="Port 5985" dir=in action=allow protocol=TCP localport=5985 3 | sc.exe config winrm start= auto 4 | -------------------------------------------------------------------------------- /w2019.base/scripts/enable-winrm.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 3.0 2 | 3 | # Configure a Windows host for remote management with Ansible 4 | # ----------------------------------------------------------- 5 | # 6 | # This script checks the current WinRM (PS Remoting) configuration and makes 7 | # the necessary changes to allow Ansible to connect, authenticate and 8 | # execute PowerShell commands. 9 | # 10 | # All events are logged to the Windows EventLog, useful for unattended runs. 11 | # 12 | # Use option -Verbose in order to see the verbose output messages. 13 | # 14 | # Use option -CertValidityDays to specify how long this certificate is valid 15 | # starting from today. So you would specify -CertValidityDays 3650 to get 16 | # a 10-year valid certificate. 17 | # 18 | # Use option -ForceNewSSLCert if the system has been SysPreped and a new 19 | # SSL Certificate must be forced on the WinRM Listener when re-running this 20 | # script. This is necessary when a new SID and CN name is created. 21 | # 22 | # Use option -EnableCredSSP to enable CredSSP as an authentication option. 23 | # 24 | # Use option -DisableBasicAuth to disable basic authentication. 25 | # 26 | # Use option -SkipNetworkProfileCheck to skip the network profile check. 27 | # Without specifying this the script will only run if the device's interfaces 28 | # are in DOMAIN or PRIVATE zones. Provide this switch if you want to enable 29 | # WinRM on a device with an interface in PUBLIC zone. 30 | # 31 | # Use option -SubjectName to specify the CN name of the certificate. This 32 | # defaults to the system's hostname and generally should not be specified. 33 | 34 | # Written by Trond Hindenes <trond@hindenes.com> 35 | # Updated by Chris Church <cchurch@ansible.com> 36 | # Updated by Michael Crilly <mike@autologic.cm> 37 | # Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com> 38 | # Updated by Nicolas Simond <contact@nicolas-simond.com> 39 | # Updated by Dag Wieërs <dag@wieers.com> 40 | # Updated by Jordan Borean <jborean93@gmail.com> 41 | # Updated by Erwan Quélin <erwan.quelin@gmail.com> 42 | # Updated by David Norman <david@dkn.email> 43 | # 44 | # Version 1.0 - 2014-07-06 45 | # Version 1.1 - 2014-11-11 46 | # Version 1.2 - 2015-05-15 47 | # Version 1.3 - 2016-04-04 48 | # Version 1.4 - 2017-01-05 49 | # Version 1.5 - 2017-02-09 50 | # Version 1.6 - 2017-04-18 51 | # Version 1.7 - 2017-11-23 52 | # Version 1.8 - 2018-02-23 53 | # Version 1.9 - 2018-09-21 54 | 55 | # Support -Verbose option 56 | [CmdletBinding()] 57 | 58 | Param ( 59 | [string]$SubjectName = $env:COMPUTERNAME, 60 | [int]$CertValidityDays = 1095, 61 | [switch]$SkipNetworkProfileCheck, 62 | $CreateSelfSignedCert = $true, 63 | [switch]$ForceNewSSLCert, 64 | [switch]$GlobalHttpFirewallAccess, 65 | [switch]$DisableBasicAuth = $false, 66 | [switch]$EnableCredSSP 67 | ) 68 | 69 | Function Write-Log 70 | { 71 | $Message = $args[0] 72 | Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message 73 | } 74 | 75 | Function Write-VerboseLog 76 | { 77 | $Message = $args[0] 78 | Write-Verbose $Message 79 | Write-Log $Message 80 | } 81 | 82 | Function Write-HostLog 83 | { 84 | $Message = $args[0] 85 | Write-Output $Message 86 | Write-Log $Message 87 | } 88 | 89 | Function New-LegacySelfSignedCert 90 | { 91 | Param ( 92 | [string]$SubjectName, 93 | [int]$ValidDays = 1095 94 | ) 95 | 96 | $hostnonFQDN = $env:computerName 97 | $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname 98 | $SignatureAlgorithm = "SHA256" 99 | 100 | $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1" 101 | $name.Encode("CN=$SubjectName", 0) 102 | 103 | $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1" 104 | $key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider" 105 | $key.KeySpec = 1 106 | $key.Length = 4096 107 | $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" 108 | $key.MachineContext = 1 109 | $key.Create() 110 | 111 | $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1" 112 | $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") 113 | $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1" 114 | $ekuoids.Add($serverauthoid) 115 | $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" 116 | $ekuext.InitializeEncode($ekuoids) 117 | 118 | $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1" 119 | $cert.InitializeFromPrivateKey(2, $key, "") 120 | $cert.Subject = $name 121 | $cert.Issuer = $cert.Subject 122 | $cert.NotBefore = (Get-Date).AddDays(-1) 123 | $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays) 124 | 125 | $SigOID = New-Object -ComObject X509Enrollment.CObjectId 126 | $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value) 127 | 128 | [string[]] $AlternativeName += $hostnonFQDN 129 | $AlternativeName += $hostFQDN 130 | $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames 131 | 132 | foreach ($AN in $AlternativeName) 133 | { 134 | $AltName = New-Object -ComObject X509Enrollment.CAlternativeName 135 | $AltName.InitializeFromString(0x3,$AN) 136 | $IAlternativeNames.Add($AltName) 137 | } 138 | 139 | $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames 140 | $SubjectAlternativeName.InitializeEncode($IAlternativeNames) 141 | 142 | [String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment") 143 | $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage 144 | $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage)) 145 | $KeyUsageObj.Critical = $true 146 | 147 | $cert.X509Extensions.Add($KeyUsageObj) 148 | $cert.X509Extensions.Add($ekuext) 149 | $cert.SignatureInformation.HashAlgorithm = $SigOID 150 | $CERT.X509Extensions.Add($SubjectAlternativeName) 151 | $cert.Encode() 152 | 153 | $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1" 154 | $enrollment.InitializeFromRequest($cert) 155 | $certdata = $enrollment.CreateRequest(0) 156 | $enrollment.InstallResponse(2, $certdata, 0, "") 157 | 158 | # extract/return the thumbprint from the generated cert 159 | $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 160 | $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata)) 161 | 162 | return $parsed_cert.Thumbprint 163 | } 164 | 165 | Function Enable-GlobalHttpFirewallAccess 166 | { 167 | Write-Verbose "Forcing global HTTP firewall access" 168 | # this is a fairly naive implementation; could be more sophisticated about rule matching/collapsing 169 | $fw = New-Object -ComObject HNetCfg.FWPolicy2 170 | 171 | # try to find/enable the default rule first 172 | $add_rule = $false 173 | $matching_rules = $fw.Rules | Where-Object { $_.Name -eq "Windows Remote Management (HTTP-In)" } 174 | $rule = $null 175 | If ($matching_rules) { 176 | If ($matching_rules -isnot [Array]) { 177 | Write-Verbose "Editing existing single HTTP firewall rule" 178 | $rule = $matching_rules 179 | } 180 | Else { 181 | # try to find one with the All or Public profile first 182 | Write-Verbose "Found multiple existing HTTP firewall rules..." 183 | $rule = $matching_rules | ForEach-Object { $_.Profiles -band 4 }[0] 184 | 185 | If (-not $rule -or $rule -is [Array]) { 186 | Write-Verbose "Editing an arbitrary single HTTP firewall rule (multiple existed)" 187 | # oh well, just pick the first one 188 | $rule = $matching_rules[0] 189 | } 190 | } 191 | } 192 | 193 | If (-not $rule) { 194 | Write-Verbose "Creating a new HTTP firewall rule" 195 | $rule = New-Object -ComObject HNetCfg.FWRule 196 | $rule.Name = "Windows Remote Management (HTTP-In)" 197 | $rule.Description = "Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]" 198 | $add_rule = $true 199 | } 200 | 201 | $rule.Profiles = 0x7FFFFFFF 202 | $rule.Protocol = 6 203 | $rule.LocalPorts = 5985 204 | $rule.RemotePorts = "*" 205 | $rule.LocalAddresses = "*" 206 | $rule.RemoteAddresses = "*" 207 | $rule.Enabled = $true 208 | $rule.Direction = 1 209 | $rule.Action = 1 210 | $rule.Grouping = "Windows Remote Management" 211 | 212 | If ($add_rule) { 213 | $fw.Rules.Add($rule) 214 | } 215 | 216 | Write-Verbose "HTTP firewall rule $($rule.Name) updated" 217 | } 218 | 219 | # Setup error handling. 220 | Trap 221 | { 222 | $_ 223 | Exit 1 224 | } 225 | $ErrorActionPreference = "Stop" 226 | 227 | # Get the ID and security principal of the current user account 228 | $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent() 229 | $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID) 230 | 231 | # Get the security principal for the Administrator role 232 | $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator 233 | 234 | # Check to see if we are currently running "as Administrator" 235 | if (-Not $myWindowsPrincipal.IsInRole($adminRole)) 236 | { 237 | Write-Output "ERROR: You need elevated Administrator privileges in order to run this script." 238 | Write-Output " Start Windows PowerShell by using the Run as Administrator option." 239 | Exit 2 240 | } 241 | 242 | $EventSource = $MyInvocation.MyCommand.Name 243 | If (-Not $EventSource) 244 | { 245 | $EventSource = "Powershell CLI" 246 | } 247 | 248 | If ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False) 249 | { 250 | New-EventLog -LogName Application -Source $EventSource 251 | } 252 | 253 | # Detect PowerShell version. 254 | If ($PSVersionTable.PSVersion.Major -lt 3) 255 | { 256 | Write-Log "PowerShell version 3 or higher is required." 257 | Throw "PowerShell version 3 or higher is required." 258 | } 259 | 260 | # Find and start the WinRM service. 261 | Write-Verbose "Verifying WinRM service." 262 | If (!(Get-Service "WinRM")) 263 | { 264 | Write-Log "Unable to find the WinRM service." 265 | Throw "Unable to find the WinRM service." 266 | } 267 | ElseIf ((Get-Service "WinRM").Status -ne "Running") 268 | { 269 | Write-Verbose "Setting WinRM service to start automatically on boot." 270 | Set-Service -Name "WinRM" -StartupType Automatic 271 | Write-Log "Set WinRM service to start automatically on boot." 272 | Write-Verbose "Starting WinRM service." 273 | Start-Service -Name "WinRM" -ErrorAction Stop 274 | Write-Log "Started WinRM service." 275 | 276 | } 277 | 278 | # WinRM should be running; check that we have a PS session config. 279 | If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener))) 280 | { 281 | If ($SkipNetworkProfileCheck) { 282 | Write-Verbose "Enabling PS Remoting without checking Network profile." 283 | Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop 284 | Write-Log "Enabled PS Remoting without checking Network profile." 285 | } 286 | Else { 287 | Write-Verbose "Enabling PS Remoting." 288 | Enable-PSRemoting -Force -ErrorAction Stop 289 | Write-Log "Enabled PS Remoting." 290 | } 291 | } 292 | Else 293 | { 294 | Write-Verbose "PS Remoting is already enabled." 295 | } 296 | 297 | # Ensure LocalAccountTokenFilterPolicy is set to 1 298 | # https://github.com/ansible/ansible/issues/42978 299 | $token_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" 300 | $token_prop_name = "LocalAccountTokenFilterPolicy" 301 | $token_key = Get-Item -Path $token_path 302 | $token_value = $token_key.GetValue($token_prop_name, $null) 303 | if ($token_value -ne 1) { 304 | Write-Verbose "Setting LocalAccountTOkenFilterPolicy to 1" 305 | if ($null -ne $token_value) { 306 | Remove-ItemProperty -Path $token_path -Name $token_prop_name 307 | } 308 | New-ItemProperty -Path $token_path -Name $token_prop_name -Value 1 -PropertyType DWORD > $null 309 | } 310 | 311 | # Make sure there is a SSL listener. 312 | $listeners = Get-ChildItem WSMan:\localhost\Listener 313 | If (!($listeners | Where-Object {$_.Keys -like "TRANSPORT=HTTPS"})) 314 | { 315 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 316 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 317 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 318 | 319 | # Create the hashtables of settings to be used. 320 | $valueset = @{ 321 | Hostname = $SubjectName 322 | CertificateThumbprint = $thumbprint 323 | } 324 | 325 | $selectorset = @{ 326 | Transport = "HTTPS" 327 | Address = "*" 328 | } 329 | 330 | Write-Verbose "Enabling SSL listener." 331 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 332 | Write-Log "Enabled SSL listener." 333 | } 334 | Else 335 | { 336 | Write-Verbose "SSL listener is already active." 337 | 338 | # Force a new SSL cert on Listener if the $ForceNewSSLCert 339 | If ($ForceNewSSLCert) 340 | { 341 | 342 | # We cannot use New-SelfSignedCertificate on 2012R2 and earlier 343 | $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays 344 | Write-HostLog "Self-signed SSL certificate generated; thumbprint: $thumbprint" 345 | 346 | $valueset = @{ 347 | CertificateThumbprint = $thumbprint 348 | Hostname = $SubjectName 349 | } 350 | 351 | # Delete the listener for SSL 352 | $selectorset = @{ 353 | Address = "*" 354 | Transport = "HTTPS" 355 | } 356 | Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset 357 | 358 | # Add new Listener with new SSL cert 359 | New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset 360 | } 361 | } 362 | 363 | # Check for basic authentication. 364 | $basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object {$_.Name -eq "Basic"} 365 | 366 | If ($DisableBasicAuth) 367 | { 368 | If (($basicAuthSetting.Value) -eq $true) 369 | { 370 | Write-Verbose "Disabling basic auth support." 371 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $false 372 | Write-Log "Disabled basic auth support." 373 | } 374 | Else 375 | { 376 | Write-Verbose "Basic auth is already disabled." 377 | } 378 | } 379 | Else 380 | { 381 | If (($basicAuthSetting.Value) -eq $false) 382 | { 383 | Write-Verbose "Enabling basic auth support." 384 | Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true 385 | Write-Log "Enabled basic auth support." 386 | } 387 | Else 388 | { 389 | Write-Verbose "Basic auth is already enabled." 390 | } 391 | } 392 | 393 | # If EnableCredSSP if set to true 394 | If ($EnableCredSSP) 395 | { 396 | # Check for CredSSP authentication 397 | $credsspAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where-Object {$_.Name -eq "CredSSP"} 398 | If (($credsspAuthSetting.Value) -eq $false) 399 | { 400 | Write-Verbose "Enabling CredSSP auth support." 401 | Enable-WSManCredSSP -role server -Force 402 | Write-Log "Enabled CredSSP auth support." 403 | } 404 | } 405 | 406 | If ($GlobalHttpFirewallAccess) { 407 | Enable-GlobalHttpFirewallAccess 408 | } 409 | 410 | # Configure firewall to allow WinRM HTTPS connections. 411 | $fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" 412 | $fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any 413 | If ($fwtest1.count -lt 5) 414 | { 415 | Write-Verbose "Adding firewall rule to allow WinRM HTTPS." 416 | netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow 417 | Write-Log "Added firewall rule to allow WinRM HTTPS." 418 | } 419 | ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5)) 420 | { 421 | Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile." 422 | netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any 423 | Write-Log "Updated firewall rule to allow WinRM HTTPS for any profile." 424 | } 425 | Else 426 | { 427 | Write-Verbose "Firewall rule already exists to allow WinRM HTTPS." 428 | } 429 | 430 | # Test a remoting connection to localhost, which should work. 431 | $httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue 432 | $httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck 433 | 434 | $httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue 435 | 436 | If ($httpResult -and $httpsResult) 437 | { 438 | Write-Verbose "HTTP: Enabled | HTTPS: Enabled" 439 | } 440 | ElseIf ($httpsResult -and !$httpResult) 441 | { 442 | Write-Verbose "HTTP: Disabled | HTTPS: Enabled" 443 | } 444 | ElseIf ($httpResult -and !$httpsResult) 445 | { 446 | Write-Verbose "HTTP: Enabled | HTTPS: Disabled" 447 | } 448 | Else 449 | { 450 | Write-Log "Unable to establish an HTTP or HTTPS remoting session." 451 | Throw "Unable to establish an HTTP or HTTPS remoting session." 452 | } 453 | Write-VerboseLog "PS Remoting has been successfully configured for Ansible." -------------------------------------------------------------------------------- /w2019.base/scripts/install-vm-tools.cmd: -------------------------------------------------------------------------------- 1 | @rem Silent mode, basic UI, no reboot 2 | e:\setup64 /s /v "/qb REBOOT=R" -------------------------------------------------------------------------------- /w2019.base/scripts/microsoft-updates.bat: -------------------------------------------------------------------------------- 1 | net stop wuauserv 2 | 3 | reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v EnableFeaturedSoftware /t REG_DWORD /d 1 /f 4 | 5 | reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v IncludeRecommendedUpdates /t REG_DWORD /d 1 /f 6 | 7 | echo Set ServiceManager = CreateObject("Microsoft.Update.ServiceManager") > A:\temp.vbs 8 | echo Set NewUpdateService = ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",7,"") >> A:\temp.vbs 9 | 10 | cscript A:\temp.vbs 11 | 12 | net start wuauserv 13 | -------------------------------------------------------------------------------- /w2019.base/scripts/set-temp.ps1: -------------------------------------------------------------------------------- 1 | # Set Temp Variable using PowerShell 2 | 3 | $TempFolder = "C:\TEMP" 4 | New-Item -ItemType Directory -Force -Path $TempFolder 5 | [Environment]::SetEnvironmentVariable("TEMP", $TempFolder, [EnvironmentVariableTarget]::Machine) 6 | [Environment]::SetEnvironmentVariable("TMP", $TempFolder, [EnvironmentVariableTarget]::Machine) 7 | [Environment]::SetEnvironmentVariable("TEMP", $TempFolder, [EnvironmentVariableTarget]::User) 8 | [Environment]::SetEnvironmentVariable("TMP", $TempFolder, [EnvironmentVariableTarget]::User) -------------------------------------------------------------------------------- /w2019.base/scripts/win-updates.ps1: -------------------------------------------------------------------------------- 1 | param($global:RestartRequired=0, 2 | $global:MoreUpdates=0, 3 | $global:MaxCycles=5, 4 | $MaxUpdatesPerCycle=500, 5 | $BeginWithRestart=0) 6 | 7 | $Logfile = "C:\Windows\Temp\win-updates.log" 8 | 9 | function LogWrite { 10 | Param ([string]$logstring) 11 | $now = Get-Date -format s 12 | Add-Content $Logfile -value "$now $logstring" 13 | Write-Output $logstring 14 | } 15 | 16 | function Check-ContinueRestartOrEnd() { 17 | $RegistryKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" 18 | $RegistryEntry = "InstallWindowsUpdates" 19 | switch ($global:RestartRequired) { 20 | 0 { 21 | $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry 22 | if ($prop) { 23 | LogWrite "Restart Registry Entry Exists - Removing It" 24 | Remove-ItemProperty -Path $RegistryKey -Name $RegistryEntry -ErrorAction SilentlyContinue 25 | } 26 | 27 | LogWrite "No Restart Required" 28 | Check-WindowsUpdates 29 | 30 | if (($global:MoreUpdates -eq 1) -and ($script:Cycles -le $global:MaxCycles)) { 31 | Install-WindowsUpdates 32 | } elseif ($script:Cycles -gt $global:MaxCycles) { 33 | LogWrite "Exceeded Cycle Count - Stopping" 34 | & "a:\enable-winrm.ps1" 35 | } else { 36 | LogWrite "Done Installing Windows Updates" 37 | & "a:\enable-winrm.ps1" 38 | } 39 | } 40 | 1 { 41 | $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry 42 | if (-not $prop) { 43 | LogWrite "Restart Registry Entry Does Not Exist - Creating It" 44 | Set-ItemProperty -Path $RegistryKey -Name $RegistryEntry -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File $($script:ScriptPath) -MaxUpdatesPerCycle $($MaxUpdatesPerCycle)" 45 | } else { 46 | LogWrite "Restart Registry Entry Exists Already" 47 | } 48 | 49 | LogWrite "Restart Required - Restarting..." 50 | Restart-Computer 51 | } 52 | default { 53 | LogWrite "Unsure If A Restart Is Required" 54 | break 55 | } 56 | } 57 | } 58 | 59 | function Install-WindowsUpdates() { 60 | $script:Cycles++ 61 | LogWrite "Evaluating Available Updates with limit of $($MaxUpdatesPerCycle):" 62 | $UpdatesToDownload = New-Object -ComObject 'Microsoft.Update.UpdateColl' 63 | $script:i = 0; 64 | $CurrentUpdates = $SearchResult.Updates 65 | while($script:i -lt $CurrentUpdates.Count -and $script:CycleUpdateCount -lt $MaxUpdatesPerCycle) { 66 | $Update = $CurrentUpdates.Item($script:i) 67 | if ($null -ne $Update) { 68 | [bool]$addThisUpdate = $false 69 | if ($Update.InstallationBehavior.CanRequestUserInput) { 70 | LogWrite "> Skipping: $($Update.Title) because it requires user input" 71 | } else { 72 | if (!($Update.EulaAccepted)) { 73 | LogWrite "> Note: $($Update.Title) has a license agreement that must be accepted. Accepting the license." 74 | $Update.AcceptEula() 75 | [bool]$addThisUpdate = $true 76 | $script:CycleUpdateCount++ 77 | } else { 78 | [bool]$addThisUpdate = $true 79 | $script:CycleUpdateCount++ 80 | } 81 | } 82 | 83 | if ([bool]$addThisUpdate) { 84 | LogWrite "Adding: $($Update.Title)" 85 | $UpdatesToDownload.Add($Update) |Out-Null 86 | } 87 | } 88 | $script:i++ 89 | } 90 | 91 | if ($UpdatesToDownload.Count -eq 0) { 92 | LogWrite "No Updates To Download..." 93 | } else { 94 | LogWrite 'Downloading Updates...' 95 | $ok = 0; 96 | while (! $ok) { 97 | try { 98 | $Downloader = $UpdateSession.CreateUpdateDownloader() 99 | $Downloader.Updates = $UpdatesToDownload 100 | $Downloader.Download() 101 | $ok = 1; 102 | } catch { 103 | LogWrite $_.Exception | Format-List -force 104 | LogWrite "Error downloading updates. Retrying in 30s." 105 | $script:attempts = $script:attempts + 1 106 | Start-Sleep -s 30 107 | } 108 | } 109 | } 110 | 111 | $UpdatesToInstall = New-Object -ComObject 'Microsoft.Update.UpdateColl' 112 | [bool]$rebootMayBeRequired = $false 113 | LogWrite 'The following updates are downloaded and ready to be installed:' 114 | foreach ($Update in $SearchResult.Updates) { 115 | if (($Update.IsDownloaded)) { 116 | LogWrite "> $($Update.Title)" 117 | $UpdatesToInstall.Add($Update) |Out-Null 118 | 119 | if ($Update.InstallationBehavior.RebootBehavior -gt 0){ 120 | [bool]$rebootMayBeRequired = $true 121 | } 122 | } 123 | } 124 | 125 | if ($UpdatesToInstall.Count -eq 0) { 126 | LogWrite 'No updates available to install...' 127 | $global:MoreUpdates=0 128 | $global:RestartRequired=0 129 | & "a:\enable-winrm.ps1" 130 | break 131 | } 132 | 133 | if ($rebootMayBeRequired) { 134 | LogWrite 'These updates may require a reboot' 135 | $global:RestartRequired=1 136 | } 137 | 138 | LogWrite 'Installing updates...' 139 | 140 | $Installer = $script:UpdateSession.CreateUpdateInstaller() 141 | $Installer.Updates = $UpdatesToInstall 142 | $InstallationResult = $Installer.Install() 143 | 144 | LogWrite "Installation Result: $($InstallationResult.ResultCode)" 145 | LogWrite "Reboot Required: $($InstallationResult.RebootRequired)" 146 | LogWrite 'Listing of updates installed and individual installation results:' 147 | if ($InstallationResult.RebootRequired) { 148 | $global:RestartRequired=1 149 | } else { 150 | $global:RestartRequired=0 151 | } 152 | 153 | for($i=0; $i -lt $UpdatesToInstall.Count; $i++) { 154 | New-Object -TypeName PSObject -Property @{ 155 | Title = $UpdatesToInstall.Item($i).Title 156 | Result = $InstallationResult.GetUpdateResult($i).ResultCode 157 | } 158 | LogWrite "Item: $($UpdatesToInstall.Item($i).Title)" 159 | LogWrite "Result: $($InstallationResult.GetUpdateResult($i).ResultCode)" 160 | } 161 | 162 | Check-ContinueRestartOrEnd 163 | } 164 | 165 | function Check-WindowsUpdates() { 166 | LogWrite "Checking For Windows Updates" 167 | $Username = $env:USERDOMAIN + "\" + $env:USERNAME 168 | LogWrite "Script: $script:ScriptPath `nScript User: $Username `nStarted: $(Get-Date)" 169 | 170 | $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher() 171 | $script:successful = $FALSE 172 | $script:attempts = 0 173 | $script:maxAttempts = 12 174 | while(-not $script:successful -and $script:attempts -lt $script:maxAttempts) { 175 | try { 176 | $script:SearchResult = $script:UpdateSearcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0") 177 | $script:successful = $TRUE 178 | } catch { 179 | LogWrite $_.Exception | Format-List -force 180 | LogWrite "Search call to UpdateSearcher was unsuccessful. Retrying in 10s." 181 | $script:attempts = $script:attempts + 1 182 | Start-Sleep -s 10 183 | } 184 | } 185 | 186 | if ($SearchResult.Updates.Count -ne 0) { 187 | $Message = "There are " + $SearchResult.Updates.Count + " more updates." 188 | LogWrite $Message 189 | try { 190 | for($i=0; $i -lt $script:SearchResult.Updates.Count; $i++) { 191 | LogWrite $script:SearchResult.Updates.Item($i).Title 192 | LogWrite $script:SearchResult.Updates.Item($i).Description 193 | LogWrite $script:SearchResult.Updates.Item($i).RebootRequired 194 | LogWrite $script:SearchResult.Updates.Item($i).EulaAccepted 195 | } 196 | $global:MoreUpdates=1 197 | } catch { 198 | LogWrite $_.Exception | Format-List -force 199 | LogWrite "Showing SearchResult was unsuccessful. Rebooting." 200 | $global:RestartRequired=1 201 | $global:MoreUpdates=0 202 | Check-ContinueRestartOrEnd 203 | LogWrite "Show never happen to see this text!" 204 | Restart-Computer 205 | } 206 | } else { 207 | LogWrite 'There are no applicable updates' 208 | $global:RestartRequired=0 209 | $global:MoreUpdates=0 210 | } 211 | } 212 | 213 | $script:ScriptName = $MyInvocation.MyCommand.ToString() 214 | $script:ScriptPath = $MyInvocation.MyCommand.Path 215 | $script:UpdateSession = New-Object -ComObject 'Microsoft.Update.Session' 216 | $script:UpdateSession.ClientApplicationID = 'Packer Windows Update Installer' 217 | $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher() 218 | $script:SearchResult = New-Object -ComObject 'Microsoft.Update.UpdateColl' 219 | $script:Cycles = 0 220 | $script:CycleUpdateCount = 0 221 | 222 | if ($BeginWithRestart) { 223 | $global:RestartRequired = 1 224 | Check-ContinueRestartOrEnd 225 | } 226 | 227 | Check-WindowsUpdates 228 | if ($global:MoreUpdates -eq 1) { 229 | Install-WindowsUpdates 230 | } else { 231 | Check-ContinueRestartOrEnd 232 | } 233 | -------------------------------------------------------------------------------- /win10.base/Win10_vsphere.json: -------------------------------------------------------------------------------- 1 | { 2 | "builders": [ 3 | { 4 | "CPUs": "{{user `vm-cpu-num`}}", 5 | "RAM": "{{user `vm-mem-size`}}", 6 | "RAM_reserve_all": true, 7 | "communicator": "winrm", 8 | "convert_to_template": "true", 9 | "datacenter": "{{user `vsphere-datacenter`}}", 10 | "datastore": "{{user `vsphere-datastore`}}", 11 | "disk_controller_type": "lsilogic-sas", 12 | "firmware": "bios", 13 | "floppy_files": [ 14 | "autounattend.xml", 15 | "../scripts/disable-network-discovery.cmd", 16 | "../scripts/enable-rdp.cmd", 17 | "../scripts/enable-winrm.ps1", 18 | "../scripts/install-vm-tools.cmd", 19 | "../scripts/set-temp.ps1", 20 | "../scripts/microsoft-updates.bat", 21 | "../scripts/win-updates.ps1", 22 | "../scripts/disable-screensaver.ps1" 23 | ], 24 | "folder": "{{user `vsphere-folder`}}", 25 | "guest_os_type": "windows9_64Guest", 26 | "host": "{{user `vsphere-host`}}", 27 | "insecure_connection": "true", 28 | "iso_paths": [ 29 | "{{user `os_iso_path`}}", 30 | "[] /vmimages/tools-isoimages/windows.iso" 31 | ], 32 | "network_adapters": [ 33 | { 34 | "network": "{{user `vsphere-network`}}", 35 | "network_card": "vmxnet3" 36 | } 37 | ], 38 | "password": "{{user `vsphere-password`}}", 39 | "storage": [ 40 | { 41 | "disk_size": "{{user `vm-disk-size`}}", 42 | "disk_thin_provisioned": true 43 | } 44 | ], 45 | "type": "vsphere-iso", 46 | "username": "{{user `vsphere-user`}}", 47 | "vcenter_server": "{{user `vsphere-server`}}", 48 | "vm_name": "{{user `vm-name`}}", 49 | "winrm_insecure": "true", 50 | "winrm_password": "{{user `winadmin-password`}}", 51 | "winrm_use_ssl": "true", 52 | "winrm_username": "{{user `winrm_username`}}" 53 | } 54 | ], 55 | "provisioners": [ 56 | { 57 | "type": "windows-restart" 58 | } 59 | ], 60 | "sensitive-variables": [ 61 | "vsphere_password", 62 | "winadmin_password" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /win10.base/autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <servicing/> 4 | <settings pass="windowsPE"> 5 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 6 | <DiskConfiguration> 7 | <Disk wcm:action="add"> 8 | <CreatePartitions> 9 | <CreatePartition wcm:action="add"> 10 | <Order>1</Order> 11 | <Type>Primary</Type> 12 | <Extend>true</Extend> 13 | </CreatePartition> 14 | </CreatePartitions> 15 | <ModifyPartitions> 16 | <ModifyPartition wcm:action="add"> 17 | <Extend>false</Extend> 18 | <Format>NTFS</Format> 19 | <Letter>C</Letter> 20 | <Order>1</Order> 21 | <PartitionID>1</PartitionID> 22 | <Label>Windows 10</Label> 23 | </ModifyPartition> 24 | </ModifyPartitions> 25 | <DiskID>0</DiskID> 26 | <WillWipeDisk>true</WillWipeDisk> 27 | </Disk> 28 | <WillShowUI>OnError</WillShowUI> 29 | </DiskConfiguration> 30 | <UserData> 31 | <AcceptEula>true</AcceptEula> 32 | <FullName>Administrator Administrator</FullName> 33 | <Organization>Administrator Inc.</Organization> 34 | 35 | <!-- 36 | NOTE: If you are re-configuring this for use of a retail key 37 | and using a retail ISO, you need to adjust the <ProductKey> block 38 | below to look like this: 39 | 40 | <ProductKey> 41 | <Key>33PXH-7Y6KF-2VJC9-XBBR8-HVTHH</Key> 42 | <WillShowUI>Never</WillShowUI> 43 | </ProductKey> 44 | 45 | Notice the addition of the `<Key>` element. 46 | --> 47 | 48 | <!-- Product Key from http://technet.microsoft.com/de-DE/library/jj612867.aspx --> 49 | <!-- <ProductKey>NPPR9-FWDCX-D2C8J-H872K-2YT43 50 | <WillShowUI>Never</WillShowUI> 51 | </ProductKey> --> 52 | </UserData> 53 | <ImageInstall> 54 | <OSImage> 55 | <InstallTo> 56 | <DiskID>0</DiskID> 57 | <PartitionID>1</PartitionID> 58 | </InstallTo> 59 | <WillShowUI>OnError</WillShowUI> 60 | <InstallToAvailablePartition>false</InstallToAvailablePartition> 61 | <InstallFrom> 62 | <MetaData wcm:action="add"> 63 | <Key>/IMAGE/NAME</Key> 64 | <Value>Windows 10 Enterprise</Value> 65 | </MetaData> 66 | </InstallFrom> 67 | </OSImage> 68 | </ImageInstall> 69 | </component> 70 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 71 | <SetupUILanguage> 72 | <UILanguage>de-DE</UILanguage> 73 | </SetupUILanguage> 74 | <InputLocale>de-DE</InputLocale> 75 | <SystemLocale>de-DE</SystemLocale> 76 | <UILanguage>de-DE</UILanguage> 77 | 78 | <UserLocale>de-DE</UserLocale> 79 | </component> 80 | </settings> 81 | <settings pass="offlineServicing"> 82 | <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 83 | <EnableLUA>false</EnableLUA> 84 | </component> 85 | </settings> 86 | <settings pass="oobeSystem"> 87 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 88 | 89 | <OOBE> 90 | <HideEULAPage>true</HideEULAPage> 91 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 92 | <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> 93 | <HideOnlineAccountScreens>true</HideOnlineAccountScreens> 94 | <SkipUserOOBE>true</SkipUserOOBE> 95 | <SkipMachineOOBE>true</SkipMachineOOBE> 96 | <NetworkLocation>Home</NetworkLocation> 97 | <ProtectYourPC>1</ProtectYourPC> 98 | </OOBE> 99 | <UserAccounts> 100 | <AdministratorPassword> 101 | <Value>Lab2020</Value> 102 | <PlainText>true</PlainText> 103 | </AdministratorPassword> 104 | </UserAccounts> 105 | <AutoLogon> 106 | <Password> 107 | <Value>Lab2020</Value> 108 | <PlainText>true</PlainText> 109 | </Password> 110 | <LogonCount>2</LogonCount> 111 | <Username>Administrator</Username> 112 | <Enabled>true</Enabled> 113 | </AutoLogon> 114 | <FirstLogonCommands> 115 | <SynchronousCommand wcm:action="add"> 116 | <Order>1</Order> 117 | <Description>Set Execution Policy 64 Bit</Description> 118 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 119 | <RequiresUserInput>true</RequiresUserInput> 120 | </SynchronousCommand> 121 | <SynchronousCommand wcm:action="add"> 122 | <Order>2</Order> 123 | <Description>Set Execution Policy 32 Bit</Description> 124 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 125 | <RequiresUserInput>true</RequiresUserInput> 126 | </SynchronousCommand> 127 | <SynchronousCommand wcm:action="add"> 128 | <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> 129 | <Order>18</Order> 130 | <Description>Disable password expiration for Administrator user</Description> 131 | </SynchronousCommand> 132 | <SynchronousCommand wcm:action="add"> 133 | <CommandLine>cmd.exe /c a:\install-vm-tools.cmd</CommandLine> 134 | <Order>20</Order> 135 | <Description>Install VMware Tools</Description> 136 | </SynchronousCommand> 137 | <SynchronousCommand wcm:action="add"> 138 | <CommandLine>cmd.exe /c a:\enable-rdp.cmd</CommandLine> 139 | <Order>21</Order> 140 | <Description>Enable RDP</Description> 141 | </SynchronousCommand> 142 | <SynchronousCommand wcm:action="add"> 143 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\set-temp.ps1</CommandLine> 144 | <Order>22</Order> 145 | <Description>Set Temp Folders</Description> 146 | </SynchronousCommand> 147 | 148 | <SynchronousCommand wcm:action="add"> 149 | <CommandLine>cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File a:\enable-winrm.ps1</CommandLine> 150 | <Description>Enable WinRM</Description> 151 | <Order>23</Order> 152 | </SynchronousCommand> 153 | 154 | </FirstLogonCommands> 155 | <ShowWindowsLive>false</ShowWindowsLive> 156 | </component> 157 | </settings> 158 | <!-- <settings pass="specialize"> 159 | <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 160 | <OEMInformation> 161 | <HelpCustomized>false</HelpCustomized> 162 | </OEMInformation> 163 | 164 | <ComputerName>Administrator-10</ComputerName> 165 | <TimeZone>Pacific Standard Time</TimeZone> 166 | <RegisteredOwner/> 167 | </component> 168 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 169 | <SkipAutoActivation>true</SkipAutoActivation> 170 | </component> 171 | </settings> --> 172 | <cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="catalog:d:/sources/install_windows 7 ENTERPRISE.clg"/> 173 | </unattend> --------------------------------------------------------------------------------