From 5c6e2ce7f42c7ed46f68b1f8e10e50e0d792c0c4 Mon Sep 17 00:00:00 2001 From: John Bowdre <61015723+jbowdre@users.noreply.github.com> Date: Mon, 27 Jun 2022 13:58:00 -0500 Subject: [PATCH] Create configure_guest.ps1 --- .../ABX Actions/configure_guest.ps1 | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 Cloud Assembly/ABX Actions/configure_guest.ps1 diff --git a/Cloud Assembly/ABX Actions/configure_guest.ps1 b/Cloud Assembly/ABX Actions/configure_guest.ps1 new file mode 100644 index 0000000..590d0e6 --- /dev/null +++ b/Cloud Assembly/ABX Actions/configure_guest.ps1 @@ -0,0 +1,157 @@ +<# vRA 8.x ABX action to perform certain in-guest actions post-deploy: + Windows: + - auto-update VM tools + - add specified domain users/groups to local Administrators group + - extend C: volume to fill disk + - set up remote access + - create a scheduled task to (attempt to) apply Windows updates + Windows: + - TBD + + ## Action Inputs: + ## Secrets: + templatePassWinDomain # password for domain account with admin rights to the template (domain-joined deployments) + templatePassWinWorkgroup # password for local account with admin rights to the template (standalone deployments) + templatePassLinDomain # password for domain account with admin rights to the template (domain-joined deployments) + templatePassLinWorkgroup # password for local account with admin rights to the template (standalone deployments) + vCenterPassword # password for vCenter account passed from the cloud template + + ## Inputs from deployment: + resourceNames[0] # VM name [BOW-DVRT-XXX003] + customProperties.vCenterUser # user for connecting to vCenter [lab\vra] + customProperties.vCenter # vCenter instance to connect to [vcsa.lab.bowdre.net] + customProperties.domain # long-form domain name [lab.bowdre.net] + customProperties.adminsList # list of domain users/groups to be added as local admins [john, lab\vra, vRA-Admins] + customProperties.adObject # boolean to determine if the system will be joined to AD (true) or not (false) + customProperties.templateUser # object containing usernames corresponding to the template passwords +#> + +function handler($context, $inputs) { + # Initialize global variables + $vcUser = $inputs.customProperties.vCenterUser + $vcPassword = $context.getSecret($inputs."vCenterPassword") + $vCenter = $inputs.customProperties.vCenter + $templateUsers = $inputs.customProperties.templateUser | ConvertFrom-Json + + # Create vmtools connection to the VM + $vmName = $inputs.resourceNames[0] + Connect-ViServer -Server $vCenter -User $vcUser -Password $vcPassword -Force + $vm = Get-VM -Name $vmName + Write-Host "Waiting for VM Tools to start..." + if (-not (Wait-Tools -VM $vm -TimeoutSeconds 180)) { + Write-Error "Unable to establish connection with VM tools" -ErrorAction Stop + } + + # Detect OS type + $count = 0 + While (!$osType) { + Try { + $osType = ($vm | Get-View).Guest.GuestFamily.ToString() + $toolsStatus = ($vm | Get-View).Guest.ToolsStatus.ToString() + } Catch { + # 60s timeout + if ($count -ge 12) { + Write-Error "Timeout exceeded while waiting for tools." -ErrorAction Stop + break + } + Write-Host "Waiting for tools..." + $count++ + Sleep 5 + } + } + Write-Host "$vmName is a $osType and its tools status is $toolsStatus." + + # Update tools on Windows if out of date + if ($osType.Equals("windowsGuest") -And $toolsStatus.Equals("toolsOld")) { + Write-Host "Updating VM Tools..." + Update-Tools $vm + Write-Host "Waiting for VM Tools to start..." + if (-not (Wait-Tools -VM $vm -TimeoutSeconds 180)) { + Write-Error "Unable to establish connection with VM tools" -ErrorAction Stop + } + } + + # Run OS-specific tasks + if ($osType.Equals("windowsGuest")) { + # Initialize Windows variables + $domainLong = $inputs.customProperties.domain + $adminsList = $inputs.customProperties.adminsList + $adObject = $inputs.customProperties.adObject + $templateUser = $adObject.Equals("true") ? $templateUsers.winDomain : $templateUsers.winWorkgroup + $templatePassword = $adObject.Equals("true") ? $context.getSecret($inputs."templatePassWinDomain") : $context.getSecret($inputs."templatePassWinWorkgroup") + + # Add domain accounts to local administrators group + if ($adminsList.Length -gt 0 -And $adObject.Equals("true")) { + # Standardize users entered without domain as DOMAIN\username + if ($adminsList.Length -gt 0) { + $domainShort = $domainLong.split('.')[0] + $adminsArray = @(($adminsList -Split ',').Trim()) + For ($i=0; $i -lt $adminsArray.Length; $i++) { + If ($adminsArray[$i] -notmatch "$domainShort.*\\" -And $adminsArray[$i] -notmatch "@$domainShort") { + $adminsArray[$i] = $domainShort + "\" + $adminsArray[$i] + } + } + $admins = '"{0}"' -f ($adminsArray -join '","') + Write-Host "Administrators: $admins" + } + $adminScript = "Add-LocalGroupMember -Group Administrators -Member $admins" + Start-Sleep -s 10 + Write-Host "Attempting to add administrator accounts..." + $runAdminScript = Invoke-VMScript -VM $vm -ScriptText $adminScript -GuestUser $templateUser -GuestPassword $templatePassword + if ($runAdminScript.ScriptOutput.Length -eq 0) { + Write-Host "Successfully added [$admins] to Administrators group." + } else { + Write-Host "Attempt to add [$admins] to Administrators group completed with warnings:`n" $runAdminScript.ScriptOutput "`n" + } + } else { + Write-Host "No admins to add..." + } + # Extend C: volume to fill system drive + $partitionScript = "`$Partition = Get-Volume -DriveLetter C | Get-Partition; `$Partition | Resize-Partition -Size (`$Partition | Get-PartitionSupportedSize).sizeMax" + Start-Sleep -s 10 + Write-Host "Attempting to extend system volume..." + $runPartitionScript = Invoke-VMScript -VM $vm -ScriptText $partitionScript -GuestUser $templateUser -GuestPassword $templatePassword + if ($runPartitionScript.ScriptOutput.Length -eq 0) { + Write-Host "Successfully extended system partition." + } else { + Write-Host "Attempt to extend system volume completed with warnings:`n" $runPartitionScript.ScriptOutput "`n" + } + # Set up remote access + $remoteScript = "Enable-NetFirewallRule -DisplayGroup `"Remote Desktop`" + Enable-NetFirewallRule -DisplayGroup `"Windows Management Instrumentation (WMI)`" + Enable-NetFirewallRule -DisplayGroup `"File and Printer Sharing`" + Enable-PsRemoting + Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name `"fDenyTSConnections`" -Value 0" + Start-Sleep -s 10 + Write-Host "Attempting to enable remote access (RDP, WMI, File and Printer Sharing, PSRemoting)..." + $runRemoteScript = Invoke-VMScript -VM $vm -ScriptText $remoteScript -GuestUser $templateUser -GuestPassword $templatePassword + if ($runRemoteScript.ScriptOutput.Length -eq 0) { + Write-Host "Successfully enabled remote access." + } else { + Write-Host "Attempt to enable remote access completed with warnings:`n" $runRemoteScript.ScriptOutput "`n" + } + # Create scheduled task to apply updates + $updateScript = "`$action = New-ScheduledTaskAction -Execute 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -Command `"& {Install-WUUpdates -Updates (Start-WUScan)}`"' + `$trigger = New-ScheduledTaskTrigger -Once -At ([DateTime]::Now.AddMinutes(1)) + `$settings = New-ScheduledTaskSettingsSet -Compatibility Win8 -Hidden + Register-ScheduledTask -Action `$action -Trigger `$trigger -Settings `$settings -TaskName `"Initial_Updates`" -User `"NT AUTHORITY\SYSTEM`" -RunLevel Highest + `$task = Get-ScheduledTask -TaskName `"Initial_Updates`" + `$task.Triggers[0].StartBoundary = [DateTime]::Now.AddMinutes(1).ToString(`"yyyy-MM-dd'T'HH:mm:ss`") + `$task.Triggers[0].EndBoundary = [DateTime]::Now.AddHours(3).ToString(`"yyyy-MM-dd'T'HH:mm:ss`") + `$task.Settings.AllowHardTerminate = `$True + `$task.Settings.DeleteExpiredTaskAfter = 'PT0S' + `$task.Settings.ExecutionTimeLimit = 'PT2H' + `$task.Settings.Volatile = `$False + `$task | Set-ScheduledTask" + Start-Sleep -s 10 + Write-Host "Creating a scheduled task to apply updates..." + $runUpdateScript = Invoke-VMScript -VM $vm -ScriptText $updateScript -GuestUser $templateUser -GuestPassword $templatePassword + Write-Host "Created task:`n" $runUpdateScript.ScriptOutput "`n" + } elseif ($osType.Equals("linuxGuest")) { + #TODO + Write-Host "Linux systems not supported by this action... yet" + } + # Cleanup connection + Disconnect-ViServer -Server $vCenter -Force -Confirm:$false + +}