mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
6.2 KiB
91 lines
6.2 KiB
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory)] [string] $LogPath,
|
|
[string] $LabName = 'NtfsSecurityOsMatrixLab',
|
|
[string[]] $Member = @('OSDC1', 'OSFile19', 'OSFile22', 'OSFile25', 'OSWin11E'),
|
|
[string[]] $LocalCredentialMember = @(),
|
|
[string] $PesterModulePath = 'V:\Git\WindowsAccessControl\output\RequiredModules\Pester\5.7.1',
|
|
[string] $PowerShell7Msi = 'V:\LabSources\SoftwarePackages\PowerShell-7.6.3-win-x64.msi'
|
|
)
|
|
|
|
# Finishes machines of the matrix lab after a deployment that stopped in AutomatedLab's file server step (a job that never completed
|
|
# although its remote side was idle) or after Add-OsMatrixMachine.ps1: detaches the installation ISO from the file servers, installs
|
|
# PowerShell 7 from the MSI of the host, and copies Pester 5.7.1 into the module folders of both editions. It uses no AutomatedLab job
|
|
# (no -AsJob), only synchronous remoting. A member in -LocalCredentialMember is reached with the local installation account through a
|
|
# session, for a machine whose secure channel to the domain controller fails. Windows PowerShell 5.1 on the host; run it elevated.
|
|
$ErrorActionPreference = 'Stop'
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
# -File passes an array as one string, so a list may arrive as 'A,B'.
|
|
$Member = @($Member | ForEach-Object -Process { $_ -split ',' } | Where-Object -FilterScript { $_ })
|
|
$LocalCredentialMember = @($LocalCredentialMember | ForEach-Object -Process { $_ -split ',' } | Where-Object -FilterScript { $_ })
|
|
$stamp = '[{0:yyyy-MM-dd HH:mm:ss}Z]'
|
|
function Write-Step { param ([string] $Message) ($stamp -f [DateTime]::UtcNow) + ' ' + $Message | Add-Content -LiteralPath $LogPath }
|
|
|
|
$installBlock = {
|
|
param ($Msi)
|
|
$msiPath = Join-Path -Path 'C:\Windows\Temp' -ChildPath $Msi
|
|
$process = Start-Process -FilePath 'msiexec.exe' -ArgumentList @('/i', ('"{0}"' -f $msiPath), '/quiet', '/norestart', 'ADD_PATH=1', '/l*v', 'C:\Windows\Temp\pwsh-install.log') -Wait -PassThru
|
|
$pwsh = Join-Path -Path $env:ProgramFiles -ChildPath 'PowerShell\7\pwsh.exe'
|
|
[pscustomobject]@{ ExitCode = $process.ExitCode; Pwsh = $(if (Test-Path -LiteralPath $pwsh) { (Get-Item -LiteralPath $pwsh).VersionInfo.ProductVersion } else { 'missing' }) }
|
|
}
|
|
$createBlock = { param ($Path) $null = New-Item -Path $Path -ItemType Directory -Force }
|
|
$checkBlock = { param ($Path) '{0}: {1}' -f $env:COMPUTERNAME, (Test-Path -LiteralPath (Join-Path -Path $Path -ChildPath '5.7.1\Pester.psd1')) }
|
|
|
|
($stamp -f [DateTime]::UtcNow) + " START complete-os-matrix-lab lab=$LabName members=$($Member -join ',') localCredential=$($LocalCredentialMember -join ',')" | Set-Content -LiteralPath $LogPath
|
|
try {
|
|
foreach ($path in $PesterModulePath, $PowerShell7Msi) { if (-not (Test-Path -LiteralPath $path)) { throw "Missing payload: $path" } }
|
|
Import-Module -Name AutomatedLab -ErrorAction Stop
|
|
Import-Lab -Name $LabName -NoValidation -NoDisplay
|
|
$fileServers = @($Member | Where-Object -FilterScript { $_ -like 'OSFile*' -and $_ -notin $LocalCredentialMember })
|
|
if ($fileServers) {
|
|
Dismount-LabIsoImage -ComputerName $fileServers -SupressOutput
|
|
Write-Step "installation ISO detached from $($fileServers -join ',')"
|
|
}
|
|
|
|
$msiName = Split-Path -Path $PowerShell7Msi -Leaf
|
|
$domainMembers = @($Member | Where-Object -FilterScript { $_ -notin $LocalCredentialMember })
|
|
foreach ($name in $Member) {
|
|
if ($name -in $LocalCredentialMember) {
|
|
$session = New-LabPSSession -ComputerName $name -UseLocalCredential
|
|
try {
|
|
Copy-Item -LiteralPath $PowerShell7Msi -Destination 'C:\Windows\Temp\' -ToSession $session -Force
|
|
$outcome = Invoke-Command -Session $session -ScriptBlock $installBlock -ArgumentList $msiName
|
|
foreach ($modulesRoot in 'C:\Program Files\WindowsPowerShell\Modules', 'C:\Program Files\PowerShell\Modules') {
|
|
$destination = Join-Path -Path $modulesRoot -ChildPath 'Pester'
|
|
Invoke-Command -Session $session -ScriptBlock $createBlock -ArgumentList $destination
|
|
Copy-Item -LiteralPath $PesterModulePath -Destination $destination -ToSession $session -Recurse -Force
|
|
Write-Step ("Pester 5.7.1 in {0}: {1}" -f $modulesRoot, (Invoke-Command -Session $session -ScriptBlock $checkBlock -ArgumentList $destination))
|
|
}
|
|
}
|
|
finally {
|
|
Remove-PSSession -Session $session -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
else {
|
|
Copy-LabFileItem -Path $PowerShell7Msi -ComputerName $name -DestinationFolderPath 'C:\Windows\Temp'
|
|
$outcome = Invoke-LabCommand -ComputerName $name -ActivityName "Install PowerShell 7 on $name" -NoDisplay -PassThru -ErrorAction Stop -ArgumentList $msiName -ScriptBlock $installBlock
|
|
}
|
|
|
|
Write-Step ("PowerShell 7 on {0}: msiexec exit code {1}; pwsh {2}" -f $name, $outcome.ExitCode, $outcome.Pwsh)
|
|
if ($outcome.ExitCode -notin 0, 3010 -or $outcome.Pwsh -eq 'missing') { throw "PowerShell 7 isn't installed on $name (exit code $($outcome.ExitCode))." }
|
|
}
|
|
|
|
if ($domainMembers) {
|
|
foreach ($modulesRoot in 'C:\Program Files\WindowsPowerShell\Modules', 'C:\Program Files\PowerShell\Modules') {
|
|
$destination = Join-Path -Path $modulesRoot -ChildPath 'Pester'
|
|
Invoke-LabCommand -ComputerName $domainMembers -ActivityName 'Create the Pester module directory' -NoDisplay -ErrorAction Stop -ArgumentList $destination -ScriptBlock $createBlock
|
|
Copy-LabFileItem -Path $PesterModulePath -ComputerName $domainMembers -DestinationFolderPath $destination -Recurse
|
|
$found = Invoke-LabCommand -ComputerName $domainMembers -ActivityName 'Check Pester' -NoDisplay -PassThru -ErrorAction Stop -ArgumentList $destination -ScriptBlock $checkBlock
|
|
Write-Step ("Pester 5.7.1 in {0}: {1}" -f $modulesRoot, (@($found) -join '; '))
|
|
if (@($found | Where-Object -FilterScript { $_ -notmatch ': True$' }).Count -gt 0) { throw "Pester 5.7.1 isn't in $destination on every member." }
|
|
}
|
|
}
|
|
|
|
Write-Step 'complete-os-matrix-lab-DONE'
|
|
exit 0
|
|
}
|
|
catch {
|
|
Write-Step ("complete-os-matrix-lab-FAILED: {0}" -f $_)
|
|
$_ | Format-List -Property * -Force | Out-String | Add-Content -LiteralPath $LogPath
|
|
exit 1
|
|
}
|
|
|