Add shadow security finding inbox
CI / Rust checks (push) Canceled after 0s
CI / Docs and registry checks (push) Canceled after 0s
CI / Smoke checks (push) Canceled after 0s
Coverage / Coverage baseline (push) Canceled after 0s
Security / Cargo audit (push) Canceled after 0s
Security / Cargo deny (push) Canceled after 0s
Security / Secret pattern check (push) Canceled after 0s
Security / Dependency review (push) Canceled after 0s
CI / Rust checks (push) Canceled after 0s
CI / Docs and registry checks (push) Canceled after 0s
CI / Smoke checks (push) Canceled after 0s
Coverage / Coverage baseline (push) Canceled after 0s
Security / Cargo audit (push) Canceled after 0s
Security / Cargo deny (push) Canceled after 0s
Security / Secret pattern check (push) Canceled after 0s
Security / Dependency review (push) Canceled after 0s
This commit is contained in:
@@ -79,6 +79,13 @@ Behavior:
|
||||
- optional `*.caseid` sidecar with the same basename triggers automatic bounded case linkage
|
||||
- processed `*.zip` is moved out of `drop/` into `report_dir/input-drop/` to avoid repeated re-trigger loops
|
||||
- sidecars are archived into `report_dir/input-sidecars/`
|
||||
- bad drop packages are rejected before `accept`, moved to
|
||||
`/opt/hayabusa/quarantine/drop/<timestamp>_<package>/`, and recorded with a
|
||||
`reason.json` file instead of blocking later packages
|
||||
- bad or partially extracted incoming packages are moved to
|
||||
`/opt/hayabusa/quarantine/incoming/<timestamp>_<package>/`; `process-inbox`
|
||||
continues with the remaining queue and does not trip systemd start-limit only
|
||||
because of one poison archive
|
||||
|
||||
## Windows direct upload into the drop zone
|
||||
|
||||
@@ -118,4 +125,43 @@ Production scheduled task on `SHARKON2025`:
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Poison-package handling is fail-closed:
|
||||
|
||||
- Rust `aw-hayabusa-autoprocess-rust` validates the zip and sidecars before
|
||||
calling `aw-hayabusa accept`.
|
||||
- A corrupt/empty/unsafe drop package is quarantined with its `.meta.json`,
|
||||
`.caseid`, optional checksum sidecar and `reason.json`.
|
||||
- `aw-hayabusa process-inbox` isolates a failed incoming package instead of
|
||||
aborting the whole batch.
|
||||
- Operators replay only a fixed/re-exported package by moving it back to the
|
||||
drop zone or incoming queue. Do not edit quarantined evidence in place.
|
||||
|
||||
## Security Finding Inbox integration
|
||||
|
||||
`aw-hayabusa-autoprocess-rust` can publish a normalized suspicious-workstation
|
||||
finding after a successful intake is written to `/opt/hayabusa/state/latest-intake.json`.
|
||||
|
||||
Default is disabled to keep forensic processing independent from ClickHouse:
|
||||
|
||||
```bash
|
||||
AW_SECURITY_FINDING_INBOX_ENABLED=false
|
||||
```
|
||||
|
||||
Enable after the ClickHouse schema and CLI are installed:
|
||||
|
||||
```bash
|
||||
AW_SECURITY_FINDING_INBOX_ENABLED=true
|
||||
AW_SECURITY_FINDING_INBOX_BIN=/usr/local/bin/security-finding-inbox
|
||||
AW_SECURITY_FINDING_INBOX_MIN_SEVERITY=medium
|
||||
AW_SECURITY_FINDING_INBOX_REQUIRED=false
|
||||
```
|
||||
|
||||
With `AW_SECURITY_FINDING_INBOX_REQUIRED=false`, a temporary ClickHouse/inbox
|
||||
failure is logged as warning and does not poison the Hayabusa backlog. Use
|
||||
`true` only when the operator wants inbox publication failure to become an
|
||||
operational failure for the drop service.
|
||||
|
||||
@@ -14,6 +14,7 @@ HAYA_STAGING_DIR="${AW_HAYABUSA_STAGING_DIR:-${HAYA_ROOT}/inbox/staging}"
|
||||
HAYA_ARCHIVE_PACKAGES_DIR="${AW_HAYABUSA_ARCHIVE_PACKAGES_DIR:-${HAYA_ROOT}/archive/packages}"
|
||||
HAYA_ARCHIVE_EXTRACTED_DIR="${AW_HAYABUSA_ARCHIVE_EXTRACTED_DIR:-${HAYA_ROOT}/archive/extracted}"
|
||||
HAYA_LOGS_DIR="${AW_HAYABUSA_LOGS_DIR:-${HAYA_ROOT}/state/logs}"
|
||||
HAYA_QUARANTINE_DIR="${AW_HAYABUSA_QUARANTINE_DIR:-${HAYA_ROOT}/quarantine/incoming}"
|
||||
LAST_REPORT_DIR=""
|
||||
|
||||
usage() {
|
||||
@@ -57,7 +58,8 @@ ensure_layout() {
|
||||
"${HAYA_INCOMING_DIR}" \
|
||||
"${HAYA_STAGING_DIR}" \
|
||||
"${HAYA_ARCHIVE_PACKAGES_DIR}" \
|
||||
"${HAYA_ARCHIVE_EXTRACTED_DIR}"
|
||||
"${HAYA_ARCHIVE_EXTRACTED_DIR}" \
|
||||
"${HAYA_QUARANTINE_DIR}"
|
||||
}
|
||||
|
||||
run_logged() {
|
||||
@@ -405,7 +407,8 @@ process_one_package() {
|
||||
|
||||
package_sha256="$(sha256sum "${package_path}" | awk '{print $1}')"
|
||||
if ! extract_zip_normalized "${package_path}" "${stage_dir}"; then
|
||||
fail "normalized zip extraction failed for ${package_path}"
|
||||
echo "ERROR: normalized zip extraction failed for ${package_path}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local manifest_path host evtx_root archive_pkg_dir archive_extract_dir status report_dir
|
||||
@@ -453,7 +456,47 @@ process_one_package() {
|
||||
if [ -n "${report_dir}" ]; then
|
||||
echo "Report directory: ${report_dir}"
|
||||
fi
|
||||
[ "${status}" = "ok" ] || fail "Package workflow ended with status=${status}; archived for inspection"
|
||||
if [ "${status}" != "ok" ]; then
|
||||
echo "ERROR: Package workflow ended with status=${status}; archived for inspection" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
quarantine_incoming_package() {
|
||||
local package_path="$1"
|
||||
local reason="$2"
|
||||
local ts package_name package_base safe_base target_dir stage_dir sha256
|
||||
ts="$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
package_name="$(basename "${package_path}")"
|
||||
package_base="${package_name%.zip}"
|
||||
safe_base="$(sanitize "${package_name}")"
|
||||
[ -n "${safe_base}" ] || safe_base="package.zip"
|
||||
target_dir="${HAYA_QUARANTINE_DIR}/${ts}_${safe_base}"
|
||||
mkdir -p "${target_dir}"
|
||||
sha256=""
|
||||
if [ -f "${package_path}" ] && command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256="$(sha256sum "${package_path}" | awk '{print $1}')"
|
||||
fi
|
||||
for candidate in "${package_path}" "${package_path}.sha256" "${package_path}.host"; do
|
||||
if [ -e "${candidate}" ]; then
|
||||
mv "${candidate}" "${target_dir}/"
|
||||
fi
|
||||
done
|
||||
stage_dir="${HAYA_STAGING_DIR}/${package_base}"
|
||||
if [ -d "${stage_dir}" ]; then
|
||||
mv "${stage_dir}" "${target_dir}/staging-partial"
|
||||
fi
|
||||
cat >"${target_dir}/reason.json" <<EOF
|
||||
{
|
||||
"quarantined_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"source": "aw-hayabusa process-inbox",
|
||||
"original_path": "${package_path}",
|
||||
"sha256": "${sha256}",
|
||||
"reason": "${reason}",
|
||||
"operator_action": "inspect source package, re-export EVTX archive if needed, then replay by moving a fixed package back to incoming or drop"
|
||||
}
|
||||
EOF
|
||||
echo "Quarantined failed incoming package: ${target_dir}" >&2
|
||||
}
|
||||
|
||||
process_inbox() {
|
||||
@@ -482,15 +525,26 @@ process_inbox() {
|
||||
esac
|
||||
ensure_layout
|
||||
|
||||
local count=0 pkg
|
||||
local count=0 failed=0 pkg
|
||||
while IFS= read -r pkg; do
|
||||
process_one_package "${pkg}" "${mode}"
|
||||
count=$((count + 1))
|
||||
if process_one_package "${pkg}" "${mode}"; then
|
||||
count=$((count + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
if [ -f "${pkg}" ]; then
|
||||
quarantine_incoming_package "${pkg}" "process_one_package failed"
|
||||
else
|
||||
echo "Package failed after archive/move, see archive intake manifest for details: ${pkg}" >&2
|
||||
fi
|
||||
fi
|
||||
if [ "${limit}" -gt 0 ] && [ "${count}" -ge "${limit}" ]; then
|
||||
break
|
||||
fi
|
||||
done < <(find "${HAYA_INCOMING_DIR}" -maxdepth 1 -type f -name '*.zip' | sort)
|
||||
[ "${count}" -gt 0 ] || echo "No packages in ${HAYA_INCOMING_DIR}"
|
||||
if [ "${failed}" -gt 0 ]; then
|
||||
echo "process-inbox completed with quarantined_or_archived_failures=${failed}" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
|
||||
Reference in New Issue
Block a user