113 lines
4.4 KiB
PowerShell
113 lines
4.4 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[switch]$ConfirmReadOnlyShadow,
|
|
[Parameter(Mandatory = $true)][string]$PreflightJson,
|
|
[string]$JavaExecutable = 'java',
|
|
[int]$MaximumPreflightAgeMinutes = 30
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
. (Join-Path $PSScriptRoot 'ShadowScriptCommon.ps1')
|
|
|
|
if (-not $ConfirmReadOnlyShadow.IsPresent) {
|
|
throw 'CONFIRM_READ_ONLY_SHADOW_REQUIRED'
|
|
}
|
|
$preflightPath = Resolve-ShadowFile $PreflightJson
|
|
$preflight = Read-ShadowJson $preflightPath
|
|
if (-not [bool]$preflight.success) { throw 'SUCCESSFUL_PREFLIGHT_REQUIRED' }
|
|
$generatedAt = [DateTime]::Parse($preflight.generatedAtUtc).ToUniversalTime()
|
|
if (([DateTime]::UtcNow - $generatedAt).TotalMinutes -gt `
|
|
$MaximumPreflightAgeMinutes) {
|
|
throw 'PREFLIGHT_EXPIRED'
|
|
}
|
|
if ($null -eq (Get-Process -Id ([int]$preflight.stable.pid) `
|
|
-ErrorAction SilentlyContinue)) {
|
|
throw 'STABLE_PROCESS_NOT_HEALTHY'
|
|
}
|
|
|
|
$artifact = Resolve-ShadowFile $preflight.shadowArtifact.path
|
|
$config = Resolve-ShadowFile $preflight.config.path
|
|
$deployment = Resolve-ShadowDirectory $preflight.deploymentDirectory
|
|
if (-not (Test-ShadowPathWithin $artifact $deployment) -or `
|
|
-not (Test-ShadowPathWithin $config $deployment)) {
|
|
throw 'SHADOW_FILES_MUST_BE_INSIDE_DEPLOYMENT_DIRECTORY'
|
|
}
|
|
if ((Get-ShadowSha256 $artifact) -ne $preflight.shadowArtifact.sha256) {
|
|
throw 'SHADOW_ARTIFACT_CHANGED_AFTER_PREFLIGHT'
|
|
}
|
|
if ((Get-ShadowSha256 $config) -ne $preflight.config.sha256) {
|
|
throw 'SHADOW_CONFIG_CHANGED_AFTER_PREFLIGHT'
|
|
}
|
|
if ((Get-ShadowSha256 $preflight.permissionReport.path) -ne `
|
|
$preflight.permissionReport.sha256) {
|
|
throw 'PERMISSION_REPORT_CHANGED_AFTER_PREFLIGHT'
|
|
}
|
|
if ((Get-ShadowSha256 $preflight.networkDenyReport.path) -ne `
|
|
$preflight.networkDenyReport.sha256) {
|
|
throw 'NETWORK_DENY_REPORT_CHANGED_AFTER_PREFLIGHT'
|
|
}
|
|
|
|
$pidFile = [IO.Path]::GetFullPath($preflight.pidFile)
|
|
if (-not (Test-ShadowPathWithin $pidFile $deployment)) {
|
|
throw 'PID_FILE_MUST_BE_INSIDE_DEPLOYMENT_DIRECTORY'
|
|
}
|
|
if (Test-Path -LiteralPath $pidFile) { throw 'SHADOW_PID_FILE_ALREADY_EXISTS' }
|
|
$java = (Get-Command $JavaExecutable -ErrorAction Stop).Source
|
|
$logs = Join-Path $deployment 'logs'
|
|
New-Item -ItemType Directory -Path $logs -Force | Out-Null
|
|
$stdout = Join-Path $logs 'shadow-stdout.log'
|
|
$stderr = Join-Path $logs 'shadow-stderr.log'
|
|
$configUri = ([uri]$config).AbsoluteUri
|
|
$statusUri = [uri]$preflight.statusUri
|
|
$runtimeProperties = @(
|
|
'--spring.profiles.active=shadow',
|
|
'--shadow.enabled=true',
|
|
"--spring.config.additional-location=$configUri",
|
|
"--server.address=$($statusUri.Host)",
|
|
"--server.port=$($statusUri.Port)",
|
|
"--shadow.evidence.run.artifact-sha256=$($preflight.shadowArtifact.sha256)",
|
|
"--shadow.evidence.run.configuration-sha256=$($preflight.config.sha256)",
|
|
"--shadow.evidence.run.source-server=$($preflight.sourceIdentity.server)",
|
|
"--shadow.evidence.run.source-database=$($preflight.sourceIdentity.database)",
|
|
"--shadow.evidence.minimum-free-bytes=$($preflight.minimumFreeBytes)"
|
|
)
|
|
$quotedProperties = @($runtimeProperties | ForEach-Object {
|
|
'"{0}"' -f $_.Replace('"', '\"')
|
|
}) -join ' '
|
|
$arguments = '-jar "{0}" {1}' -f $artifact.Replace('"', '\"'), `
|
|
$quotedProperties
|
|
|
|
$process = $null
|
|
try {
|
|
$process = Start-Process -FilePath $java -ArgumentList $arguments `
|
|
-WorkingDirectory $deployment -WindowStyle Hidden -PassThru `
|
|
-RedirectStandardOutput $stdout -RedirectStandardError $stderr
|
|
Start-Sleep -Milliseconds 300
|
|
if ($process.HasExited) {
|
|
throw "SHADOW_PROCESS_EXITED_EARLY:$($process.ExitCode)"
|
|
}
|
|
$record = [pscustomobject]@{
|
|
schemaVersion = 1
|
|
pid = [int]$process.Id
|
|
processStartTimeUtc = $process.StartTime.ToUniversalTime().ToString('o')
|
|
javaExecutable = [IO.Path]::GetFullPath($java)
|
|
shadowArtifact = $artifact
|
|
shadowArtifactSha256 = Get-ShadowSha256 $artifact
|
|
config = $config
|
|
configSha256 = Get-ShadowSha256 $config
|
|
deploymentDirectory = $deployment
|
|
preflightJson = $preflightPath
|
|
preflightSha256 = Get-ShadowSha256 $preflightPath
|
|
startedAtUtc = [DateTime]::UtcNow.ToString('o')
|
|
}
|
|
Write-ShadowJson -Value $record -Path $pidFile
|
|
return $record
|
|
}
|
|
catch {
|
|
if ($null -ne $process -and -not $process.HasExited) {
|
|
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
|
|
}
|
|
throw
|
|
}
|