#!/usr/bin/env bash
set -euo pipefail

TARGET_ROOT="${1:-.}"
BLACKSHIELD_SITE_URL="${BLACKSHIELD_SITE_URL:-https://app.blackshield.chaplau.com}"
BLACKSHIELD_API_URL="${BLACKSHIELD_API_URL:-https://api.blackshield.chaplau.com}"
BLACKSHIELD_OSSEC_VERSION="${BLACKSHIELD_OSSEC_VERSION:-4.0.0}"
BLACKSHIELD_VMS_NATIVE_PACKAGE_VERSION="${BLACKSHIELD_VMS_NATIVE_PACKAGE_VERSION:-1.0.6}"
BLACKSHIELD_VMS_NATIVE_PACKAGE_URL="${BLACKSHIELD_VMS_NATIVE_PACKAGE_URL:-${BLACKSHIELD_SITE_URL}/source-bundles/blackshield-vms-scanner-native-${BLACKSHIELD_VMS_NATIVE_PACKAGE_VERSION}.tar.gz}"
BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256="${BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256:-408dac4716a617782eaf72f445098afc2022c41c4c6c1bc106a658c468682b19}"

mkdir -p "$TARGET_ROOT/deploy/vm-scanner/managed"
env_file="$TARGET_ROOT/deploy/vm-scanner/managed/.env.vm-scanner"
stale_native_package_sha256_values="
bdb7a708f504f1dac7274fab54151dfd27cc96ce1a4fb8e67324eaf1c96ace6c
69fc019ab5df9c16ca3b529f190d31bd47400b52a12ba81fe3b35088443914f0
156ddd07b3ffd62923bb66d195621e372113b1009cceb7980e20ba5508db1268
bf047ae24d80ce35361ab8bba27338f081f7760b9f8dd5c52925ece180bed423
7b2f5b3c89a12d2f9cf7a8dd1aad9d76f9545b9af34a8bc05dc0a8567ee97005
9f71bf102816ad61c726ed7f4e6fdcb18037806fc92ced2dd1a1913e859ff852
"

if [ ! -f "$env_file" ]; then
cat > "$env_file" <<EOF
BLACKSHIELD_API_URL=${BLACKSHIELD_API_URL}
BLACKSHIELD_API_KEY=sp_xxxx
BLACKSHIELD_OSSEC_MODE=existing
BLACKSHIELD_OSSEC_VERSION=${BLACKSHIELD_OSSEC_VERSION}
BLACKSHIELD_VMS_NATIVE_PACKAGE_URL=${BLACKSHIELD_VMS_NATIVE_PACKAGE_URL}
BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256=${BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256}
VMS_COLLECTOR_MODE=file
OSSEC_ALERTS_FILE=/var/ossec/logs/alerts/alerts.json
OSSEC_STATE_FILE=/var/lib/blackshield/vm-scanner/ossec-state.json
SCAN_INTERVAL_SECONDS=60
SCAN_ON_STARTUP=true
MIN_SEVERITY=high
LOG_LEVEL=INFO
HEALTH_PORT=8080
EOF
  printf 'Wrote deploy/vm-scanner/managed/.env.vm-scanner\n'
else
  printf 'Preserved existing deploy/vm-scanner/managed/.env.vm-scanner\n'
  for stale_native_package_sha256 in $stale_native_package_sha256_values; do
    if grep -q "^BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256=${stale_native_package_sha256}$" "$env_file"; then
      sed -i.bak "s/^BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256=.*/BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256=${BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256}/" "$env_file"
      rm -f "${env_file}.bak"
      printf 'Updated deploy/vm-scanner/managed/.env.vm-scanner native package checksum\n'
      break
    fi
  done
fi

cat > "$TARGET_ROOT/deploy/vm-scanner/managed/.env.vm-scanner.example" <<EOF
BLACKSHIELD_API_URL=${BLACKSHIELD_API_URL}
BLACKSHIELD_API_KEY=sp_xxxx
BLACKSHIELD_OSSEC_MODE=existing
BLACKSHIELD_OSSEC_VERSION=${BLACKSHIELD_OSSEC_VERSION}
BLACKSHIELD_VMS_NATIVE_PACKAGE_URL=${BLACKSHIELD_VMS_NATIVE_PACKAGE_URL}
BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256=${BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256}
VMS_COLLECTOR_MODE=file
OSSEC_ALERTS_FILE=/var/ossec/logs/alerts/alerts.json
OSSEC_STATE_FILE=/var/lib/blackshield/vm-scanner/ossec-state.json
SCAN_INTERVAL_SECONDS=60
SCAN_ON_STARTUP=true
MIN_SEVERITY=high
LOG_LEVEL=INFO
HEALTH_PORT=8080
EOF

cat > "$TARGET_ROOT/deploy/vm-scanner/managed/blackshield-vms-scanner-run" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

ENV_FILE="${BLACKSHIELD_VMS_ENV_FILE:-/etc/blackshield/vm-scanner.env}"
RUNTIME_BIN="${BLACKSHIELD_VMS_RUNTIME_BIN:-/opt/blackshield/vm-scanner/venv/bin/blackshield-vms-scanner}"

fail() {
  printf 'blackshield-vms-scanner-run: %s\n' "$*" >&2
  exit 2
}

require_env() {
  local name="$1"
  if [ -z "${!name:-}" ]; then
    fail "${name} is required in ${ENV_FILE}"
  fi
}

if [ -r "$ENV_FILE" ]; then
  set -a
  . "$ENV_FILE"
  set +a
elif [ -z "${BLACKSHIELD_API_URL:-}" ] || [ -z "${BLACKSHIELD_API_KEY:-}" ] || \
  [ -z "${VMS_COLLECTOR_MODE:-}" ] || [ -z "${OSSEC_ALERTS_FILE:-}" ] || \
  [ -z "${OSSEC_STATE_FILE:-}" ]; then
  fail "env file is not readable at ${ENV_FILE}; systemd did not provide the required service environment"
fi

require_env BLACKSHIELD_API_URL
require_env BLACKSHIELD_API_KEY
require_env VMS_COLLECTOR_MODE
require_env OSSEC_ALERTS_FILE
require_env OSSEC_STATE_FILE

if [ "$BLACKSHIELD_API_KEY" = "sp_xxxx" ]; then
  fail "replace BLACKSHIELD_API_KEY before starting the service"
fi

case "$VMS_COLLECTOR_MODE" in
  file) ;;
  *) fail "managed native runner only supports VMS_COLLECTOR_MODE=file" ;;
esac

if [ ! -r "$OSSEC_ALERTS_FILE" ]; then
  fail "alerts.json is not readable at ${OSSEC_ALERTS_FILE}"
fi

mkdir -p "$(dirname "$OSSEC_STATE_FILE")"

if [ ! -x "$RUNTIME_BIN" ]; then
  fail "native runtime is not executable at ${RUNTIME_BIN}"
fi

exec "$RUNTIME_BIN"
EOF

cat > "$TARGET_ROOT/deploy/vm-scanner/managed/blackshield-vms-scanner.service" <<'EOF'
[Unit]
Description=BlackShield Managed VM Scanner
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=blackshield-vms-scanner
Group=blackshield-vms-scanner
EnvironmentFile=/etc/blackshield/vm-scanner.env
ExecStart=/usr/local/bin/blackshield-vms-scanner-run
Restart=always
RestartSec=10
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadOnlyPaths=/var/ossec/logs/alerts
ReadWritePaths=/var/lib/blackshield/vm-scanner

[Install]
WantedBy=multi-user.target
EOF

cat > "$TARGET_ROOT/deploy/vm-scanner/managed/install-managed-vm-scanner.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

ENV_SOURCE="${1:-.env.vm-scanner}"
SERVICE_NAME="blackshield-vms-scanner"
SERVICE_USER="blackshield-vms-scanner"
TEST_ROOT="${BLACKSHIELD_TEST_ROOT:-}"
DRY_RUN="${BLACKSHIELD_DRY_RUN:-false}"

ENV_TARGET="/etc/blackshield/vm-scanner.env"
RUNNER_TARGET="/usr/local/bin/blackshield-vms-scanner-run"
UNIT_TARGET="/etc/systemd/system/${SERVICE_NAME}.service"
APP_DIR="/opt/blackshield/vm-scanner"
STATE_DIR="/var/lib/blackshield/vm-scanner"
OSSEC_CONF="/var/ossec/etc/ossec.conf"
DEFAULT_ALERTS_FILE="/var/ossec/logs/alerts/alerts.json"

log() {
  printf '[blackshield-vm-scanner] %s\n' "$*"
}

fail() {
  printf '[blackshield-vm-scanner] ERROR: %s\n' "$*" >&2
  exit 2
}

is_dry_run() {
  [ "$DRY_RUN" = "1" ] || [ "$DRY_RUN" = "true" ]
}

root_path() {
  local path="$1"
  if [ -n "$TEST_ROOT" ]; then
    printf '%s%s' "$TEST_ROOT" "$path"
  else
    printf '%s' "$path"
  fi
}

install_file() {
  local source="$1"
  local target="$2"
  local mode="$3"
  install -D -m "$mode" "$source" "$(root_path "$target")"
}

require_root_or_test_root() {
  if [ -n "$TEST_ROOT" ]; then
    return
  fi
  if [ "${EUID:-$(id -u)}" -ne 0 ]; then
    fail "run this installer with sudo, or set BLACKSHIELD_TEST_ROOT for tests"
  fi
}

load_env() {
  if [ ! -r "$ENV_SOURCE" ]; then
    fail "env file is not readable at ${ENV_SOURCE}"
  fi
  set -a
  . "$ENV_SOURCE"
  set +a
}

require_env() {
  local name="$1"
  if [ -z "${!name:-}" ]; then
    fail "${name} is required in ${ENV_SOURCE}"
  fi
}

validate_env() {
  BLACKSHIELD_OSSEC_MODE="${BLACKSHIELD_OSSEC_MODE:-existing}"
  BLACKSHIELD_OSSEC_VERSION="${BLACKSHIELD_OSSEC_VERSION:-4.0.0}"
  VMS_COLLECTOR_MODE="${VMS_COLLECTOR_MODE:-file}"
  OSSEC_ALERTS_FILE="${OSSEC_ALERTS_FILE:-$DEFAULT_ALERTS_FILE}"
  OSSEC_STATE_FILE="${OSSEC_STATE_FILE:-$STATE_DIR/ossec-state.json}"
  HEALTH_PORT="${HEALTH_PORT:-8080}"

  require_env BLACKSHIELD_API_URL
  require_env BLACKSHIELD_API_KEY
  require_env BLACKSHIELD_VMS_NATIVE_PACKAGE_URL
  require_env BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256

  if [ "$BLACKSHIELD_API_KEY" = "sp_xxxx" ] || [ "${BLACKSHIELD_API_KEY#sp_}" = "$BLACKSHIELD_API_KEY" ]; then
    fail "replace BLACKSHIELD_API_KEY with a dedicated sp_ ingestion key before installing"
  fi

  case "$BLACKSHIELD_OSSEC_MODE" in
    auto|existing|managed-local) ;;
    *) fail "BLACKSHIELD_OSSEC_MODE must be auto, existing, or managed-local" ;;
  esac

  if [ "$VMS_COLLECTOR_MODE" != "file" ]; then
    fail "managed Linux installs use VMS_COLLECTOR_MODE=file; use S3/GCS bundles for object storage"
  fi
}

ensure_ubuntu_or_debian() {
  local os_release
  os_release="$(root_path /etc/os-release)"
  if [ ! -r "$os_release" ]; then
    os_release="/etc/os-release"
  fi
  if [ ! -r "$os_release" ]; then
    fail "cannot determine Linux distribution; v1 managed installs support Ubuntu/Debian systemd hosts"
  fi

  # shellcheck disable=SC1090
  . "$os_release"
  case "${ID:-}" in
    ubuntu|debian) return ;;
  esac
  case " ${ID_LIKE:-} " in
    *" debian "*) return ;;
  esac
  fail "unsupported Linux distribution '${ID:-unknown}'; v1 managed installs support Ubuntu/Debian systemd hosts"
}

service_exists() {
  local service="$1"
  if [ -n "$TEST_ROOT" ]; then
    [ -e "$(root_path "/etc/systemd/system/${service}.service")" ] && return 0
    [ -e "$(root_path "/lib/systemd/system/${service}.service")" ] && return 0
    return 1
  fi
  systemctl list-unit-files "${service}.service" --no-legend 2>/dev/null | grep -q "^${service}.service" && return 0
  systemctl status "${service}.service" >/dev/null 2>&1 && return 0
  return 1
}

detect_alert_source() {
  if [ -r "$(root_path "$OSSEC_ALERTS_FILE")" ]; then
    printf 'existing-alert-source\n'
    return
  fi
  if service_exists wazuh-manager; then
    printf 'wazuh-manager\n'
    return
  fi
  if service_exists ossec || service_exists ossec-hids || [ -x "$(root_path /var/ossec/bin/ossec-control)" ]; then
    printf 'ossec-local\n'
    return
  fi
  if service_exists wazuh-agent || [ -x "$(root_path /var/ossec/bin/wazuh-control)" ]; then
    printf 'wazuh-agent-only\n'
    return
  fi
  printf 'none\n'
}

ensure_host_packages() {
  if is_dry_run; then
    log "dry-run: would install apt prerequisites"
    return
  fi
  export DEBIAN_FRONTEND=noninteractive
  apt-get update
  apt-get install -y ca-certificates curl tar python3 python3-venv
}

install_ossec_build_packages() {
  if is_dry_run; then
    log "dry-run: would install OSSEC build prerequisites"
    return
  fi
  export DEBIAN_FRONTEND=noninteractive
  apt-get install -y build-essential make zlib1g-dev libpcre2-dev libevent-dev libssl-dev libsystemd-dev
}

install_managed_ossec_local() {
  log "installing OSSEC ${BLACKSHIELD_OSSEC_VERSION} in local mode"
  if is_dry_run; then
    install -d -m 755 "$(root_path /var/ossec/etc)" "$(root_path /var/ossec/logs/alerts)"
    cat > "$(root_path "$OSSEC_CONF")" <<'CONF'
<ossec_config>
  <global>
  </global>
</ossec_config>
CONF
    touch "$(root_path "$OSSEC_ALERTS_FILE")"
    return
  fi

  install_ossec_build_packages
  local tmp_dir source_dir archive_path
  tmp_dir="$(mktemp -d)"
  archive_path="${tmp_dir}/ossec-hids.tar.gz"
  curl -fsSL "https://github.com/ossec/ossec-hids/archive/refs/tags/${BLACKSHIELD_OSSEC_VERSION}.tar.gz" -o "$archive_path"
  tar -xzf "$archive_path" -C "$tmp_dir"
  source_dir="$(find "$tmp_dir" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
  cat > "${source_dir}/etc/preloaded-vars.conf" <<CONF
USER_LANGUAGE="en"
USER_NO_STOP="y"
USER_INSTALL_TYPE="local"
USER_DIR="/var/ossec"
USER_ENABLE_EMAIL="n"
USER_ENABLE_SYSLOG="n"
USER_ENABLE_ACTIVE_RESPONSE="y"
USER_ENABLE_SYSCHECK="y"
USER_ENABLE_ROOTCHECK="y"
CONF
  (cd "$source_dir" && PCRE2_SYSTEM=yes ZLIB_SYSTEM=yes ./install.sh)
}

enable_json_alerts() {
  local conf_path
  conf_path="$(root_path "$OSSEC_CONF")"
  if [ ! -r "$conf_path" ]; then
    fail "OSSEC config is not readable at ${OSSEC_CONF}"
  fi
  cp "$conf_path" "${conf_path}.blackshield.bak"
  python3 - "$conf_path" <<'PY'
import sys
import xml.etree.ElementTree as ET

path = sys.argv[1]
tree = ET.parse(path)
root = tree.getroot()
global_node = root.find("global")
if global_node is None:
    global_node = ET.SubElement(root, "global")
json_node = global_node.find("jsonout_output")
if json_node is None:
    json_node = ET.SubElement(global_node, "jsonout_output")
json_node.text = "yes"
tree.write(path, encoding="unicode")
PY
}

restart_ossec() {
  if is_dry_run; then
    log "dry-run: would restart OSSEC/Wazuh manager or local service"
    return
  fi
  if service_exists wazuh-manager; then
    systemctl restart wazuh-manager
  elif service_exists ossec; then
    systemctl restart ossec
  elif service_exists ossec-hids; then
    systemctl restart ossec-hids
  elif [ -x /var/ossec/bin/ossec-control ]; then
    /var/ossec/bin/ossec-control restart || /var/ossec/bin/ossec-control start
  else
    fail "unable to find an OSSEC/Wazuh manager service to restart"
  fi
}

ensure_alerts_file() {
  local alerts_path attempts
  alerts_path="$(root_path "$OSSEC_ALERTS_FILE")"
  attempts=0
  while [ "$attempts" -lt 30 ]; do
    if [ -r "$alerts_path" ]; then
      return
    fi
    attempts=$((attempts + 1))
    sleep 1
  done

  if [ "$BLACKSHIELD_OSSEC_MODE" = "existing" ]; then
    fail "alerts.json is not readable at ${OSSEC_ALERTS_FILE}"
  fi

  install -d -m 755 "$(dirname "$alerts_path")"
  touch "$alerts_path"
  chmod 0644 "$alerts_path"
}

install_native_runtime() {
  local package_path
  install -d -m 755 "$(root_path "$APP_DIR")"

  if is_dry_run; then
    install -d -m 755 "$(root_path "$APP_DIR/venv/bin")"
    cat > "$(root_path "$APP_DIR/venv/bin/blackshield-vms-scanner")" <<'SCRIPT'
#!/usr/bin/env sh
printf 'blackshield-vms-scanner dry-run runtime\n'
SCRIPT
    chmod 0755 "$(root_path "$APP_DIR/venv/bin/blackshield-vms-scanner")"
    return
  fi

  python3 -m venv "${APP_DIR}/venv"
  "${APP_DIR}/venv/bin/python" -m pip install --upgrade pip setuptools wheel
  package_path="$(mktemp -t blackshield-vms-scanner-native.XXXXXX.tar.gz)"
  curl -fsSL "$BLACKSHIELD_VMS_NATIVE_PACKAGE_URL" -o "$package_path"
  printf '%s  %s\n' "$BLACKSHIELD_VMS_NATIVE_PACKAGE_SHA256" "$package_path" | sha256sum -c -
  "${APP_DIR}/venv/bin/python" -m pip install "$package_path"
}

install_service_user() {
  install -d -m 750 "$(root_path "$STATE_DIR")"
  if is_dry_run; then
    return
  fi
  if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then
    useradd --system --home-dir "$STATE_DIR" --shell /usr/sbin/nologin "$SERVICE_USER"
  fi
  chown -R "$SERVICE_USER:$SERVICE_USER" "$STATE_DIR"

  local alerts_group
  alerts_group="$(stat -c %G "$OSSEC_ALERTS_FILE" 2>/dev/null || true)"
  if [ -n "$alerts_group" ] && [ "$alerts_group" != "UNKNOWN" ]; then
    usermod -a -G "$alerts_group" "$SERVICE_USER" || true
  fi
}

verify_service_user_alert_access() {
  if is_dry_run; then
    return
  fi
  if runuser -u "$SERVICE_USER" -- test -r "$OSSEC_ALERTS_FILE"; then
    return
  fi

  fail "${SERVICE_USER} cannot read ${OSSEC_ALERTS_FILE}; grant that service account read access before starting the scanner"
}

install_systemd_assets() {
  install -d -m 750 "$(root_path /etc/blackshield)"
  install_file "$ENV_SOURCE" "$ENV_TARGET" 0640
  install_file "blackshield-vms-scanner-run" "$RUNNER_TARGET" 0755
  install_file "blackshield-vms-scanner.service" "$UNIT_TARGET" 0644

  if is_dry_run; then
    log "dry-run: installed files under ${TEST_ROOT:-/}"
    return
  fi

  chown root:"$SERVICE_USER" /etc/blackshield "$ENV_TARGET"
  chmod 0750 /etc/blackshield
  chmod 0640 "$ENV_TARGET"
  systemctl daemon-reload
  systemctl enable --now "$SERVICE_NAME"
}

main() {
  require_root_or_test_root
  load_env
  validate_env
  ensure_ubuntu_or_debian
  ensure_host_packages

  local source_kind
  source_kind="$(detect_alert_source)"
  case "$source_kind" in
    existing-alert-source|wazuh-manager|ossec-local)
      log "using existing OSSEC/Wazuh alert source (${source_kind})"
      ;;
    wazuh-agent-only)
      fail "detected a Wazuh agent-only endpoint without manager-side alerts.json; run BlackShield on the Wazuh manager/OSSEC server/local install, or use the S3/GCS sync path"
      ;;
    none)
      if [ "$BLACKSHIELD_OSSEC_MODE" = "existing" ]; then
        fail "BLACKSHIELD_OSSEC_MODE=existing requires a readable ${OSSEC_ALERTS_FILE}"
      fi
      install_managed_ossec_local
      ;;
    *)
      fail "unexpected OSSEC detection result: ${source_kind}"
      ;;
  esac

  enable_json_alerts
  restart_ossec
  ensure_alerts_file
  install_native_runtime
  install_service_user
  verify_service_user_alert_access
  install_systemd_assets

  log "managed VM scanner installed"
  log "verify with: sudo systemctl status blackshield-vms-scanner --no-pager"
  log "health check: curl http://localhost:${HEALTH_PORT}/health"
}

main "$@"
EOF

cat > "$TARGET_ROOT/deploy/vm-scanner/managed/README.md" <<'EOF'
# Managed Linux VM Scanner

This is the recommended Ubuntu/Debian path when you want the BlackShield VM
scanner to ingest an existing Wazuh or OSSEC alert source from a native service.

1. Open `.env.vm-scanner` and replace `BLACKSHIELD_API_KEY` with a dedicated
   Ingestion API key. If that key was pasted into a terminal transcript, ticket,
   or chat, revoke it and create a new key before testing.
2. Leave `BLACKSHIELD_OSSEC_MODE=existing` for the safe default path when a
   Wazuh manager, OSSEC server, or OSSEC local install already writes
   `/var/ossec/logs/alerts/alerts.json`. Set `managed-local` only when your
   organization has approved this installer to download and install OSSEC
   GPLv2 local mode. `auto` is still accepted for compatibility.
3. Install the managed service:

```bash
sudo ./install-managed-vm-scanner.sh
```

The service runs natively from `/opt/blackshield/vm-scanner/venv`, stores
incremental scanner state in `/var/lib/blackshield/vm-scanner/ossec-state.json`,
and exposes health on `${HEALTH_PORT:-8080}`.

## Existing Wazuh and OSSEC

Wazuh managers and OSSEC server/local installs write manager-side alerts to
`/var/ossec/logs/alerts/alerts.json`. Wazuh agent-only endpoints normally do not
own that file; install BlackShield on the manager/server/local host, or use the
S3/GCS sync path from the advanced bundles.

## Optional managed OSSEC local mode

For a fresh Ubuntu/Debian VM with no existing Wazuh or OSSEC alert source, set
`BLACKSHIELD_OSSEC_MODE=managed-local` only after your organization approves
the OSSEC GPLv2 install path. The installer downloads OSSEC source, configures
local mode, enables JSON alerts, and then installs the BlackShield native
scanner service.

## Troubleshooting

```bash
sudo systemctl status blackshield-vms-scanner --no-pager
sudo journalctl -u blackshield-vms-scanner -n 100 --no-pager
sudo -u blackshield-vms-scanner test -r /etc/blackshield/vm-scanner.env
sudo -u blackshield-vms-scanner test -r /var/ossec/logs/alerts/alerts.json
curl http://localhost:8080/health
curl http://localhost:8080/metrics
```

For OSSEC/Wazuh freshness, cross-check the official docs:

- Wazuh Linux agent install: https://documentation.wazuh.com/current/installation-guide/wazuh-agent/wazuh-agent-package-linux.html
- Wazuh alert files: https://documentation.wazuh.com/current/user-manual/manager/alert-management.html
- OSSEC JSON output: https://www.ossec.net/docs/docs/manual/output/json-alert-log-output.html
- OSSEC unattended install: https://www.ossec.net/docs/docs/manual/installation/install-source-unattended.html
EOF

chmod +x "$TARGET_ROOT/deploy/vm-scanner/managed/install-managed-vm-scanner.sh"
chmod +x "$TARGET_ROOT/deploy/vm-scanner/managed/blackshield-vms-scanner-run"

printf 'Wrote deploy/vm-scanner/managed/.env.vm-scanner.example\n'
printf 'Wrote deploy/vm-scanner/managed/blackshield-vms-scanner-run\n'
printf 'Wrote deploy/vm-scanner/managed/blackshield-vms-scanner.service\n'
printf 'Wrote deploy/vm-scanner/managed/install-managed-vm-scanner.sh\n'
printf 'Wrote deploy/vm-scanner/managed/README.md\n'
