From f22cd27e31585bf9e4370f5e703dd5a7f3aa7f3c Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Sat, 9 May 2026 11:00:59 +0300 Subject: [PATCH] fix(ansible): harden WinRM deploy wrapper with md4+retry --- ansible/README.md | 9 +++++++ ansible/deploy_aw_windows.yml | 2 ++ ansible/run_deploy_aw_windows.sh | 42 +++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/ansible/README.md b/ansible/README.md index 9baec79..a3680ed 100644 --- a/ansible/README.md +++ b/ansible/README.md @@ -99,6 +99,15 @@ cd ansible AW_WINRM_PASSWORD='...' bash ./run_deploy_aw_windows.sh ``` +`run_deploy_aw_windows.sh` автоматически: +- очищает proxy env (`http_proxy/https_proxy/...`), чтобы WinRM не уходил в локальный прокси; +- включает OpenSSL legacy provider, если на хосте отключён `MD4` (нужно для NTLM в pywinrm). +- перезапускает `ansible-playbook` при временных WinRM/NTLM сбоях (по умолчанию 5 попыток, пауза 30 сек). + +Параметры retry: +- `AW_DEPLOY_RETRIES` (по умолчанию `5`); +- `AW_DEPLOY_RETRY_DELAY_SEC` (по умолчанию `30`). + Playbook: - выгружает полный `windows/*` toolkit на целевой хост в InnoSetup-compatible каталог `C:\Program Files\AWatch-rus\windows`, включая DLP и `worktime-session-collector.ps1`; diff --git a/ansible/deploy_aw_windows.yml b/ansible/deploy_aw_windows.yml index 4bbd054..d02160e 100644 --- a/ansible/deploy_aw_windows.yml +++ b/ansible/deploy_aw_windows.yml @@ -4,6 +4,8 @@ gather_facts: false vars: + ansible_winrm_operation_timeout_sec: 120 + ansible_winrm_read_timeout_sec: 180 aw_windows_repo_root: "{{ playbook_dir | dirname }}" aw_windows_deploy_root: "C:\\Program Files\\AWatch-rus" aw_windows_server_scheme: "http" diff --git a/ansible/run_deploy_aw_windows.sh b/ansible/run_deploy_aw_windows.sh index 5276ed2..d9af0c4 100644 --- a/ansible/run_deploy_aw_windows.sh +++ b/ansible/run_deploy_aw_windows.sh @@ -4,6 +4,10 @@ set -euo pipefail # WinRM uses requests/pywinrm which may pick up local proxy settings (systemd env, shells, etc). # If that happens, WinRM traffic can be sent to 127.0.0.1: and time out. # This wrapper hard-disables proxy env vars to make deploy deterministic. +# +# Also, NTLM auth requires MD4. On OpenSSL 3 builds where MD4 is disabled by default, +# pywinrm fails with "unsupported hash type md4". In that case we enable OpenSSL legacy +# provider only for this process. if [[ -z "${AW_WINRM_PASSWORD:-}" ]]; then echo "ERROR: AW_WINRM_PASSWORD is not set" >&2 @@ -13,5 +17,41 @@ fi unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY all_proxy ALL_PROXY -exec ansible-playbook -i inventory.ini deploy_aw_windows.yml "$@" +if ! python3 - <<'PY' >/dev/null 2>&1 +import hashlib +raise SystemExit(0 if 'md4' in hashlib.algorithms_available else 1) +PY +then + cat >/tmp/openssl-legacy.cnf <<'EOF' +openssl_conf = openssl_init +[openssl_init] +providers = provider_sect +[provider_sect] +default = default_sect +legacy = legacy_sect +[default_sect] +activate = 1 +[legacy_sect] +activate = 1 +EOF + export OPENSSL_CONF=/tmp/openssl-legacy.cnf +fi +retries="${AW_DEPLOY_RETRIES:-5}" +delay="${AW_DEPLOY_RETRY_DELAY_SEC:-30}" + +attempt=1 +while [[ "$attempt" -le "$retries" ]]; do + echo "Deploy attempt $attempt/$retries" + if ansible-playbook -i inventory.ini deploy_aw_windows.yml "$@"; then + exit 0 + fi + if [[ "$attempt" -lt "$retries" ]]; then + echo "Deploy attempt $attempt failed; sleeping ${delay}s before retry..." >&2 + sleep "$delay" + fi + attempt=$((attempt + 1)) +done + +echo "Deploy failed after ${retries} attempts." >&2 +exit 1