This is a fork of Microsoft OMI repository. Read more about this fork in my blog post Wacky WSMan on Linux.
The main goal of this fork is to produce an alternative build of libmi
that is used by PowerShell for WinRM based PSRemoting.
This alternative build is designed to fix the current problems with the shipped version of libmi
.
Unfortunately there is no interest in upstream to accept any patches for this use case so I've decided to store them in this fork and produce my own builds.
The following changes have been made:
gcc
versions that had stricter default setGSS_C_DELEG_POLICY_FLAG
flag to support credential delegation with KerberosGSS_C_NT_HOSTBASED_SERVICE
with the service http@<hostname>
principal which works in more situations than beforekrb5.conf
kinit
-Authentication Negotiate
or -Authentication Kerberos
but the former will only work with Kerberos with no NTLM fallback-Authentication NegotiateWithImplicitCredential
but PowerShell does not pass in the required flags to know thisMI_RESULT_FAILED
errorAuth/CbtHardeningLevel = Strict
7.2
, you still need to tell PowerShell to skip the checks but those skip options are ignored in OMIlibpsrpclient
forI am not looking at fixing any underlying problems in this library or work on the server side part of OMI. This is purely focusing on improving the experience when using WinRM as a client on non-Windows based hosts within PowerShell. There are no guarantees of support, you are free to change whatever you wish on your own builds but use the code here at your own risk.
See build for more information on how to manually build these libraries.
Since the 2.0.0
release there is now a PowerShell module that can be used to install this library on known distributions.
You can see this package at PSGallery PSWSMan.
To install the WSMan libs through this module you can run the following in PowerShell:
Install-Module -Name PSWSMan
# Requires root access to install, Install-WSMan can be run directly if already running as root
sudo pwsh -Command 'Install-WSMan'
If you wish to build your own changes you can manually build the module.
Make sure to run this step after you've manually built OMI into the build/lib
directory.
./build.py module
Once built you can import the module and install the WSMan components.
# Import PSWSMan from the repo source, that will source the libs from PSWSMan/lib/{distribution} of the repo
Import-Module -Name ./build/PSWSMan
Install-WSMan
You can also manually install the libraries by copying the files build/lib/{distribution}/lib*
into the PowerShell directory.
The location of the PowerShell directory differs based on each distribution or how it was installed.
An easy way to determine this directory is by running dirname "$( readlink "$( which pwsh )" )"
To enable Kerberos authentication you will need to ensure you install the Kerberos system packages that can vary between distros.
See the .json
files in distribution_meta to see the test_deps
that are required to test PowerShell with Kerberos auth.
NTLM auth also requires the gss-ntlmssp package which is another separate package that can be installed.
This is also documented in the .json
files for each distribution.
A few thing to note when using the WSMan transport in PowerShell
username@DOMAIN.COM
. Do not use the Netlogon form DOMAIN\username
-SessionOption (New-PSSession -SkipCACheck -SkipCNCheck)
See testing for more information on how to test the changes here.
There are a few steps you can follow to troubleshoot any problems when using this library in PowerShell. Most problems are split into 3 different categories:
The libmi
library also has a builtin logging mechanism that you can enable to help with debugging issues at runtime.
To enable logging for OMI you first need to create a file at /opt/omi/etc/omicli.conf
with the following contents:
# Can be ERROR, WARNING, INFO, DEBUG, VERBOSE (requires a debug build) with the default being WARNING
# Any previous values will also be set, i.e. setting INFO will enable ERROR and WARNING
loglevel = DEBUG
# The directory (must end with /) to place the log file in
logpath = /tmp/
# The name of the logfile to write to
logfile = omi-pwsh.log
If you have specified a custom --prefix
path when you built libmi
, then /opt/omi
should be subsituted with the prefix you specified.
You may also want to create the dir /opt/omi/var/log
as this directory is used to place the HTTP trace files.
If PowerShell fails to load the libpsrpclient
or libmi
library it can fail with the error
This parameter set requires WSMan, and no supported WSMan client library was found. WSMan is either not installed or unavailable for this system.
The main thing you can do to test this out is to very the linked libraries are present on the system. Run the following to get information on all the linked libraries
PWSHDIR="$( dirname "$( readlink "$( which pwsh )" )" )"
# On Linux
ldd "${PWSHDIR}/libpsrpclient.so"
ldd "${PWSHDIR}/libmi.so"
# On macOS
otool -L "${PWSHDIR}/libpsrpclient.dylib"
otool -L "${PWSHDIR}/libmi.dylib"
Read through this list and make sure each of the libraries it reference actually resolve to a path on the system.
There may be a chance that you never replaced the original libmi
library with one from this fork.
Authentication can be a tricky thing to debug due to the complexities of GSSAPI on Linux.
If you would like to use Kerberos authentication (you should) then the first time you should verify is that you are able to get a Kerberos ticket for your user.
You can test this by running kinit username@DOMAIN.COM
and entering your password.
If this fails then you have a system setup issue with your Kerberos config and should fix that first.
Once you have verified the system can talk to the domain controller then you can start testing using it in PowerShell.
A few things you should be aware of when it comes to Kerberos authentication:
username@DOMAIN.COM
A helpful way to troubleshoot Kerberos issues is to set the env var KRB5_TRACE=/dev/stdout
before opening PowerShell.
This will output any any GSSAPI events to the console allowing you to see the steps it follows and potentially trace down the underlying problem in your scenario.
NTLM authentication is less picky about the environment it is run in but it comes at the downside of it being less secure.
NTLM auth works out of the box on macOS but on other Linux hosts you need to ensure you have installed the gss-ntlmssp package.
Have a look through the distribution_meta .json
files to see what name this package comes under for your distribution.
These are the hardest problems to debug as it's usually a sign of a logic issue in the libmi
code.
The best advice I can give you here is to create a debug build of the library using ./build.py --debug
and make sure you have enable the VERBOSE
level logs in the omicli.conf
file.
Hopefully the logs can at least narrow down where the problem lies.
OMI does not use the HTTPS stack provided by .NET which means it links directly against OpenSSL on the system.
On Linux hosts this is usually nothing major and will automatically select the same OpenSSL installed by the system's package manager.
This is a different story on macOS as OpenSSL isn't shipped in a form that can be used by OMI.
This means macOS needs to install it's own copy of OpenSSL which is typically done with either brew
or port
:
# brew
brew install openssl
# port
port install openssl curl-ca-bundle
Note: For port the curl-ca-bundle package must also be installed so it's provided with a sane default of trusted root certificates.
Common errors that are encountered when using OpenSSL are:
Install-WSMan
openssl
package is installed using the distribution specific package manageropenssl
is installed through brew
, port`, or compile it yourselfopenssl
has been installed with the same architecture as what pwsh
is running as - archs cannot mix and match in the same processcertificate verify failed
or error:16000069:STORE routines::unregistered scheme
There are a few known issues so far that are split into the can and can't fix categories. Can fix issues are ones that are problems in this codebase that can be fixed and a new library recompiled. Can't fix issues are either issues that would take a lot of effort to implement and/or require changes in other libraries which is out of scope here.
{prefix}/var/log
if that folder exists
loglevel
in the omicli.conf
file is set to DEBUG
or higher but currently that does not happen/etc/krb5.conf
contains [libdefaults]\nforwardable = true
gss_acquire_cred_with_pass
will only acquire a forwardable ticket (required for delegation) if the krb5.conf
contains the forwardable = true
settingkinit -f username@DOMAIN.COM
to get a forwardable ticket regardless of the krb5.conf
value and use the implicit credential insteadI'm happy to look at any PRs or help with any issues but bear in mind that this is something I work on in my spare time.
There is no guarantee that I will be able to solve your problems or look at a PR.
If you are making any changes to the code in Unix/
then I recommend you add a comment # JBOREAN CHANGE: reason for change
.
This allows me to easily merge any upstream changes and compare what has been edited here and why compared to any incoming changes.
See Can Fix for known bugs that can be fixed. Otherwise other features/changes that are in the backlog are:
omicli.conf
file through an env var instead of the hardcoded location-Authentication Negotiate