unit 8 · Windows track

The double-hop problem

Why the share says no when RDP says yes

essential · 7 min · windows

you may want to read 31 · The WinRM auth matrix , 34 · become, runas & Windows paths first — but nothing is locked

tl;dr

  • WinRM hands the target a network logon: proof of who you are, but no credentials to pass onward.
  • Any task reaching a second server — share, AD, SQL — dies with Access is denied: the double hop.
  • Three fixes: Kerberos delegation, CredSSP, or become with explicit credentials.

why it matters Access is denied on a share you fully control, while the same action works over RDP — until you can name the double hop and two fixes, this costs hours.

Here is the failure this unit has been building toward. Your playbook targets a domain-joined server, Kerberos auth per lesson 31, every task clean — until one needs to reach past the target:

- name: Pull the installer from the share
  ansible.windows.win_copy:
    src: '\\fileserver\installers\sql-server.iso'
    remote_src: true # the copy runs ON the target
    dest: 'C:\Temp\sql-server.iso'
hop two: the target itself must reach a second server

Access is denied. Your service account has full control on that share. You RDP into the target as that account, paste the same UNC path into Explorer: opens instantly. The playbook still fails. This is not a permissions problem; no ACL archaeology will fix it. You’ve hit the double hop problem.

The mechanism: logon types. RDP performs an interactive logon — Windows caches your credentials on that machine, so anything you launch there can authenticate onward as you. WinRM performs a network logon: the target receives proof of your identity, enough to authorise you locally, but never the credentials themselves. Hop one is fine. At hop two the target must authenticate to fileserver as you — and it has nothing to present:

control node ──credentials──▶ target ──nothing to present──▶ \\fileserver
              hop 1: authorised        hop 2: Access is denied
the credential dies at hop two

The error is honest — it just isn’t about your account. It denies whoever the target was at hop two: nobody. The same wall blocks every second-system task: UNC paths, AD queries, SQL installs that touch a share.

Lesson 31’s matrix told you to notice which rows say Yes under Delegation: Kerberos and CredSSP. That column is your map. Three fixes.

Fix 1: Kerberos delegation

Already on the kerberos transport in a domain? Then the fix is one variable — this is Kerberos delegation :

ansible_winrm_transport: kerberos
ansible_winrm_kerberos_delegation: true # delegate your ticket onward
group_vars/windows.yml — next to lesson 31's transport settings

The target can now request onward tickets in your name, and hop two authenticates as you. AD gets a vote — delegation must be permitted for the machines involved, a knob you know from AD administration. This is the default fix for a domain estate.

Fix 2: CredSSP

The CredSSP row earns its Yes differently: it hands your actual credentials to the target, which can then go anywhere you can. Lesson 31’s warning applies at full strength — unconstrained delegation, so a compromised target owns your account. Reach for it when Kerberos delegation isn’t available (local accounts, AD forbids it) and security has signed off.

Fix 3: become with explicit credentials

Lesson 34 planted this: become on Windows does more than elevate — the docs describe using it to bypass WinRM’s restrictions. The non-delegating network logon is exactly such a restriction:

- name: Pull the installer from the share
  ansible.windows.win_copy:
    src: '\\fileserver\installers\sql-server.iso'
    remote_src: true
    dest: 'C:\Temp\sql-server.iso'
  become: true
  become_method: runas
  become_user: '{{ ansible_user }}' # explicit creds — a real logon
same task — become swaps the logon type under it

With become_user and ansible_become_password set (vault it — lesson 27), Windows performs a fresh interactive logon for the task. Real credentials now exist on the target, hop two works, and DPAPI unlocks as a bonus. The most surgical fix: per-task, no AD or transport changes — at the cost of shipping a password to the host. If your estate went SSH instead (lesson 30), the answers keep their shape: an explicit password, or Kerberos/GSSAPI with delegation.

Say it back in one breath: a network logon doesn’t delegate credentials, so any hop from the target to a second server fails — fix it with Kerberos delegation, CredSSP, or become with explicit credentials. That sentence is the summit of the Windows track — the bar this unit exists to clear. Next up, the workplace track: how real Ansible repos are laid out.

practice — fix the double hop (1/3)

Domain environment, security team vetoes CredSSP (unconstrained delegation). The playbook copies an installer from a file share. Best fix?

practice, not progress — answers come from the matrix above

at work, this sounds like

“Works when I RDP in, dies in the playbook.”
The double-hop signature: RDP is an interactive logon that caches credentials; WinRM is a network logon that cannot pass them onward.

self-check — recall, not a test

  1. 1 A domain playbook touching \\fileserver\installers fails with Access is denied though your account has full rights. Why, and name two fixes.

  2. 2 In lesson 31's auth matrix, which two rows say Yes under Delegation, and what does each cost?

  3. 3 How does become fix the double hop without touching AD or the auth transport?

lab (optional — never required)

Reproduce it: win_copy with a UNC src against a domain target, then fix it with become, and again with the Kerberos delegation flag.

needs: Two domain-joined Windows VMs plus a DC — heavyweight. With only lesson 32's single VM, skip it; the mental model stands alone.

next up 36 · Repo structure & conventions 7 min · unit 9