Windows Lock Workstation

Hi,

I am trying lock the workstation during a play while installing Windows Updates and doing some maintenance activities for an application.
This is a highly sensitive and regulated environment.
At the moment we are looking at two use cases, one where the process is manually initiated by the user.
I have done this through a handler (still new to Ansible).

Once this step happens I would require the workstation to be locked to avoid any potential user interference.
In the past I have done other projects with the help of MDT (HideShell, DisableTaskMgr) Task Sequences but this project requires much more, hence we are evaluating Ansible.

I have tried the following variations (after I found some guidance here https://groups.google.com/forum/#!searchin/ansible-project/cmd.exe|sort:date/ansible-project/7inLJoctNLk/WzrrqX5TAwAJ)

  • name: Lock Desktop
    win_command: ‘cmd.exe “start (Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).Win32Shutdown(0)”’
    become: yes
    become_method: runas
    become_user: SYSTEM

  • name: Lock Desktop
    win_command: RunDll32.exe user32.dll,LockWorkStation
    vars:
    ansible_become: yes
    ansible_become_method: runas
    ansible_become_user: Host\Administrator
    ansible_become_pass: Password
    ansible_become_flags: logon_type=new_credentials logon_flags=netcredentials_only

I have also tried to start the rundll method through a script (PowerShell and Batch) but I simply cannot get the function to work.
The playbook runs through with changed=1 but the workstation remains unlocked.

I am sure I am overlooking something (I apologize upfront for stupid mistakes as Ansible is really new for me).

Thanks
Lukas

You are delving deep into Windows stations and desktops [1] and the solution won’t be too pretty. When using WinRM, the service that spawns the initial process is located in session 0 which means our Ansible process is also in session 0. The docs for LockWorkStation [2] indicates that it will only work when you call it from the interactive desktop of the session you want to lock. In Windows station/desktop speak this would be on the station ‘WinSta0’ and the ‘Default’ desktop for the user’s session.

To see what session, station, and desktop a process is associated with, you can run the ‘Get-ProcessSessionStationAndDesktop’ function at [3]. Here is the result in various permutations in Ansible;

  • Plain WinRM

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b66125$

  • Desktop: Default

  • Become with password

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b68e5a$

  • Desktop: Default

  • Become without password and impersonation (2.8+)

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b6d2ae$

  • Desktop: Default

  • PsExec

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b717bc$

  • Desktop: Default

  • PsExec with credentials

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b74e19$

  • Desktop: Default

  • PsExec interactive

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b78771$

  • Desktop: Default

  • PsExec interactive with credentials

  • Can Lock: No

  • Session: 0

  • Station: Service-0x0-b7bc74$

  • Desktop: Default

  • PsExec explicit interactive session

  • Can Lock: No

  • Session: 2

  • Station: WinSta0

  • Desktop: Default

  • PsExec explicit interactive session with credentials

  • Can Lock: Yes

  • Session: 2

  • Station: WinSta0

  • Desktop: Default

Only PsExec with an explicit interactive session id that matches the session we want to lock is the only scenario that worked. I’ve found that the credentials you use doesn’t have to be the user who created the session, just one that can spawn the process in that session. By process of elimination it seems like you need to meet the following criteria to be able to lock a session;

  1. The station and desktop must be set to ‘WinSta0\Default’. This is not something you can do currently with become but it’s quite trivial to add the code
  2. Start the process in the session that needs to be locked. This is not something you can do in Ansible, and from a brief attempt it isn’t trivial to add. This is why PsExec is the only solution that works
  3. The process must be spawned from an interactive logon type, this is why only PsExec with explicit credentials works
    Point 3 is already possible as that is what become currently does, point 1 is easy to implement but when playing around with this point 2 seems to be a lot more complex. PsExec shows that this is possible to do and possibly something that would be added to become sometime in the future but currently it’s not something you can do in become right now.

While it is possible to do this it’s not something you should rely on because;

  • Once you’ve locked a user’s session there is nothing to stop them from just unlocking it
  • You need to enumerate the actual system sessions, this isn’t hard but it’s not something that’s built into Ansiblw

[1] https://docs.microsoft.com/en-us/windows/desktop/winstation/about-window-stations-and-desktops
[2] https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-lockworkstation
[3] https://gist.github.com/jborean93/d4359898b1c378c8828aa2b817c0ad68

Thanks

Jordan

Hi Jordan,

Much appreciated, Thank you!
I will think about it and also bring it up in the next Stakeholder Meeting to gather feedback.

May I ask if you would know of any other way (if you would have such a use case where you need to prevent user input at all during the patching process)?

Thank you
Lukas

Hi Lukas

There are registry keys which prevent keyboard and mouse input