ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Salt macOS 模块修复:`mac_brew_pkg.homebrew_prefix()` 不再无条件触发 `su` 密码提示

Salt macOS 模块修复:`mac_brew_pkg.homebrew_prefix()` 不再无条件触发 `su` 密码提示 运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载导读本文讲解 Salt 在 macOS 平台上的 Homebrew 软件包管理模块mac_brew_pkg中一次典型缺陷的修复homebrew_prefix()探测函数会在每次调用时触发su密码提示或在非 TTY 环境下报su: Sorry罪魁祸首是cmdmod.run在 macOS 上对runas参数的无条件su -l包装。读完本文你将理解 Salt 执行模块在 macOS 上的提权实现细节、该缺陷的根因与修复思路以及配套回归测试如何锁定修复行为。背景homebrew_prefix()是 mac_brew_pkg 模块的基石mac_brew_pkg是 Salt 在 macOS 上管理 Homebrew 软件包的执行模块其虚拟名称为pkg仅当osgrain 为MacOS且能找到brew二进制时才加载见 salt/modules/mac_brew_pkg.py 中的__virtual__()。而homebrew_prefix()用于探测 Homebrew 的安装前缀Intel Mac 通常为/usr/localApple Silicon Mac 通常为/opt/homebrew是模块内众多功能的依赖基础例如_homebrew_bin()通过它拼接出brew二进制完整路径prefix/bin/brew见 salt/modules/mac_brew_pkg.py_call_brew()基于该路径构造实际的brew命令调用salt/modules/mac_brew_pkg.py__virtual__()中也会通过_homebrew_bin()校验brew是否存在。因此homebrew_prefix()几乎在模块每次被实际使用时都会被调用任何低效或引发交互式提示的实现都会被放大为高频故障。问题根因cmdmod.run在 macOS 上对runas的无条件su -l包装修复前的homebrew_prefix()会无条件地把 brew 二进制所有者作为runas传给cmdmod.run以brew --prefix探测前缀。问题在于cmdmod.run在 macOS 平台上的特殊处理逻辑见 salt/modules/cmdmod.pyif runas and salt.utils.platform.is_darwin(): # ... 组装为 login shell 命令 cmd fsu -l {_cmd_quote(runas)} -c {_cmd_quote(cmd)} # Set runas to None, because if you try to run su -l after changing # user, su will prompt for the password of the user and cause salt to # hang. runas None从源码结构看macOS 上任何非空runas都会导致命令被包装成su -l user -c ...。当 brew 二进制的所有者恰好就是当前进程用户例如非 root 用户通过 salt-ssh 管理自己所有的 Homebrew 环境时这条su -l依旧会被执行从而在交互式终端触发su密码提示在非 TTY 调用如 salt-ssh、自动化任务中直接报su: Sorry并失败。由于homebrew_prefix()是高频基础调用该问题在每次调用时都会复现属于典型的探测函数反而导致命令无法执行的回归缺陷。修复方案仅在所有者不同时传递runas修复后的homebrew_prefix()不再无条件传递runas而是在调用cmdmod.run之前先比较 brew 二进制所有者与当前进程用户见 salt/modules/mac_brew_pkg.py# Try brew --prefix otherwise try: log.debug(Trying to find homebrew prefix by running brew --prefix) brew _homebrew_os_bin() if brew is not None: # Check if the found brew command is the right one import salt.modules.cmdmod import salt.modules.file runas salt.modules.file.get_user(brew) # Only pass runas when the brew binary is owned by a different # user than the current process. On macOS, cmdmod.run with a # truthy runas wraps the command in su -l user -c ... # unconditionally, which triggers a password prompt (or # su: Sorry on non-tty invocations) even when the target user # is the current user. See #69027. try: if runas getpass.getuser(): runas None except Exception: # pylint: disablebroad-except # getpass.getuser() can raise on unusual environments (e.g. # empty passwd db); fall back to sending runas as-is. pass ret salt.modules.cmdmod.run( brew --prefix, runasrunas, output_logleveltrace, raise_errTrue ) return ret except CommandExecutionError as exc: log.debug( Unable to find homebrew prefix by running brew --prefix. Error: %s, exc ) return None关键逻辑拆解所有者探测通过salt.modules.file.get_user(brew)获取 brew 二进制的所有者用户名get_user基于文件stats返回user字段见 salt/modules/file.py条件归零用getpass.getuser()取得当前进程用户若二者相同则将runas置为None从而在cmdmod.run的 macOS 分支中跳过su -l包装因为该分支要求runas为真值异常兜底getpass.getuser()在异常环境如空的 passwd 数据库可能抛异常此时按原样透传runas保证功能不因兜底失败而中断行为保持当 brew 二进制所有者确实与当前用户不同时runas依然被传递su -l包装照常生效——修复只消除对自己执行 su这一无意义且有害的场景不改变正常提权路径。同时函数整体保留了原有的回退语义优先使用HOMEBREW_PREFIX环境变量salt/modules/mac_brew_pkg.py无法执行brew --prefix时捕获CommandExecutionError并返回None。回归测试两条测试锁定修复行为仓库中的单元测试文件 tests/pytests/unit/modules/test_mac_brew_pkg.py 针对该修复补充了两条成对的回归测试测试一brew 所有者等于当前用户时不得传递runastest_homebrew_prefix_no_su_when_brew_owner_is_current_usertests/pytests/unit/modules/test_mac_brew_pkg.py该测试注释明确把场景描述为 #69027 回归测试修复前homebrew_prefix()无条件把runasbrew 二进制所有者传给cmdmod.run而 macOS 上即使目标用户就是当前用户也会包装成su -l导致每次 salt-ssh 非 root 调用用户自持 Homebrew都会触发密码提示或su: Sorry。测试断言_, kwargs run_mock.call_args assert kwargs.get(runas) is None, ( homebrew_prefix() must not pass runascurrent user to cmdmod.run; on macOS this wraps the probe in su -l and triggers a password prompt (issue #69027) )测试二brew 所有者是其他用户时仍须传递runastest_homebrew_prefix_still_uses_runas_when_brew_owned_by_other_usertests/pytests/unit/modules/test_mac_brew_pkg.py作为互补用例当file.get_user返回brewowner而getpass.getuser返回someoneelse时runas必须保持为brewowner确保正常的按所有者提权路径不被破坏_, kwargs run_mock.call_args assert kwargs.get(runas) brewowner两条测试一正一反共同界定了修复的精确边界只在所有者就是当前用户时跳过提权包装其余场景行为不变。修复带来的实际影响消除高频交互提示homebrew_prefix()的每次调用不再因自我su而触发密码提示或su: Sorry错误非 root 用户自持 Homebrew 的 salt-ssh 场景可以稳定执行减少无意义系统调用避免了为探测前缀而启动一次多余的子进程su -l包装缩短了pkg系列命令的响应链路不影响既有权限模型所有者在其他用户时依旧以su -l提权管理员模式的 Homebrew 管理行为与修复前一致。运维建议对于 macOS minion / salt-ssh 用户模块头部文档还给出了规避探测开销的推荐做法为 salt-minion 设置HOMEBREW_PREFIX环境变量Intel 为/usr/localApple Silicon 为/opt/homebrew这样homebrew_prefix()会直接命中环境变量分支跳过brew --prefix子进程调用见 salt/modules/mac_brew_pkg.py。该建议在修复前后都成立可进一步降低每次pkg调用时的探测成本。赞分享运维配置管理后端【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址https://gitcode.com/gh_mirrors/sa/salt点击查看免费下载相关推荐Salt salt-ssh 修复relenv Minion 配置不再嵌入 __master_opts__根治 Argument list too longSalt salt ssh 修复relenv Minion 配置不再嵌入 __master_opts__ 根治 Argument list too long运维配置管理后端Area51模型动画事件触发条件代码示例Area51模型动画事件触发条件代码示例 在游戏开发中模型动画事件Animation Event是连接动画序列与游戏逻辑的关键桥梁。Area51项目通过Salt manage 状态检测修复深度解析manage.status/manage.up/manage.down 不再误报无响应 minionSalt manage 状态检测修复深度解析 manage.status / manage.up / manage.down 不再误报无响应 minion 导运维配置管理后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表