unit 8 · Windows track

become, runas & Windows paths

Elevation without sudo, backslashes without tears

essential · 6 min · windows

you may want to read 13 · YAML pitfalls & the quoting rule , 30 · Windows connections: WinRM, PSRP, SSH first — but nothing is locked

tl;dr

  • On Windows, become means become_method: runas — a fresh logon as become_user, not a sudo wrapper.
  • become also bypasses WinRM restrictions (WUA, DPAPI, non-interactive limits) — key for lesson 35.
  • Double-quoted "C:\temp" turns \t into a tab. Single-quote Windows paths and backslashes stay literal.

why it matters Half the mystery Windows failures — access denied, updates refusing to install, paths with tabs in them — trace back to runas and quoting, not to the module you blamed.

On Linux, become: true quietly means sudo. Windows has no sudo, but become still works. The method underneath changes to runas , and it behaves less like a sudo prefix than like something you already know: a brand-new logon session, created for the task, carrying become_user’s token.

- name: Show who the task really runs as
  ansible.windows.win_shell: whoami /all # user, groups, privileges
  become: true
  become_method: runas # the Windows become method
  become_user: svc_deploy # fresh logon as this account
  vars:
    ansible_become_password: '{{ vault_deploy_password }}' # lesson 27
become on Windows: runas + a user + a (vaulted) password

Two mechanics. First, unlike sudo, runas generally wants the target account’s password — supplied as ansible_become_password, vaulted, never plaintext. Built-in service accounts (SYSTEM and friends) need none. Second, creating that logon requires SeDebugPrivilege on the connecting account. Administrators have it by default, so it only bites when Ansible gets a deliberately stripped-down account — then runas fails before your task starts.

UAC gets a vote too. Runas asks for the full elevated token. If the account can’t elevate, it falls back to the limited token — the task still runs, minus the admin half of its group memberships. Same split-token dance as “Run as administrator”, performed non-interactively.

The side effect that matters more than elevation

A WinRM session is a network, non-interactive logon. Several Windows components flatly refuse to work in one: the Windows Update Agent, DPAPI (anything that decrypts stored secrets), installers demanding an interactive session. Your module is fine; the logon type is the problem.

become fixes this, because a runas logon isn’t a network logon. The official docs are explicit: become can bypass all WinRM restrictions — WUA, DPAPI, the non-interactive limits. On Windows, become has two jobs: changing who runs the task, and changing what kind of logon runs it. The second job is useful even when become_user is the same account you connected as.

Plant this deep — it returns next lesson. When a task reaches from the target to a second machine (a file share, a domain controller), the network logon fails in a uniquely maddening way. become is one of the official fixes.

Backslashes: lesson 13, Windows edition

Lesson 13’s quoting rule gets a Windows extension. In YAML double quotes, escape sequences are live — \t is a tab, \n is a newline — and Windows paths are made of exactly those sequences:

- name: Create the release folder
  ansible.windows.win_file:
    path: "C:\temp\new_build" # \t → TAB, \n → newline
    state: directory
BROKEN — double quotes process the escapes
    path: 'C:\temp\new_build' # nothing is an escape here
    # or double every backslash: "C:\\temp\\new_build"
FIXED — single quotes keep backslashes literal

The house rule: single-quote every Windows path and this bug class disappears. Double-escaping works but is easier to get half-right. Many Windows modules tolerate forward slashes, but mixing slash styles invites subtle comparison bugs. Pick backslashes-in-single-quotes and stay consistent.

Next lesson takes the bypass property to its most famous destination: a domain playbook touches a file share and Windows answers “Access is denied” — with perfectly good credentials.

at work, this sounds like

“Wrap it in become — that gets around the WinRM restrictions.”
Run the task under a runas logon so WUA, DPAPI and other non-interactive blocks stop failing it.
“Does the service account have SeDebugPrivilege?”
The account Ansible connects as needs that privilege for runas — members of Administrators carry it by default.

self-check — recall, not a test

  1. 1 A Windows Update task fails over WinRM, but the same install works fine when you RDP in. What is the Ansible-side fix?

  2. 2 Why is path: "C:\temp\new_build" broken, and what are the two fixes?

  3. 3 What does runas do about UAC — which token does it ask for?

lab (optional — never required)

Run win_shell whoami /all against your Windows target twice — with and without become — and compare the logon, group memberships and privilege list.

needs: A Windows VM reachable over WinRM — the target you set up in lesson 32.

next up 35 · The double-hop problem 7 min · unit 8