fix: WinRM try host.hostname first like Enter-PSSession (0.10.4)

This commit is contained in:
2026-06-20 00:13:02 +10:00
parent c8e3eef9d7
commit 279ea925a8
6 changed files with 56 additions and 13 deletions
+35 -8
View File
@@ -35,8 +35,28 @@ def resolve_windows_host_target(host: Host) -> str:
return targets[0]
def _netbios_name_variants(name: str | None) -> list[str]:
"""Короткое имя ПК (NetBIOS), как Enter-PSSession -ComputerName Andrisonova-PC."""
text = (name or "").strip()
if not text:
return []
short = text.split(".")[0].split("\\")[0].strip()
if not short:
return []
if short.casefold() == text.casefold():
return [short]
return [short, text]
def _looks_like_computer_name(value: str) -> bool:
text = value.strip()
if not text or " " in text:
return False
return len(text) <= 63
def iter_winrm_targets(host: Host) -> list[str]:
"""WinRM + NTLM: сначала имя машины (SPN), затем IPv4."""
"""WinRM + NTLM: сначала имя хоста (как Enter-PSSession -ComputerName), IP — последним."""
if not is_windows_host(host):
raise HostNotWindowsError("Host is not Windows")
@@ -45,17 +65,24 @@ def iter_winrm_targets(host: Host) -> list[str]:
def add(value: str | None) -> None:
text = (value or "").strip()
if not text or text in seen:
if not text or text.casefold() in seen:
return
seen.add(text)
seen.add(text.casefold())
ordered.append(text)
for variant in _netbios_name_variants(host.hostname):
add(variant)
inventory = host.inventory if isinstance(host.inventory, dict) else {}
computer_name = inventory.get("computer_name")
if isinstance(computer_name, str):
add(computer_name)
add(host.hostname)
add(host.display_name)
for variant in _netbios_name_variants(computer_name):
add(variant)
if host.display_name and _looks_like_computer_name(host.display_name):
for variant in _netbios_name_variants(host.display_name):
add(variant)
add(host.ipv4)
return ordered
@@ -104,8 +131,8 @@ def test_winrm_connection(
hint = ""
if "credentials were rejected" in detail.lower():
hint = (
" Проверьте логин (B26\\user), пароль и что учётка — admin на целевом ПК; "
"при подключении по IP NTLM часто отклоняет creds — используйте имя хоста."
" Проверьте логин (B26\\user), пароль и права admin на ПК; "
"подключайтесь по имени хоста (как Enter-PSSession -ComputerName), не по IP."
)
return WinRmTestResult(
ok=False,
+1 -1
View File
@@ -1,5 +1,5 @@
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
APP_NAME = "Security Alert Center"
APP_VERSION = "0.10.3"
APP_VERSION = "0.10.4"
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
+2 -2
View File
@@ -4,6 +4,6 @@ from app.version import APP_NAME, APP_VERSION, APP_VERSION_LABEL
def test_version_constants():
assert APP_VERSION == "0.10.3"
assert APP_VERSION == "0.10.4"
assert APP_NAME == "Security Alert Center"
assert APP_VERSION_LABEL == "Security Alert Center v.0.10.3"
assert APP_VERSION_LABEL == "Security Alert Center v.0.10.4"
+16
View File
@@ -4,6 +4,7 @@ from unittest.mock import patch
from app.models.ui_settings import UI_SETTINGS_ROW_ID, UiSettings
from app.services.win_admin_settings import normalize_win_admin_user
from app.services.winrm_connect import iter_winrm_targets
def test_normalize_win_admin_user():
@@ -11,6 +12,21 @@ def test_normalize_win_admin_user():
assert normalize_win_admin_user(r"B26\papatramp") == r"B26\papatramp"
def test_iter_winrm_targets_hostname_before_ip():
from app.models import Host
host = Host(
hostname="Andrisonova-PC",
os_family="windows",
product="rdp-login-monitor",
ipv4="192.168.1.50",
inventory={"computer_name": "Andrisonova-PC"},
)
targets = iter_winrm_targets(host)
assert targets[0] == "Andrisonova-PC"
assert targets[-1] == "192.168.1.50"
def test_get_win_admin_settings_env_default(jwt_headers, client, monkeypatch):
monkeypatch.setenv("SAC_WIN_ADMIN_USER", "")
monkeypatch.setenv("SAC_WIN_ADMIN_PASSWORD", "")
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "sac-ui",
"private": true,
"version": "0.10.3",
"version": "0.10.4",
"type": "module",
"scripts": {
"dev": "vite",
+1 -1
View File
@@ -1,4 +1,4 @@
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
export const APP_NAME = "Security Alert Center";
export const APP_VERSION = "0.10.3";
export const APP_VERSION = "0.10.4";
export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;