Remote Windows Management from Linux using Dockers

Since PowerShell Core 6, PowerShell became cross-platform, free and open source. There is, of course, some limitations when it comes to PowerShell for non-Windows platforms. Microsoft documentation explains that:

“PowerShell on Linux and macOS uses .NET Core, which is a subset of the full .NET Framework on Microsoft Windows. As a result, scripts that run on Windows may not run on non-Windows platforms because of the differences in the frameworks.”

With this in mind, I wanted to see if it was possible to manage Windows from Linux using WinRM (keep in mind that New-PSSession offers support for connections to a Windows remote host over SSH). In Windows PowerShell, you can use New-PSSession and Invoke-Command to manage a Windows host remotely. First, let us provide a basic example of the usage of those cmdlets in Windows PowerShell:

$newSession = New-PSSession -ComputerName $computerName -Credential (Get-Credential)
Invoke-Command -Session $newSession -ScriptBlock {Write-Output "testing winrm"}

Since WinRM is properly configured in the remote host, this code returns “testing winrm” after it prompts for the credentials to connect to the remote machine. We can also create a PSCredential to automatically send the credentials:

$remoteUserName = 'user'
$remoteUserPass = ConvertTo-SecureString "p@ssWord!" -AsPlainText -Force
$remoteUserCred = New-Object System.Management.Automation.PSCredential ($remoteUserName, $remoteUserPass)

$newSession = New-PSSession -ComputerName 192.168.100.5 -Credential ($remoteUserCred)

Invoke-Command -Session $newSession -ScriptBlock {Write-Output "testing winrm"}

Now let us jump to Linux to see if we can do the same thing. We will use CentOS 7 with the pwsh package installed on this occasion. To start pwsh, we have to type “pwsh”:

Calling PowerShell in CentOS 7

Let us get right into it by typing the New-PSSession to see if it works:

Running New-PSSession in PowerShell for Linux

The same cmdlet that we tried for Windows PowerShell does not work here. The error seems to be: New-PSSession: MI_RESULT_ACCESS_DENIED. After trying different things, I found that none of the parameters available for New-PSSession, including New-PSSessionOption, seem to work. For instance, Basic authentication fails with New-PSSession: Basic authentication is not supported over HTTP on Unix, NTLM fails with An invalid name was supplied SPNEGO cannot find mechanisms to negotiate. The same applies for Invoke-Command. After googling for a bit, I found this post and this docker image that could be a potential solution for this problem.

A docker image with support for NTLM authentication between Linux and Windows

Following the official documentation, I installed docker in my Centos 7 server. Then, I ran the PowerShell-NTLM docker image using the following command:

docker run -it quickbreach/powershell-ntlm

After that, I was presented with this screen:

Now, let us try with New-PSSession:

This is expected as the default authentication for this cmdlet is not negotiate, which is the authentication method supported in this image. So let us change that and try again:

This works great! As we would do in Windows PowerShell, if we want to run code, we just pass the session as a parameter to Invoke-Command:

Also, the PSCredential object works too:

This can be used for a lot of things, from integrating it in CI/CD tools to just gathering info from a remote Windows hosts from Linux. In my case, I needed this to trigger a PowerShell script in a Windows remote host from a Jenkins instance running Linux based images in Dockers.

| Theme: UPortfolio