fix(hayabusa): restore scheduled EVTX upload pipeline
This commit is contained in:
@@ -105,4 +105,17 @@ Server-side prerequisite for user `awops`:
|
||||
printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILoFWQmgoUJj1P7mp1/fB5aBkI3fVgjPme9jmK8Gh9jr igor@snb-live' | sudo tee /var/lib/awops/.ssh/authorized_keys >/dev/null
|
||||
sudo chown awops:awops /var/lib/awops/.ssh/authorized_keys
|
||||
sudo chmod 600 /var/lib/awops/.ssh/authorized_keys
|
||||
sudo chown awops:awops /opt/activitywatch/aw-rus-ops/drop
|
||||
sudo chmod 0750 /opt/activitywatch/aw-rus-ops/drop
|
||||
```
|
||||
|
||||
Production scheduled task on `SHARKON2025`:
|
||||
|
||||
- task name: `ActivityWatch Hayabusa Upload`
|
||||
- action: `C:\ProgramData\AWatch-rus\export-upload-hayabusa-to-aw-server.ps1 -HoursBack 6 -Mode incident`
|
||||
- principal: `Администратор`, `LogonType=Interactive`, `RunLevel=Highest`
|
||||
- normal `LastTaskResult`: `0`
|
||||
|
||||
Do not switch this task back to `SYSTEM` on the current RDP host: Task Scheduler starts `powershell.exe` under `SYSTEM`, but the process exits with `0xC0000142` before the upload script starts.
|
||||
|
||||
Server-side processing accepts Windows zip packages with backslash path separators and UTF-8 BOM in sidecar JSON. `aw-hayabusa-autoprocess` processes the full incoming queue after accepting a drop package, so stale incoming files from an earlier failed run are drained before the latest intake is recorded.
|
||||
|
||||
@@ -113,19 +113,36 @@ detect_host_from_manifest() {
|
||||
extract_zip_normalized() {
|
||||
local package_path="$1"
|
||||
local dest_dir="$2"
|
||||
command -v zipinfo >/dev/null 2>&1 || fail "zipinfo is required to inspect ${package_path}"
|
||||
command -v unzip >/dev/null 2>&1 || fail "unzip is required to extract ${package_path}"
|
||||
command -v python3 >/dev/null 2>&1 || fail "python3 is required to extract ${package_path}"
|
||||
mkdir -p "${dest_dir}"
|
||||
local entry normalized
|
||||
while IFS= read -r entry; do
|
||||
normalized="${entry//\\//}"
|
||||
case "${normalized}" in
|
||||
""|.|/*|*"/../"*|../*|*"..")
|
||||
fail "unsafe zip entry: ${entry}"
|
||||
;;
|
||||
esac
|
||||
done < <(zipinfo -1 "${package_path}")
|
||||
unzip -q "${package_path}" -d "${dest_dir}"
|
||||
python3 - "${package_path}" "${dest_dir}" <<'PY'
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
package_path = sys.argv[1]
|
||||
dest_dir = os.path.abspath(sys.argv[2])
|
||||
|
||||
with zipfile.ZipFile(package_path) as archive:
|
||||
for info in archive.infolist():
|
||||
name = info.filename.replace("\\", "/")
|
||||
is_dir = info.is_dir() or name.endswith("/")
|
||||
if is_dir:
|
||||
name = name.rstrip("/")
|
||||
parts = [part for part in name.split("/") if part]
|
||||
if not parts or name.startswith("/") or any(part in (".", "..") for part in parts):
|
||||
raise SystemExit(f"unsafe zip entry: {info.filename}")
|
||||
target_path = os.path.abspath(os.path.join(dest_dir, *parts))
|
||||
if os.path.commonpath([dest_dir, target_path]) != dest_dir:
|
||||
raise SystemExit(f"unsafe zip entry: {info.filename}")
|
||||
if is_dir:
|
||||
os.makedirs(target_path, exist_ok=True)
|
||||
continue
|
||||
os.makedirs(os.path.dirname(target_path), exist_ok=True)
|
||||
with archive.open(info) as src, open(target_path, "wb") as dst:
|
||||
shutil.copyfileobj(src, dst)
|
||||
PY
|
||||
}
|
||||
|
||||
write_package_manifest() {
|
||||
|
||||
Reference in New Issue
Block a user