Correct crash on PowerShell 5

This commit is contained in:
2025-10-09 10:36:25 +01:00
parent 9d0e2f7fde
commit d964631532

View File

@@ -32,8 +32,8 @@
If $true, keep the temporary script and task after completion. Default $false = cleanup. If $true, keep the temporary script and task after completion. Default $false = cleanup.
.EXAMPLE .EXAMPLE
# Using gMSA (no need to user $ at end of name) # Using gMSA
.\createSAcreds.ps1 -Domain AD -AccountName rubrikgmsa -AccountType gMSA -SaJsonPath C:\Rubrik\scripts\sa.json -OutputXmlPath C:\Rubrik\scripts\sa-rbksql.xml .\createSAcreds.ps1 -Domain AD -AccountName rubrikgmsa -AccountType gMSA -SaJsonPath C:\temp\sa.json -OutputXmlPath C:\temp\sa-rbksql.xml
.EXAMPLE .EXAMPLE
# Using regular service account with password prompt # Using regular service account with password prompt
@@ -76,12 +76,16 @@ try {
$logFile = Join-Path $tempDir "Create-SA-File.log" $logFile = Join-Path $tempDir "Create-SA-File.log"
# ---- Create the one-shot script that will run under the service account ---- # ---- Create the one-shot script that will run under the service account ----
$escapedSaJsonPath = $SaJsonPath -replace '\\', '\\'
$escapedOutputXmlPath = $OutputXmlPath -replace '\\', '\\'
$escapedLogFile = $logFile -replace '\\', '\\'
$oneShotContent = @" $oneShotContent = @"
# One-shot script created by createSAcreds.ps1 # One-shot script created by create-and-run-one-shot-via-gMSA.ps1
# Runs RubrikSecurityCloud command to create service-account file # Runs RubrikSecurityCloud command to create service-account file
# Start transcript for detailed logging # Start transcript for detailed logging
Start-Transcript -Path `"$logFile`" -Append Start-Transcript -Path "$escapedLogFile" -Append
Write-Output "Script started at: `$(Get-Date)" Write-Output "Script started at: `$(Get-Date)"
Write-Output "Running as user: `$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)" Write-Output "Running as user: `$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
@@ -99,42 +103,42 @@ Try {
} }
Try { Try {
Write-Output "Checking input file: $SaJsonPath" Write-Output "Checking input file: $escapedSaJsonPath"
# Ensure the input file exists # Ensure the input file exists
if (-not (Test-Path -Path `"$SaJsonPath`")) { if (-not (Test-Path -Path "$escapedSaJsonPath")) {
Write-Error "Input SA JSON not found: $SaJsonPath" Write-Error "Input SA JSON not found: $escapedSaJsonPath"
Stop-Transcript Stop-Transcript
Exit 3 Exit 3
} }
Write-Output "Input file found, size: `$((Get-Item `"$SaJsonPath`").Length) bytes" Write-Output "Input file found, size: `$((Get-Item "$escapedSaJsonPath").Length) bytes"
Write-Output "Calling Set-RscServiceAccountFile..." Write-Output "Calling Set-RscServiceAccountFile..."
Write-Output " Input: $SaJsonPath" Write-Output " Input: $escapedSaJsonPath"
Write-Output " Output: $OutputXmlPath" Write-Output " Output: $escapedOutputXmlPath"
Set-RscServiceAccountFile `"$SaJsonPath`" -OutputFilePath `"$OutputXmlPath`" -Verbose Set-RscServiceAccountFile "$escapedSaJsonPath" -OutputFilePath "$escapedOutputXmlPath" -Verbose
Write-Output "Set-RscServiceAccountFile completed" Write-Output "Set-RscServiceAccountFile completed"
if (Test-Path -Path `"$OutputXmlPath`") { if (Test-Path -Path "$escapedOutputXmlPath") {
Write-Output "Service account XML created successfully: $OutputXmlPath" Write-Output "Service account XML created successfully: $escapedOutputXmlPath"
Write-Output "Output file size: `$((Get-Item `"$OutputXmlPath`").Length) bytes" Write-Output "Output file size: `$((Get-Item "$escapedOutputXmlPath").Length) bytes"
Stop-Transcript Stop-Transcript
Exit 0 Exit 0
} else { } else {
Write-Error "Set-RscServiceAccountFile completed but output file not found: $OutputXmlPath" Write-Error "Set-RscServiceAccountFile completed but output file not found: $escapedOutputXmlPath"
Write-Error "Checking parent directory: `$(Split-Path `"$OutputXmlPath`")" Write-Error "Checking parent directory: `$(Split-Path "$escapedOutputXmlPath")"
if (Test-Path (Split-Path `"$OutputXmlPath`")) { if (Test-Path (Split-Path "$escapedOutputXmlPath")) {
Write-Output "Parent directory exists, listing contents:" Write-Output "Parent directory exists, listing contents:"
Get-ChildItem (Split-Path `"$OutputXmlPath`") | ForEach-Object { Write-Output " `$(`$_.Name)" } Get-ChildItem (Split-Path "$escapedOutputXmlPath") | ForEach-Object { Write-Output " `$(`$_.Name)" }
} else { } else {
Write-Error "Parent directory does not exist: `$(Split-Path `"$OutputXmlPath`")" Write-Error "Parent directory does not exist: `$(Split-Path "$escapedOutputXmlPath")"
} }
Stop-Transcript Stop-Transcript
Exit 4 Exit 4
} }
} Catch { } Catch {
Write-Error "Error creating Rubrik service-account file: `$(`$_.Exception.Message)" Write-Error "Error creating RBK service-account file: `$(`$_.Exception.Message)"
Write-Error "Full exception: `$(`$_.Exception | Format-List * | Out-String)" Write-Error "Full exception: `$(`$_.Exception | Format-List * | Out-String)"
Write-Error "Stack trace: `$(`$_.ScriptStackTrace)" Write-Error "Stack trace: `$(`$_.ScriptStackTrace)"
Stop-Transcript Stop-Transcript
@@ -142,29 +146,37 @@ Try {
} }
"@ "@
# Replace placeholders (so we don't have to escape too much)
$oneShotContent = $oneShotContent -replace '\$SaJsonPath', [Regex]::Escape($SaJsonPath)
$oneShotContent = $oneShotContent -replace '\$OutputXmlPath', [Regex]::Escape($OutputXmlPath)
$oneShotContent = $oneShotContent -replace '\$logFile', [Regex]::Escape($logFile)
Set-Content -Path $oneShotScript -Value $oneShotContent -Encoding UTF8 Set-Content -Path $oneShotScript -Value $oneShotContent -Encoding UTF8
# Make sure executable by scheduled task # Make sure executable by scheduled task
try {
icacls $oneShotScript /grant "BUILTIN\Administrators:(R,W)" | Out-Null icacls $oneShotScript /grant "BUILTIN\Administrators:(R,W)" | Out-Null
} catch {
Write-Warning "Could not set permissions on script file: $($_.Exception.Message)"
}
# ---- Build Scheduled Task objects ---- # ---- Build Scheduled Task objects ----
# Construct the UserId based on account type # Construct the UserId based on account type
if ($AccountType -eq 'gMSA') { if ($AccountType -eq 'gMSA') {
$userId = if ([string]::IsNullOrWhiteSpace($Domain)) { "$AccountName`$" } else { "$Domain\$AccountName`$" } if ([string]::IsNullOrWhiteSpace($Domain)) {
$logonType = 'Password' # needed even though gMSA uses AD for auth $userId = "$AccountName`$"
} else { } else {
$userId = if ([string]::IsNullOrWhiteSpace($Domain)) { $AccountName } else { "$Domain\$AccountName" } $userId = "$Domain\$AccountName`$"
$logonType = 'Password' }
$logonType = 'Password' # For gMSA, use Password logon type
} else {
if ([string]::IsNullOrWhiteSpace($Domain)) {
$userId = $AccountName
} else {
$userId = "$Domain\$AccountName"
}
$logonType = 'Password' # For regular service accounts, use Password logon type
} }
# Action: run PowerShell to execute the one-shot script with output redirection # Action: run PowerShell to execute the one-shot script with output redirection
$psArgs = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -File `"$oneShotScript`" *>&1 | Tee-Object -FilePath `"$logFile`" -Append" $psExePath = Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\powershell.exe'
$action = New-ScheduledTaskAction -Execute (Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\powershell.exe') -Argument $psArgs $psArgs = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -File `"$oneShotScript`""
$action = New-ScheduledTaskAction -Execute $psExePath -Argument $psArgs
# Trigger: once, a short time in the future (1 minute from now) # Trigger: once, a short time in the future (1 minute from now)
$startTime = (Get-Date).AddMinutes(1) $startTime = (Get-Date).AddMinutes(1)
@@ -185,8 +197,13 @@ Try {
Write-Host "Registered scheduled task '$TaskName' to run as gMSA $userId at $startTime." Write-Host "Registered scheduled task '$TaskName' to run as gMSA $userId at $startTime."
} else { } else {
# For regular service accounts, register with password # For regular service accounts, register with password
$securePassword = if ($Password -is [SecureString]) { $Password } else { ConvertTo-SecureString $Password -AsPlainText -Force } if ($Password -is [SecureString]) {
Register-ScheduledTask -TaskName $TaskName -InputObject $task -User $userId -Password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword))) -Force $securePassword = $Password
} else {
$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
}
$plainPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword))
Register-ScheduledTask -TaskName $TaskName -InputObject $task -User $userId -Password $plainPassword -Force
Write-Host "Registered scheduled task '$TaskName' to run as service account $userId at $startTime." Write-Host "Registered scheduled task '$TaskName' to run as service account $userId at $startTime."
} }
@@ -205,6 +222,7 @@ Try {
Start-Sleep -Seconds $pollInterval Start-Sleep -Seconds $pollInterval
$elapsed += $pollInterval $elapsed += $pollInterval
try {
$info = Get-ScheduledTaskInfo -TaskName $TaskName -ErrorAction SilentlyContinue $info = Get-ScheduledTaskInfo -TaskName $TaskName -ErrorAction SilentlyContinue
if ($null -eq $info) { if ($null -eq $info) {
Write-Warning "Could not query task info yet." Write-Warning "Could not query task info yet."
@@ -218,7 +236,7 @@ Try {
# 1. State is Ready/Disabled/Unknown AND we have a valid LastResult # 1. State is Ready/Disabled/Unknown AND we have a valid LastResult
# 2. OR if LastResult changed from 267009 (SCHED_S_TASK_RUNNING) to something else # 2. OR if LastResult changed from 267009 (SCHED_S_TASK_RUNNING) to something else
if (($state -eq 'Ready' -or $state -eq 'Disabled' -or $state -eq 'Unknown' -or [string]::IsNullOrEmpty($state)) -and if (($state -eq 'Ready' -or $state -eq 'Disabled' -or $state -eq 'Unknown' -or [string]::IsNullOrEmpty($state)) -and
($lastResult -ne $null -and $lastResult -ne 267009)) { ($null -ne $lastResult -and $lastResult -ne 267009)) {
$taskCompleted = $true $taskCompleted = $true
break break
} }
@@ -227,6 +245,9 @@ Try {
Write-Host "Task still running..." Write-Host "Task still running..."
} }
} }
} catch {
Write-Warning "Error querying task status: $($_.Exception.Message)"
}
if ($elapsed -ge $maxWaitSeconds) { if ($elapsed -ge $maxWaitSeconds) {
throw "Timed out waiting for scheduled task to finish (waited $maxWaitSeconds seconds)." throw "Timed out waiting for scheduled task to finish (waited $maxWaitSeconds seconds)."
@@ -255,7 +276,7 @@ Try {
Write-Warning "Log file not found at: $logFile" Write-Warning "Log file not found at: $logFile"
} }
throw "Scheduled task finished with non-zero LastTaskResult: $lastResult." throw "Scheduled task finished with non-zero LastTaskResult: $lastResult. Check Event Viewer > Applications and Services Logs > Microsoft > Windows > TaskScheduler for details, or review the log output above."
} }
# ---- Cleanup ---- # ---- Cleanup ----
@@ -270,5 +291,11 @@ Try {
} catch { } catch {
Write-Error "ERROR: $($_.Exception.Message)" Write-Error "ERROR: $($_.Exception.Message)"
if (-not $KeepArtifacts -and $TaskName) {
try { Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue } catch {}
}
if (-not $KeepArtifacts -and $tempDir -and (Test-Path $tempDir)) {
try { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } catch {}
}
throw throw
} }