fix(hayabusa): restore scheduled EVTX upload pipeline

This commit is contained in:
igor04091968
2026-06-12 10:57:39 +03:00
parent 7919051688
commit 106d796d95
18 changed files with 164 additions and 19 deletions
@@ -120,8 +120,6 @@ fn process_one(zip_path: &Path) -> Result<ProcessResult> {
"process-inbox".to_string(),
"--mode".to_string(),
mode.clone(),
"--limit".to_string(),
"1".to_string(),
],
)?;
let latest = read_json_file(Path::new(LATEST_INTAKE))?;
+2 -1
View File
@@ -92,7 +92,8 @@ fn decode_optional_json(body: String) -> Result<Value> {
pub fn read_json_file(path: &Path) -> Result<Value> {
let text = fs::read_to_string(path).with_context(|| format!("read {}", path.display()))?;
serde_json::from_str(&text).with_context(|| format!("decode {}", path.display()))
serde_json::from_str(text.trim_start_matches('\u{feff}'))
.with_context(|| format!("decode {}", path.display()))
}
pub fn write_json_pretty(value: &Value) -> Result<String> {
+3
View File
@@ -157,6 +157,7 @@ Playbook:
- `aw_windows_hayabusa_auto_upload_hours_back: 6` — lookback для каждого запуска;
- `aw_windows_hayabusa_auto_upload_mode: "incident"` — mode для server-side processing;
- `aw_windows_hayabusa_auto_upload_task_name: "ActivityWatch Hayabusa Upload"` — имя scheduled task.
- `aw_windows_hayabusa_auto_upload_run_as_user: "Администратор"` — production principal для scheduled task на RDP-хосте. На `SHARKON2025` запуск `powershell.exe` из `SYSTEM` возвращал `0xC0000142`, поэтому авто-upload должен идти как interactive/highest task от локального администратора.
## Server-side Hayabusa auto-case и Telegram alerting
@@ -176,6 +177,8 @@ Playbook:
- пишет bounded metadata в `forensics.hayabusa`;
- отправляет Telegram alert.
Для Windows direct upload пользователь `awops` на AW-server должен иметь право записи в `/opt/activitywatch/aw-rus-ops/drop`; нормальное состояние каталога: owner/group `awops:awops`, mode `0750`. Unit `aw-hayabusa-drop.service` работает от root и после обработки очищает `drop`.
Основные vars:
- `aw_hayabusa_auto_case_enabled: true`
+16
View File
@@ -2591,6 +2591,22 @@
- /opt/activitywatch/aw-rus-ops/ansible
- /opt/activitywatch/aw-rus-ops/drop
- name: Проверить наличие upload user awops для Hayabusa drop-zone
ansible.builtin.command:
cmd: id -u awops
register: aw_hayabusa_drop_upload_user
changed_when: false
failed_when: false
- name: Разрешить awops писать в Hayabusa drop-zone
ansible.builtin.file:
path: /opt/activitywatch/aw-rus-ops/drop
state: directory
owner: awops
group: awops
mode: "0750"
when: aw_hayabusa_drop_upload_user.rc == 0
- name: Положить исходный wrapper в server-side ops bundle
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/hayabusa/aw-hayabusa.sh"
+2
View File
@@ -41,6 +41,7 @@
aw_windows_hayabusa_auto_upload_hours_back: 6
aw_windows_hayabusa_auto_upload_mode: "incident"
aw_windows_hayabusa_auto_upload_task_name: "ActivityWatch Hayabusa Upload"
aw_windows_hayabusa_auto_upload_run_as_user: ""
aw_windows_file_1c_auto_upload_enabled: true
aw_windows_file_1c_auto_upload_interval_minutes: 15
aw_windows_file_1c_auto_upload_task_name: "ActivityWatch File1C Upload"
@@ -311,6 +312,7 @@
HayabusaAutoUploadHoursBack = {{ aw_windows_hayabusa_auto_upload_hours_back | int }}
HayabusaAutoUploadMode = "{{ aw_windows_hayabusa_auto_upload_mode }}"
HayabusaAutoUploadTaskName = "{{ aw_windows_hayabusa_auto_upload_task_name }}"
HayabusaAutoUploadRunAsUser = "{{ aw_windows_hayabusa_auto_upload_run_as_user }}"
File1CAutoUploadEnabled = {{ '$true' if (aw_windows_file_1c_auto_upload_enabled | bool) else '$false' }}
File1CAutoUploadIntervalMinutes = {{ aw_windows_file_1c_auto_upload_interval_minutes | int }}
File1CAutoUploadTaskName = "{{ aw_windows_file_1c_auto_upload_task_name }}"
+1
View File
@@ -39,6 +39,7 @@ aw_windows_hayabusa_auto_upload_interval_hours: 6
aw_windows_hayabusa_auto_upload_hours_back: 6
aw_windows_hayabusa_auto_upload_mode: "incident"
aw_windows_hayabusa_auto_upload_task_name: "ActivityWatch Hayabusa Upload"
aw_windows_hayabusa_auto_upload_run_as_user: "{{ aw_windows_builtin_administrator_name }}"
aw_windows_afk_enabled: true
aw_windows_window_enabled: true
+1
View File
@@ -9,6 +9,7 @@ aw_windows_hayabusa_auto_upload_interval_hours: 6
aw_windows_hayabusa_auto_upload_hours_back: 6
aw_windows_hayabusa_auto_upload_mode: "incident"
aw_windows_hayabusa_auto_upload_task_name: "ActivityWatch Hayabusa Upload"
aw_windows_hayabusa_auto_upload_run_as_user: ""
aw_windows_package_version: "v0.13.2"
aw_windows_package_url: "https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-windows-x86_64.zip"
aw_windows_package_zip_path: ""
+13
View File
@@ -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.
+29 -12
View File
@@ -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() {
+25
View File
@@ -276,6 +276,10 @@ powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-up
3. Проверить результат:
```bash
systemctl is-active aw-hayabusa-drop.path
systemctl is-failed aw-hayabusa-drop.service || true
aw-hayabusa doctor
aw-hayabusa inventory
cat /opt/hayabusa/state/latest-intake.json
journalctl -u aw-hayabusa-drop.service -n 80 --no-pager
curl -fsS http://127.0.0.1:5602/api/0/dlp/cases/30
@@ -288,6 +292,27 @@ curl -fsS http://127.0.0.1:5602/api/0/dlp/cases/30
- в case есть `forensics.hayabusa`;
- Telegram alert уже уходит в операторский чат.
Production scheduled task на `SHARKON2025`:
- `ActivityWatch Hayabusa Upload`
- principal `Администратор`, `LogonType=Interactive`, `RunLevel=Highest`
- период `6` часов, lookback `6` часов
- нормальный `LastTaskResult=0`
Если `LastTaskResult=3221225794` (`0xC0000142`) и в `C:\ProgramData\AWatch-rus\logs\hayabusa-upload.log` нет новой строки, скрипт не стартовал. На текущем RDP-хосте это воспроизводится даже минимальной SYSTEM-задачей с `powershell.exe`; пересоздать Hayabusa task как interactive/highest от `Администратор`, не от `SYSTEM`.
Если upload прошёл, но сервер не обработал пакет:
```bash
sudo systemctl reset-failed aw-hayabusa-drop.path aw-hayabusa-drop.service
sudo systemctl start aw-hayabusa-drop.path
sudo systemctl start aw-hayabusa-drop.service
find /opt/activitywatch/aw-rus-ops/drop -maxdepth 1 -type f -ls
find /opt/hayabusa/inbox/incoming -maxdepth 1 -type f -ls
```
`drop` и `incoming` после успешной обработки должны быть пустыми; latest intake должен указывать на последний пакет `SHARKON2025`.
### Hayabusa: manual fallback / production validation end-to-end
Цель: подтвердить один реальный путь
+5
View File
@@ -34,15 +34,20 @@ Core outcomes:
- `.meta.json`
- optional `.caseid`
- `ActivityWatch Hayabusa Upload` scheduled task runs every 6 hours
- on `SHARKON2025` the task runs as interactive/highest `Администратор`; `SYSTEM` PowerShell tasks fail with `0xC0000142` before the script starts
- sidecar JSON is written as UTF-8 without BOM; server-side readers also tolerate BOM for older files
### Server side
- `aw-hayabusa-drop.path` watches `/opt/activitywatch/aw-rus-ops/drop`
- `aw-hayabusa-drop.service` runs `aw-hayabusa-autoprocess`
- `/opt/activitywatch/aw-rus-ops/drop` is writable by `awops` and processed by root-owned systemd units
- `aw-hayabusa` performs:
- accept
- process-inbox
- report generation
- Windows zip entries with backslash separators are normalized during extraction
- autoprocess drains the incoming queue after accepting a drop package, preventing stale failed-run packages from being linked to a newer drop upload
- `aw-hayabusa-case-alert` performs:
- severity scoring from `timeline.jsonl`
- optional auto-case creation
+6
View File
@@ -5,6 +5,7 @@
## Что уже работает
- Windows-хост раз в `6` часов делает `EVTX export + upload`
- production scheduled task: `ActivityWatch Hayabusa Upload`, principal `Администратор`, `LogonType=Interactive`, `RunLevel=Highest`
- `AW-server` автоматически подхватывает пакет из `drop`
- `aw-hayabusa` строит forensic-отчёт
- `aw-hayabusa-case-alert` считает severity и score
@@ -22,11 +23,16 @@ powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-up
На сервере для проверки:
```bash
systemctl is-active aw-hayabusa-drop.path
systemctl is-failed aw-hayabusa-drop.service || true
aw-hayabusa inventory
cat /opt/hayabusa/state/latest-intake.json
journalctl -u aw-hayabusa-drop.service -n 80 --no-pager
curl -fsS http://127.0.0.1:5602/api/0/dlp/cases/30
```
Ожидаемо: `drop` и `incoming` пустые, `latest-intake.json` имеет `status=ok`, `host=SHARKON2025`, а `LastTaskResult` Windows-задачи равен `0`.
## Что получает оператор
- `summary.html`
+10
View File
@@ -83,6 +83,16 @@ This wrapper:
- uploads `.meta.json`;
- uploads the `zip` to the AW-server drop directory.
Scheduled production upload on `SHARKON2025`:
- task: `ActivityWatch Hayabusa Upload`
- principal: `Администратор`, interactive, highest privileges
- interval: `6` hours
- lookback: `6` hours
- success: `LastTaskResult=0` and a new line in `C:\ProgramData\AWatch-rus\logs\hayabusa-upload.log`
`LastTaskResult=3221225794` (`0xC0000142`) with no new upload log means Task Scheduler failed to start `powershell.exe`; keep this task on the interactive administrator principal for this host.
## Boundaries
- output stays outside standard AW buckets
+8 -1
View File
@@ -942,6 +942,7 @@ function New-ActivityWatchDeploymentConfig {
[int]$HayabusaAutoUploadHoursBack = 6,
[string]$HayabusaAutoUploadMode = 'incident',
[string]$HayabusaAutoUploadTaskName = 'ActivityWatch Hayabusa Upload',
[string]$HayabusaAutoUploadRunAsUser,
[bool]$File1CAutoUploadEnabled = $true,
[int]$File1CAutoUploadIntervalHours = 6,
[int]$File1CAutoUploadIntervalMinutes = 15,
@@ -1037,6 +1038,7 @@ function New-ActivityWatchDeploymentConfig {
hoursBack = $HayabusaAutoUploadHoursBack
mode = $HayabusaAutoUploadMode
taskName = $HayabusaAutoUploadTaskName
runAsUser = $HayabusaAutoUploadRunAsUser
}
}
analytics = [pscustomobject]@{
@@ -2531,11 +2533,16 @@ function Register-ActivityWatchHayabusaAutoUploadTask {
$intervalHours = [Math]::Max(1, [int]$automation.intervalHours)
$hoursBack = [Math]::Max(1, [int]$automation.hoursBack)
$mode = if ($automation.PSObject.Properties.Name -contains 'mode' -and -not [string]::IsNullOrWhiteSpace([string]$automation.mode)) { [string]$automation.mode } else { 'incident' }
$runAsUser = if ($automation.PSObject.Properties.Name -contains 'runAsUser' -and -not [string]::IsNullOrWhiteSpace([string]$automation.runAsUser)) { [string]$automation.runAsUser } else { '' }
$powerShellExe = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe'
$taskCommand = "`"$powerShellExe`" -NoProfile -ExecutionPolicy Bypass -File `"$uploadScript`" -ConfigPath `"$ConfigPath`" -HoursBack $hoursBack -Mode `"$mode`""
Remove-ActivityWatchScheduledTask -TaskName $taskName
& schtasks.exe /Create /TN $taskName /TR $taskCommand /SC HOURLY /MO $intervalHours /ST 00:00 /RU SYSTEM /RL HIGHEST /F | Out-Null
if ($runAsUser) {
& schtasks.exe /Create /TN $taskName /TR $taskCommand /SC HOURLY /MO $intervalHours /ST 00:00 /RU $runAsUser /IT /RL HIGHEST /F | Out-Null
} else {
& schtasks.exe /Create /TN $taskName /TR $taskCommand /SC HOURLY /MO $intervalHours /ST 00:00 /RU SYSTEM /RL HIGHEST /F | Out-Null
}
if ($LASTEXITCODE -ne 0) {
throw "Не удалось создать scheduled task $taskName через schtasks.exe"
}
+2
View File
@@ -45,6 +45,7 @@ param(
[int]$HayabusaAutoUploadHoursBack = 6,
[string]$HayabusaAutoUploadMode = 'incident',
[string]$HayabusaAutoUploadTaskName = 'ActivityWatch Hayabusa Upload',
[string]$HayabusaAutoUploadRunAsUser,
[bool]$File1CAutoUploadEnabled = $true,
[int]$File1CAutoUploadIntervalHours = 6,
[int]$File1CAutoUploadIntervalMinutes = 15,
@@ -157,6 +158,7 @@ $config = New-ActivityWatchDeploymentConfig `
-HayabusaAutoUploadHoursBack $HayabusaAutoUploadHoursBack `
-HayabusaAutoUploadMode $HayabusaAutoUploadMode `
-HayabusaAutoUploadTaskName $HayabusaAutoUploadTaskName `
-HayabusaAutoUploadRunAsUser $HayabusaAutoUploadRunAsUser `
-File1CAutoUploadEnabled $File1CAutoUploadEnabled `
-File1CAutoUploadIntervalHours $File1CAutoUploadIntervalHours `
-File1CAutoUploadIntervalMinutes $File1CAutoUploadIntervalMinutes `
+2
View File
@@ -46,6 +46,7 @@ param(
[int]$HayabusaAutoUploadHoursBack = 6,
[string]$HayabusaAutoUploadMode = 'incident',
[string]$HayabusaAutoUploadTaskName = 'ActivityWatch Hayabusa Upload',
[string]$HayabusaAutoUploadRunAsUser,
[bool]$File1CAutoUploadEnabled = $true,
[int]$File1CAutoUploadIntervalHours = 6,
[int]$File1CAutoUploadIntervalMinutes = 15,
@@ -118,6 +119,7 @@ if (-not (Test-Path -LiteralPath $deployScript)) {
-HayabusaAutoUploadHoursBack $HayabusaAutoUploadHoursBack `
-HayabusaAutoUploadMode $HayabusaAutoUploadMode `
-HayabusaAutoUploadTaskName $HayabusaAutoUploadTaskName `
-HayabusaAutoUploadRunAsUser $HayabusaAutoUploadRunAsUser `
-File1CAutoUploadEnabled $File1CAutoUploadEnabled `
-File1CAutoUploadIntervalHours $File1CAutoUploadIntervalHours `
-File1CAutoUploadIntervalMinutes $File1CAutoUploadIntervalMinutes `
@@ -16,6 +16,25 @@ param(
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$LogDir = Join-Path (Split-Path -Parent $ConfigPath) 'logs'
$LogPath = Join-Path $LogDir 'hayabusa-upload.log'
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
function Write-RunLog {
param(
[Parameter(Mandatory = $true)]
[string]$Message
)
$line = '{0} {1}' -f ([DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ssZ')), $Message
Add-Content -LiteralPath $LogPath -Value $line -Encoding UTF8
}
trap {
Write-RunLog ("ERROR: " + ($_ | Out-String).Trim())
exit 1
}
function New-TemporarySshKeyCopy {
param(
[Parameter(Mandatory = $true)]
@@ -27,9 +46,20 @@ function New-TemporarySshKeyCopy {
$tempKeyPath = Join-Path $tempDir 'awops_ed25519'
Copy-Item -LiteralPath $SourceKeyPath -Destination $tempKeyPath -Force
$currentIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$grantPrincipals = @(
('*' + $currentIdentity.User.Value),
'*S-1-5-18',
'*S-1-5-32-544'
) |
Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) } |
Select-Object -Unique
& icacls.exe $tempKeyPath /inheritance:r | Out-Null
& icacls.exe $tempKeyPath /grant:r "$($env:USERNAME):(F)" | Out-Null
& icacls.exe $tempKeyPath /remove:g 'Users' 'Authenticated Users' 'Everyone' 'BUILTIN\Users' 'BUILTIN\Administrators' 'NT AUTHORITY\SYSTEM' 2>$null | Out-Null
foreach ($principal in $grantPrincipals) {
& icacls.exe $tempKeyPath /grant:r "$principal`:(F)" | Out-Null
}
& icacls.exe $tempKeyPath /remove:g 'Users' 'Authenticated Users' 'Everyone' 'BUILTIN\Users' 2>$null | Out-Null
return $tempKeyPath
}
@@ -42,6 +72,8 @@ if (-not (Test-Path -LiteralPath $RemoteKeyPath)) {
throw "SSH private key not found: $RemoteKeyPath"
}
Write-RunLog ("start hoursBack={0} daysBack={1} mode={2} serverHost={3} runRemote={4}" -f $HoursBack, $DaysBack, $Mode, $ServerHost, [bool]$RunRemote)
$config = Get-Content -Raw -LiteralPath $ConfigPath | ConvertFrom-Json
if ([string]::IsNullOrWhiteSpace($ServerHost)) {
$ServerHost = [string]$config.server.host
@@ -81,7 +113,8 @@ try {
if ($null -ne $CaseId) {
$meta.case_id = [int]$CaseId
}
$meta | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $metaPath -Encoding UTF8
$metaJson = $meta | ConvertTo-Json -Depth 6
[System.IO.File]::WriteAllText($metaPath, $metaJson, [System.Text.UTF8Encoding]::new($false))
& scp.exe -i $effectiveKeyPath -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL $metaPath $remoteTarget
if ($LASTEXITCODE -ne 0) {
throw "scp meta upload failed with rc=$LASTEXITCODE"
@@ -97,6 +130,7 @@ try {
if ($LASTEXITCODE -ne 0) {
throw "scp upload failed with rc=$LASTEXITCODE"
}
Write-RunLog ("upload complete zip={0} remote={1}" -f $zipPath, $remoteTarget)
}
finally {
Remove-Item -LiteralPath $effectiveKeyPath -Force -ErrorAction SilentlyContinue
+2
View File
@@ -119,6 +119,7 @@ $effectiveHayabusaAutoUploadIntervalHours = if ($existingConfig -and $existingCo
$effectiveHayabusaAutoUploadHoursBack = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'hayabusaAutomation' -and $existingConfig.forensics.hayabusaAutomation.PSObject.Properties.Name -contains 'hoursBack') { [int]$existingConfig.forensics.hayabusaAutomation.hoursBack } else { 6 }
$effectiveHayabusaAutoUploadMode = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'hayabusaAutomation' -and $existingConfig.forensics.hayabusaAutomation.PSObject.Properties.Name -contains 'mode') { [string]$existingConfig.forensics.hayabusaAutomation.mode } else { 'incident' }
$effectiveHayabusaAutoUploadTaskName = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'hayabusaAutomation' -and $existingConfig.forensics.hayabusaAutomation.PSObject.Properties.Name -contains 'taskName') { [string]$existingConfig.forensics.hayabusaAutomation.taskName } else { 'ActivityWatch Hayabusa Upload' }
$effectiveHayabusaAutoUploadRunAsUser = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'hayabusaAutomation' -and $existingConfig.forensics.hayabusaAutomation.PSObject.Properties.Name -contains 'runAsUser') { [string]$existingConfig.forensics.hayabusaAutomation.runAsUser } else { '' }
$effectiveFile1CAutoUploadEnabled = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'analytics' -and $existingConfig.analytics.PSObject.Properties.Name -contains 'file1cAutomation' -and $existingConfig.analytics.file1cAutomation.PSObject.Properties.Name -contains 'enabled') { [bool]$existingConfig.analytics.file1cAutomation.enabled } else { $true }
$effectiveFile1CAutoUploadIntervalHours = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'analytics' -and $existingConfig.analytics.PSObject.Properties.Name -contains 'file1cAutomation' -and $existingConfig.analytics.file1cAutomation.PSObject.Properties.Name -contains 'intervalHours') { [int]$existingConfig.analytics.file1cAutomation.intervalHours } else { 6 }
$effectiveFile1CAutoUploadIntervalMinutes = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'analytics' -and $existingConfig.analytics.PSObject.Properties.Name -contains 'file1cAutomation' -and $existingConfig.analytics.file1cAutomation.PSObject.Properties.Name -contains 'intervalMinutes') { [int]$existingConfig.analytics.file1cAutomation.intervalMinutes } else { [Math]::Max(1, $effectiveFile1CAutoUploadIntervalHours) * 60 }
@@ -237,6 +238,7 @@ $config = New-ActivityWatchDeploymentConfig `
-HayabusaAutoUploadHoursBack $effectiveHayabusaAutoUploadHoursBack `
-HayabusaAutoUploadMode $effectiveHayabusaAutoUploadMode `
-HayabusaAutoUploadTaskName $effectiveHayabusaAutoUploadTaskName `
-HayabusaAutoUploadRunAsUser $effectiveHayabusaAutoUploadRunAsUser `
-File1CAutoUploadEnabled $effectiveFile1CAutoUploadEnabled `
-File1CAutoUploadIntervalHours $effectiveFile1CAutoUploadIntervalHours `
-File1CAutoUploadIntervalMinutes $effectiveFile1CAutoUploadIntervalMinutes `