"""Probe remote host for Nexus file-manager sudo capability.""" from __future__ import annotations from server.domain.models import Server from server.infrastructure.ssh.asyncssh_pool import exec_ssh_command from server.utils.files_elevation import ( SUDOERS_DOC_PATH, FilesElevation, get_files_elevation, ) async def probe_files_capability(server: Server) -> dict: """Run lightweight SSH checks for passwordless sudo and chmod/chown whitelist.""" ssh_user = (server.username or "root").strip() or "root" elevation: FilesElevation = get_files_elevation(server) is_root = ssh_user == "root" if is_root: return { "ssh_user": ssh_user, "is_root": True, "files_elevation": elevation.value, "can_sudo_nopasswd": True, "whitelist_ok": True, "message": "SSH 用户为 root,无需 sudo 提权", "docs_path": SUDOERS_DOC_PATH, } sudo_probe = await exec_ssh_command(server, "sudo -n true", timeout=15) can_sudo_nopasswd = sudo_probe.get("exit_code") == 0 whitelist_probe = await exec_ssh_command( server, "sudo -n bash -c 'command -v chmod >/dev/null && command -v chown >/dev/null && command -v rsync >/dev/null'", timeout=15, ) whitelist_ok = can_sudo_nopasswd and whitelist_probe.get("exit_code") == 0 if can_sudo_nopasswd and whitelist_ok: message = "已配置免密 sudo,文件管理与推送可自动提权" elif can_sudo_nopasswd: message = ( "可免密 sudo,但 chmod/chown/rsync 可能未列入白名单;" "文件推送至 www 目录会失败,请参考仓库内 sudoers 示例补全" ) else: message = ( "无法免密 sudo;写权限、chmod 等可能失败。" "请在目标机安装 nexus-files.sudoers(见文档路径)" ) return { "ssh_user": ssh_user, "is_root": False, "files_elevation": elevation.value, "can_sudo_nopasswd": can_sudo_nopasswd, "whitelist_ok": whitelist_ok, "message": message, "docs_path": SUDOERS_DOC_PATH, }