tools.winrm_tools module

WinRM and PowerShell remoting (WS-Man) tools for remote Windows management.

Uses pywinrm (HTTP/HTTPS to ports 5985/5986). Per-user named sessions, same ergonomics as ssh_* tools. Requires UNSANDBOXED_EXEC.

async tools.winrm_tools.check_unsandboxed_exec(ctx)[source]

Gate a WinRM operation behind the UNSANDBOXED_EXEC privilege.

Verifies that the calling user is allowed to run arbitrary remote commands. Every WinRM tool handler calls this first and returns its result verbatim when it is non-None, short-circuiting the operation.

Interactions: imports and calls tools.alter_privileges.has_privilege() with PRIVILEGES["UNSANDBOXED_EXEC"], reading ctx.redis, ctx.config and ctx.user_id off the tool context (the privilege check itself consults the Redis-backed privilege store). On denial it logs a SECURITY warning naming the user. This helper is also imported and reused by the sibling Windows tool modules tools.ad_dns_tools, tools.ad_gpo_tools and tools.agpm_tools.

Called by: every handler in this module (_winrm_connect, _winrm_run_ps, _winrm_run_cmd, _winrm_save_credentials, etc.) and by the AD/GPO/AGPM tool handlers listed above.

Parameters:

ctx (Any) – The active ToolContext (or any object exposing redis, config and user_id attributes).

Return type:

str | None

Returns:

None when the user holds the privilege (proceed). Otherwise a JSON string with success: False describing either the missing privilege or that the privilege system is unavailable.

tools.winrm_tools.resolve_owned_winrm_session(connection_name, user_id)[source]

Look up a WinRM session and enforce that the caller owns it.

Central ownership-and-existence gate shared by the run handlers: it confirms that connection_name is present in the registry and was opened by user_id before any command is allowed to run on it, returning a ready-to-send JSON error string (rather than raising) when it is not.

Interactions: reads the module-level _winrm_sessions registry, listing the user’s own connection names via _user_sessions() for a helpful error, and checks ownership with _is_owner(); no network or Redis use. Called by get_owned_winrm_session() and _winrm_run_ps() here, and reused by the sibling Windows tool modules tools.ad_gpo_tools, tools.ad_dns_tools and tools.agpm_tools.

Parameters:
  • connection_name (str) – Label of the session to resolve.

  • user_id (str) – Identifier of the requesting user, used for the ownership check.

Returns:

(session, None) when the named session exists and is owned by the caller; otherwise (None, json_error_string) whose message distinguishes an unknown name (listing the user’s connections, or noting there are none) from a connection owned by someone else.

Return type:

tuple[Any, str | None]

tools.winrm_tools.get_owned_winrm_session(connection_name, user_id)[source]

Return the owned pywinrm session, discarding the error string.

Thin convenience wrapper over resolve_owned_winrm_session() for callers that only want the session object and treat any failure (unknown name or wrong owner) uniformly as None.

Interactions: delegates entirely to resolve_owned_winrm_session() (and thus to the _winrm_sessions registry, _user_sessions() and _is_owner()); no other side effects. No callers were found in the repo, so this is a public convenience entry point retained for sibling tool modules and tests.

Parameters:
  • connection_name (str) – Label of the session to resolve.

  • user_id (str) – Identifier of the requesting user, used for the ownership check.

Returns:

The live pywinrm Session when it exists and is owned by the caller, otherwise None.

Return type:

Any | None

async tools.winrm_tools.execute_winrm_ps(session, script, timeout)[source]

Run a PowerShell script on a connected WinRM session without blocking.

Async wrapper around pywinrm’s blocking run_ps: it derives the WS-Man read/operation timeouts from timeout, off-loads the synchronous remote call to a worker thread, and normalises the result (or any failure) into a plain dict so handlers never have to catch exceptions themselves.

Interactions: invokes the remote Windows host’s PowerShell over HTTP/HTTPS by running the nested _run closure through asyncio.to_thread under an asyncio.wait_for guard; decodes the returned std_out/std_err bytes with _decode_out(); logs an exception via the module logger on error. Called by _winrm_run_ps() here and by the AD/GPO/AGPM tool handlers in tools.ad_gpo_tools, tools.ad_dns_tools and tools.agpm_tools.

Parameters:
  • session (Any) – A connected pywinrm Session (typically from resolve_owned_winrm_session()).

  • script (str) – The PowerShell script text to execute remotely.

  • timeout (int) – Maximum execution time in seconds; the WS-Man and outer wait_for timeouts are derived from it with margins.

Returns:

{"success": True, "stdout": ..., "stderr": ..., "status_code": ...} on success, or {"success": False, "error": ...} on a timeout or any pywinrm exception.

Return type:

dict[str, Any]