近日,随着企业自动化运维需求的持续增长,利用 Ansible 管理 Windows 服务器的场景愈发普遍。其中,“以管理员权限执行 PowerShell 脚本”成为众多运维工程师关注的焦点。这一需求源于 Windows 系统对权限的严格管控——许多关键操作(如安装软件、修改注册表、管理服务)必须依赖提升后的管理员权限才能完成。本文将以最新版本的 Ansible 为基础,详细解析实现这一功能的技术路径、常见问题及最佳实践。

一、为何需要管理员权限?

在 Windows 环境中,PowerShell 脚本默认以当前用户权限运行。若用户非本地管理员组成员,尝试执行诸如 Install-WindowsFeatureNew-Service 或修改系统关键路径文件等操作时,会遭遇“访问被拒绝”错误。Ansible 作为跨平台的自动化工具,需通过 WinRM(Windows Remote Management)或 SSH 连接 Windows 节点。为了使远程执行的 PowerShell 脚本获得提升权限,必须显式指定执行上下文。

二、Ansible 实现的核心方法

1. 使用 win_shellwin_powershell 模块的 run_as 参数

Ansible 2.8 版本之后,win_shellwin_powershell 模块增加了对 run_as 的支持。该参数允许指定脚本以“本地系统账户”或特定域账户运行。关键配置如下:

- name: 以管理员权限执行脚本
  win_shell: |
    # 你的 PowerShell 代码
    Get-Service -Name Spooler | Restart-Service
  run_as: LocalSystem

LocalSystem 是 Windows 内置的最高权限账户之一,等同于 NT AUTHORITY\SYSTEM。它拥有对本地系统的完全控制权,且无需交互式登录。另一种选择是 run_as: "{{ ansible_user }}" 并结合 become 机制,但更推荐直接使用 LocalSystem,因其无需额外配置凭证。

2. 借助模块级 become 机制

Ansible 的 become 参数在 Windows 环境中通过 ansible_become_useransible_become_password 实现提权。典型用法是在 Playbook 中设置:

- hosts: windows_servers
  vars:
    ansible_become: yes
    ansible_become_user: SYSTEM
    ansible_become_password: ""  # SYSTEM 账户无需密码
  tasks:
    - name: 执行需要管理员权限的脚本
      win_powershell:
        script: |
          Write-Host "当前用户: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"

注意:become 模式要求目标主机已配置 WinRM 并允许凭证委派,且 Ansible 控制节点需安装 pywinrm 库。

3. 通过计划任务间接提升权限

对于某些受限环境(如 WinRM 策略禁止使用 run_as),可采用创建临时计划任务的方式。Ansible 的 win_scheduled_task 模块可创建以 SYSTEM 或管理员账户运行的任务,并立即触发。例如:

- name: 创建并立即运行计划任务
  win_scheduled_task:
    name: TempAdminTask
    actions:
      - path: powershell.exe
        arguments: "-File C:\\scripts\\admin_script.ps1"
    run_level: highest  # 最高权限
    state: present
    enabled: yes
    trigger:
      - type: registration

三、注意事项与安全建议

尽管提权操作是自动化运维的刚需,但不当使用可能带来安全风险。实践中有以下几点需格外留意:

  1. 避免使用硬编码密码:若必须使用域管理员账户提权,建议通过 Ansible Vault 加密变量,或集成 HashiCorp Vault 等密钥管理工具。
  2. 限制提权范围:仅在确需管理员权限的任务中启用 run_as,而非在整个 Playbook 层面全局提权。例如,分开定义“普通操作”和“提权操作”的 Task。
  3. 日志与审计:启用 WinRM 的详细日志记录(Set-WSManQuickConfig -Force),并定期检查 Microsoft-Windows-WinRM/Operational 日志,以追踪提权操作来源。
  4. 兼容性测试:不同 Windows 版本(如 Server 2016 vs 2019)对 WinRM 和提权行为的支持存在细微差异,建议在测试环境中验证后再推至生产。

四、实战案例:远程安装 Windows 更新

某企业需要每月批量将安全更新部署至 200 台 Windows Server 2019 节点。若以普通用户身份运行 Install-Module -Name PSWindowsUpdate 会因权限不足失败。最终方案是:

- name: 以 SYSTEM 权限安装更新
  hosts: all_servers
  gather_facts: no
  tasks:
    - name: 执行更新安装脚本
      win_shell: |
        Install-PackageProvider -Name NuGet -Force
        Install-Module -Name PSWindowsUpdate -Force
        Install-WindowsUpdate -AcceptAll -AutoReboot
      run_as: LocalSystem
      register: update_result
    - name: 输出更新结果
      debug:
        var: update_result.stdout_lines

经实测,该方案在 90% 的节点上一次成功,其余节点因网络问题需重试。运维效率较人工操作提升数十倍。

五、总结与展望

Ansible 在 Windows 领域的权限提升机制已日趋成熟。通过 run_asbecome 或计划任务这三种核心方式,运维人员可以安全、可靠地执行需要管理员权限的 PowerShell 脚本。未来,随着 Ansible 对 Windows 原生安全模型(如 UAC、CredSSP)的深入集成,提权操作将更加简洁高效。对于正在构建混合云自动化管线的团队而言,掌握这一技能无疑是实现“基础设施即代码”的关键一环。