Housekeeping;Add prereq module installation
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			This commit is contained in:
		
							
								
								
									
										238
									
								
								scripts/payload/Apply-FirstBootConfig.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								scripts/payload/Apply-FirstBootConfig.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| [CmdletBinding()] | ||||
| Param( | ||||
|     # No parameters | ||||
| ) | ||||
|  | ||||
| $SetLocationSplat = @{ | ||||
|     Path = $PSScriptRoot | ||||
| } | ||||
| Set-Location @SetLocationSplat | ||||
|  | ||||
| $NewEventLogSplat = @{ | ||||
|     LogName     = 'Application' | ||||
|     Source      = 'FirstBoot' | ||||
|     ErrorAction = 'SilentlyContinue' | ||||
| } | ||||
| New-EventLog @NewEventLogSplat | ||||
| $WriteEventLogSplat = @{ | ||||
|     LogName   = 'Application' | ||||
|     Source    = 'FirstBoot' | ||||
|     EntryType = 'Information' | ||||
|     EventID   = 1 | ||||
|     Message   = "FirstBoot sequence initiated [working directory: '$PWD']" | ||||
| } | ||||
| Write-EventLog @WriteEventLogSplat | ||||
|  | ||||
| $VMwareToolsExecutable = "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" | ||||
|  | ||||
| [xml]$ovfEnv = & $VMwareToolsExecutable --cmd "info-get guestinfo.ovfEnv" | Out-String | ||||
| $ovfProperties = $ovfEnv.ChildNodes.NextSibling.PropertySection.Property | ||||
|  | ||||
| $ovfPropertyValues = @{} | ||||
| foreach ($ovfProperty in $ovfProperties) { | ||||
|     $ovfPropertyValues[$ovfProperty.key] = $ovfProperty.Value | ||||
| } | ||||
|  | ||||
| # Check for mandatory values | ||||
| Switch -regex ($ovfPropertyValues['deployment.type']) { | ||||
|     '^domainmember' { | ||||
|         $MandatoryProperties, $MissingProperties = @('guestinfo.hostname', 'guestinfo.ipaddress', 'guestinfo.prefixlength', 'guestinfo.gateway', 'addsconfig.domainname', 'addsconfig.username', 'addsconfig.password'), @() | ||||
|     } | ||||
|     '^standalone' { | ||||
|         $MandatoryProperties, $MissingProperties = @('guestinfo.hostname', 'guestinfo.ipaddress', 'guestinfo.prefixlength', 'guestinfo.gateway', 'guestinfo.administratorpw', 'guestinfo.ntpserver'), @()         | ||||
|     } | ||||
|     default { | ||||
|         # Mandatory values missing, cannot provision. | ||||
|         $WriteEventLogSplat = @{ | ||||
|             LogName   = 'Application' | ||||
|             Source    = 'FirstBoot' | ||||
|             EntryType = 'Error' | ||||
|             EventID   = 66 | ||||
|             Message   = "Unexpected or no value set for property 'deployment.type', cannot provision." | ||||
|         } | ||||
|         Write-EventLog @WriteEventLogSplat | ||||
|         & schtasks.exe /Change /TN 'FirstBoot' /DISABLE | ||||
|         Stop-Computer -Force | ||||
|         Exit | ||||
|     } | ||||
| } | ||||
| ForEach ($Property in $MandatoryProperties) { | ||||
|     If (!$ovfPropertyValues[$Property]) { | ||||
|         $MissingProperties += $Property | ||||
|     } | ||||
| } | ||||
| If ($MissingProperties.Length -gt 0) { | ||||
|         # Mandatory values missing, cannot provision. | ||||
|         $WriteEventLogSplat = @{ | ||||
|             LogName   = 'Application' | ||||
|             Source    = 'FirstBoot' | ||||
|             EntryType = 'Error' | ||||
|             EventID   = 66 | ||||
|             Message   = "Missing values for mandatory properties $(($MissingProperties | ForEach-Object {"'{0}'" -f $_}) -join ', '), cannot provision." | ||||
|         } | ||||
|         Write-EventLog @WriteEventLogSplat | ||||
|         & schtasks.exe /Change /TN 'FirstBoot' /DISABLE | ||||
|         Stop-Computer -Force | ||||
|         Exit | ||||
| } | ||||
|  | ||||
| # Set hostname and description | ||||
| If ($Env:ComputerName -ne $ovfPropertyValues['guestinfo.hostname']) { | ||||
|     $RenameComputerSplat = @{ | ||||
|         NewName     = $ovfPropertyValues['guestinfo.hostname'] | ||||
|         Force       = $True | ||||
|         Confirm     = $False | ||||
|     } | ||||
|     Rename-Computer @RenameComputerSplat | ||||
|     $SetCimInstanceSplat = @{ | ||||
|         InputObject = (Get-CimInstance -ClassName 'Win32_OperatingSystem') | ||||
|         Property    = @{ | ||||
|             Description = $ovfPropertyValues['guestinfo.hostname'] | ||||
|         } | ||||
|     } | ||||
|     Set-CimInstance  @SetCimInstanceSplat | ||||
|  | ||||
|     # Restart the computer to apply changes | ||||
|     Restart-Computer -Force | ||||
|     Exit | ||||
| } | ||||
|  | ||||
| # Configure network interface | ||||
| If ((Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration').IPAddress -NotContains $ovfPropertyValues['guestinfo.ipaddress']) { | ||||
|     $NewNetIPAddressSplat = @{ | ||||
|         InterfaceAlias = (Get-NetAdapter).Name | ||||
|         AddressFamily  = 'IPv4' | ||||
|         IPAddress      = $ovfPropertyValues['guestinfo.ipaddress'] | ||||
|         PrefixLength   = $ovfPropertyValues['guestinfo.prefixlength'] | ||||
|         DefaultGateway = $ovfPropertyValues['guestinfo.gateway'] | ||||
|     } | ||||
|     $IPAddress = New-NetIPAddress @NewNetIPAddressSplat | ||||
|  | ||||
|     # Wait for network connection to become available | ||||
|     $Timestamp, $TimeoutMinutes = (Get-Date), 5 | ||||
|     Do { | ||||
|         If ($Timestamp.AddMinutes($TimeoutMinutes) -lt (Get-Date)) { | ||||
|             $WriteEventLogSplat = @{ | ||||
|                 LogName   = 'Application' | ||||
|                 Source    = 'FirstBoot' | ||||
|                 EntryType = 'Warning' | ||||
|                 EventID   = 13 | ||||
|                 Message   = "Timeout after $($TimeoutMinutes) minutes waiting for network connection to become available." | ||||
|             } | ||||
|             Write-EventLog @WriteEventLogSplat | ||||
|             Break | ||||
|         } | ||||
|  | ||||
|         Start-Sleep -Milliseconds 250 | ||||
|  | ||||
|         $GetNetIPAddressSplat = @{ | ||||
|             IPAddress      = $ovfPropertyValues['guestinfo.ipaddress'] | ||||
|             InterfaceIndex = $IPAddress.InterfaceIndex | ||||
|             AddressFamily  = 'IPv4' | ||||
|             ErrorAction    = 'SilentlyContinue' | ||||
|         } | ||||
|     } Until ((Get-NetIPAddress @GetNetIPAddressSplat).AddressState -eq 'Preferred') | ||||
|  | ||||
|     $OldErrorActionPreference, $ErrorActionPreference = $ErrorActionPreference, 'SilentlyContinue' | ||||
|     $TestNetConnectionSplat = @{ | ||||
|         ComputerName     = ([IPAddress]$ovfPropertyValues['guestinfo.dnsserver']).IPAddressToString | ||||
|         InformationLevel = 'Quiet' | ||||
|     } | ||||
|     $SetDnsClientServerAddressSplat = @{ | ||||
|         InterfaceAlias  = (Get-NetAdapter).Name | ||||
|         ServerAddresses = If ( | ||||
|             [boolean]($ovfPropertyValues['guestinfo.dnsserver'] -as [IPaddress]) -and (Test-NetConnection @TestNetConnectionSplat)) { | ||||
|                 ($ovfPropertyValues['guestinfo.dnsserver']) | ||||
|             } else { | ||||
|                 ('127.0.0.1') | ||||
|             } | ||||
|         Validate        = $False | ||||
|     } | ||||
|     Set-DnsClientServerAddress @SetDnsClientServerAddressSplat | ||||
|     $ErrorActionPreference, $OldErrorActionPreference = $OldErrorActionPreference, $NULL | ||||
| } | ||||
|  | ||||
| Switch -regex ($ovfPropertyValues['deployment.type']) { | ||||
|     '^domainmember' { | ||||
|         # Join Active Directory domain as member | ||||
|         If (!(Get-WmiObject -Class Win32_ComputerSystem).PartOfDomain) { | ||||
|             $AddComputerSplat = @{ | ||||
|                 DomainName = $ovfPropertyValues['addsconfig.domainname'] | ||||
|                 Credential = New-Object System.Management.Automation.PSCredential( | ||||
|                     $ovfPropertyValues['addsconfig.username'], | ||||
|                     (ConvertTo-SecureString $ovfPropertyValues['addsconfig.password'] -AsPlainText -Force) | ||||
|                 ) | ||||
|                 # OUPath     = $ovfPropertyValues['addsconfig.organizationalunit'] | ||||
|                 Restart    = $True | ||||
|                 Force      = $True | ||||
|                 Confirm    = $False | ||||
|             } | ||||
|             Add-Computer @AddComputerSplat | ||||
|  | ||||
|             # Previous cmdlet performs a reboot on completion; so these are commented out | ||||
|             # Restart-Computer -Force | ||||
|             # Exit | ||||
|         } | ||||
|     } | ||||
|     '^standalone' { | ||||
|         # Change password of built-in Administrator | ||||
|         $BuiltinAdministrator = (Get-LocalUser | Where-Object {$_.SID -match '-500'}) | ||||
|         $ConvertToSecureStringSplat = @{ | ||||
|             String      = $ovfPropertyValues['guestinfo.administratorpw'] | ||||
|             AsPlainText = $True | ||||
|             Force       = $True | ||||
|         } | ||||
|         $SetLocalUserSplat = @{ | ||||
|             InputObject = $BuiltinAdministrator | ||||
|             Password              = ConvertTo-SecureString @ConvertToSecureStringSplat | ||||
|             PasswordNeverExpires  = $True | ||||
|             AccountNeverExpires   = $True | ||||
|             ### This setting is not allowed on the last administrator | ||||
|             # UserMayChangePassword = $False | ||||
|             Confirm               = $False | ||||
|         } | ||||
|         Set-LocalUser @SetLocalUserSplat | ||||
|     } | ||||
| } | ||||
|  | ||||
| # Iterate through and invoke all payload scripts | ||||
| #! TODO: add registry values to determine which scripts have already been invoked (in case of intermediate reboots) | ||||
| $GetItemSplat = @{ | ||||
|     Path = "$($PSScriptRoot)\Scripts\*.ps1" | ||||
| } | ||||
| ForEach ($Script in (Get-Item @GetItemSplat)) { | ||||
|     Try { | ||||
|         $WriteEventLogSplat = @{ | ||||
|             LogName   = 'Application' | ||||
|             Source    = 'FirstBoot' | ||||
|             EntryType = 'Information' | ||||
|             EventID   = 4 | ||||
|             Message   = "Running script: '$($Script.FullName)'" | ||||
|         } | ||||
|         Write-EventLog @WriteEventLogSplat | ||||
|         & $Script.FullName -Parameter $ovfPropertyValues | ||||
|     } | ||||
|     Catch { | ||||
|         $WriteEventLogSplat = @{ | ||||
|             LogName   = 'Application' | ||||
|             Source    = 'FirstBoot' | ||||
|             EntryType = 'Error' | ||||
|             EventID   = 66 | ||||
|             Message   = @" | ||||
| Error occurred while executing script '$($Script.Name)': | ||||
| $($_.Exception.Message) | ||||
| "@ | ||||
|         } | ||||
|         Write-EventLog @WriteEventLogSplat | ||||
|     } | ||||
| } | ||||
|  | ||||
| $WriteEventLogSplat = @{ | ||||
|     LogName   = 'Application' | ||||
|     Source    = 'FirstBoot' | ||||
|     EntryType = 'Information' | ||||
|     EventID   = 42 | ||||
|     Message   = 'FirstBoot sequence applied and finished' | ||||
| } | ||||
| Write-EventLog @WriteEventLogSplat | ||||
| & schtasks.exe /Change /TN 'FirstBoot' /DISABLE | ||||
		Reference in New Issue
	
	Block a user