Eigenverft.Manifested.Sandbox.Shared.Elevation.ps1
|
<#
Eigenverft.Manifested.Sandbox.Shared.Elevation #> function Test-ManifestedProcessElevation { [CmdletBinding()] [OutputType([bool])] param() if ([System.Environment]::OSVersion.Platform -ne [System.PlatformID]::Win32NT) { return $false } try { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } catch { return $false } } function Get-ManifestedPowerShellHostPath { [CmdletBinding()] param() try { $process = Get-Process -Id $PID -ErrorAction Stop if ($process.Path) { return $process.Path } } catch { } $desktopHostPath = Join-Path $PSHOME 'powershell.exe' if (Test-Path -LiteralPath $desktopHostPath) { return $desktopHostPath } $coreHostPath = Join-Path $PSHOME 'pwsh.exe' if (Test-Path -LiteralPath $coreHostPath) { return $coreHostPath } throw 'Unable to resolve the current PowerShell host path for self-elevation.' } function Get-ManifestedModuleManifestPath { [CmdletBinding()] param() return (Join-Path $PSScriptRoot 'Eigenverft.Manifested.Sandbox.psd1') } function Get-ManifestedSelfElevationContext { [CmdletBinding()] param() $wasSelfElevated = ([System.Environment]::GetEnvironmentVariable('EIGENVERFT_MANIFESTED_SELF_ELEVATED', 'Process') -eq '1') [pscustomobject]@{ SkipSelfElevation = $wasSelfElevated WasSelfElevated = $wasSelfElevated } } function Get-ManifestedCommandElevationPlan { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$CommandName, [string[]]$PlannedActions = @(), [hashtable]$Context = @{}, [string]$LocalRoot = (Get-ManifestedLocalRoot), [switch]$SkipSelfElevation, [switch]$WasSelfElevated, [switch]$WhatIfMode ) $layout = Get-ManifestedLayout -LocalRoot $LocalRoot $requiresElevation = $false $requirementSource = $null switch ($CommandName) { 'Initialize-VCRuntime' { $installedRuntime = if ($Context.ContainsKey('InstalledRuntime')) { $Context['InstalledRuntime'] } else { $null } $installerInfo = if ($Context.ContainsKey('InstallerInfo')) { $Context['InstallerInfo'] } else { $null } if ($installedRuntime -and $installedRuntime.Installed) { if ($installerInfo -and $installerInfo.VersionObject) { if (-not $installedRuntime.VersionObject -or $installedRuntime.VersionObject -lt $installerInfo.VersionObject) { $requiresElevation = $true $requirementSource = 'Install-VCRuntime' } } } elseif (@($PlannedActions) -contains 'Install-VCRuntime') { $requiresElevation = $true $requirementSource = 'Install-VCRuntime' } } } $processIsElevated = Test-ManifestedProcessElevation [pscustomobject]@{ CommandName = $CommandName LocalRoot = $layout.LocalRoot Layout = $layout PlannedActions = @($PlannedActions) ProcessIsElevated = $processIsElevated RequiresElevation = $requiresElevation RequirementSource = $requirementSource SkipSelfElevation = [bool]$SkipSelfElevation WasSelfElevated = [bool]$WasSelfElevated WhatIfMode = [bool]$WhatIfMode ShouldSelfElevate = ($requiresElevation -and -not $processIsElevated -and -not $SkipSelfElevation -and -not $WhatIfMode) } } function Invoke-ManifestedElevatedCommand { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject]$ElevationPlan, [Parameter(Mandatory = $true)] [string]$CommandName, [Parameter(Mandatory = $true)] [hashtable]$CommandParameters ) if (-not $ElevationPlan.ShouldSelfElevate) { return $null } $layout = Get-ManifestedLayout -LocalRoot $ElevationPlan.LocalRoot $stagePath = New-ManifestedStageDirectory -RootPath $layout.LocalRoot -Prefix 'elevated' $scriptPath = Join-Path $stagePath 'invoke-elevated.ps1' $parameterPath = Join-Path $stagePath 'invoke-parameters.json' $resultPath = Join-Path $stagePath 'invoke-result.json' $moduleManifestPath = Get-ManifestedModuleManifestPath $hostPath = Get-ManifestedPowerShellHostPath try { $invocationParameters = @{} foreach ($entry in $CommandParameters.GetEnumerator()) { if ($null -ne $entry.Value) { $invocationParameters[$entry.Key] = $entry.Value } } $invocationParameters | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $parameterPath -Encoding UTF8 $scriptContent = @" param( [Parameter(Mandatory = \$true)] [string]\$ModuleManifestPath, [Parameter(Mandatory = \$true)] [string]\$CommandName, [Parameter(Mandatory = \$true)] [string]\$ParameterPath, [Parameter(Mandatory = \$true)] [string]\$PinnedLocalRoot, [Parameter(Mandatory = \$true)] [string]\$ResultPath ) Set-StrictMode -Version Latest \$ErrorActionPreference = 'Stop' \$env:EIGENVERFT_MANIFESTED_LOCALROOT = \$PinnedLocalRoot \$env:EIGENVERFT_MANIFESTED_SELF_ELEVATED = '1' Import-Module -Name \$ModuleManifestPath -Force \$parameterDocument = Get-Content -LiteralPath \$ParameterPath -Raw -ErrorAction Stop | ConvertFrom-Json \$invokeParameters = @{} foreach (\$property in \$parameterDocument.PSObject.Properties) { \$invokeParameters[\$property.Name] = \$property.Value } \$result = & \$CommandName @invokeParameters \$result | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath \$ResultPath -Encoding UTF8 "@ Set-Content -LiteralPath $scriptPath -Value $scriptContent -Encoding UTF8 $argumentList = @( '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $scriptPath, '-ModuleManifestPath', $moduleManifestPath, '-CommandName', $CommandName, '-ParameterPath', $parameterPath, '-PinnedLocalRoot', $layout.LocalRoot, '-ResultPath', $resultPath ) try { $process = Start-Process -FilePath $hostPath -ArgumentList $argumentList -Verb RunAs -Wait -PassThru -ErrorAction Stop } catch { throw "Failed to start an elevated PowerShell process for $CommandName. $($_.Exception.Message)" } if ($process.ExitCode -ne 0) { throw "Elevated $CommandName exited with code $($process.ExitCode)." } if (-not (Test-Path -LiteralPath $resultPath)) { throw "Elevated $CommandName completed without producing a result payload at $resultPath." } return ((Get-Content -LiteralPath $resultPath -Raw -ErrorAction Stop) | ConvertFrom-Json) } finally { Remove-ManifestedPath -Path $stagePath | Out-Null } } |