PowerShell Remoting was a huge time-saver when it was introduced with PowerShell v2. Although PowerShell Core has introduced support for SSH, it’s still possible to connect to Linux hosts over WinRM from Windows hosts using Python. In this blog post, you’re going to learn how to connect to Windows hosts over WinRM using Python on Linux.
If you would like to learn how to set up OpenSSH on Windows be sure to check out this blog post.
You have two options when connecting from Linux to Windows over WinRM:
- HTTPS (certificate-based)
- HTTP (unencrypted, basic authentication)
If you’re setting up a lab environment or perhaps doing some basic testing, connecting over HTTP is fine but if setting up Linux -> Windows connections, you should opt for certificate-based communication. In this post, you will learn how to set up connectivity using basic authentication (HTTP).
If you’d like to learn how to set up WinRM using certificates, check out this blog article which contains some information about that. Be forewarned though, the process is painful!
Setting up a Linux host to connect to Windows over WinRM using Python with basic authentication requires six steps.
- Enabling PowerShell Remoting on the Windows host.
- Allowing unencrypted (HTTP) communication on the Windows host.
- Allowing basic authentication on the Windows host.
- Installing the pywinrm Python package.
- Importing the winrm package in Python.
- Creating a WinRM session with the winrm package.
Enabling PowerShell Remoting on Windows
PowerShell Remoting is enabled on most modern Windows operating systems already. If not, simply running Enable-PSRemoting -Force
on the host is all that’s required.
Running Enable-PSRemoting -Force
on the Windows host will ensure the WinRM service is started, the appropriate firewall rules are set up, a WinRM listener is setup and a more. For a full breakdown, check out the Enable-PSRemoting
help page.
Allowing Unencrypted Traffic
The next step is to allow HTTP traffic. This is done by configuring the WinRM listener on the Windows hosts using the command below:
> winrm set winrm/config/service '@{AllowUnencrypted="true"}'
Allowing Basic Authentication
Since you’re configuring WinRM to authenticate against local Windows users and not Kerberos (Active Directory) or other more advanced techniques like certificates, you need to allow basic authentication.
By default, the WinRM listener does not allow basic authentication. To allow basic authentication, you can again use the winrm set
command as shown below.
> winrm set winrm/config/service/auth '@{Basic="true"}'
Installing the pywinrm (Python WinRM) Package
Once the Windows setup is complete, it’s time to turn to the Linux client. Since, by itself, Linux cannot directly speak to a Windows node over WinRM. It will need some help. Luckily, the majority of Linux distributions come with Python installed.
There’s a package called pywinrm you can install that takes care of the work to make the initial connection.
To download and install the pywinrm package, you can use the pip package manager. If you don’t already have this package manager installed, you can do so via running sudo easy_install pip
or using your preferred way.
pip can then be used to download the pywinrm package.
> sudo pip install pywinrm
Importing the pywinrm Library
Once installed, it’s now time to connect to the Windows host. To test this out, we’ll first bring up python in interactive mode.
> python
Once in interactive mode, then import the winrm library. If no errors are seen here, this will confirm that the library was imported
successfully.
> import winrm
Creating a PowerShell Remoting Session
Next, a WinRM session will need to be established to the Windows node. To do that, use the Session()
method and provide:
- the name or IP of the Windows host
- the name of the local Windows user to authenticate with
- the user password
I’ll be using the local administrator password here. If you’d like to use another user account, be sure they are in the Remote Management Users group.
> session = winrm.Session('<IPorHost>', auth=('administrator','<password here>'))
If no errors are thrown yet, this means that a session has been established. At this point, a command can be run on the remote Windows node to test things out.
Testing Things Out
One way to run PowerShell commands over WinRM on the Windows host from Linux is using the run_ps()
method. This is a method on the session object that allows you to run any command you’d like inside of a PowerShell session on the remote Windows host.
When the run_ps()
method is executed, it will execute the command on the remote Windows computer and return the output (if any) to stdout on the Linux client.
Below you can see the Python syntax to use to capture the output from a command and print it to the console. I’m simply running the command hostname
on the Windows host to return the hostname.
> result = session.run_ps("hostname")
> print(result.std_out)
Summary
You should now have all the required skills necessary to remotely invoke PowerShell commands from Linux clients to a Windows host. Depending on the Linux distribution, this process may vary slightly, but since we’ve used Python , the differences should be minimal.