ICONN PowerShell Plugin

Having issues getting the PowerShell plugin to run correctly. Given that the orchestrators run on Linux, I was hoping to essentially nominate a Windows Server (Automation Server) to be the place where scripts are ran to simplify the process, but I’m having trouble getting this setup.

For example, I want the orchestrator to run a basic script on the Automation server, which connects to a device through WinRM to display a notification:

Invoke-Command -ComputerName -ScriptBlock {msg * "This device has been quarantined by the Security Operations Centre. Please contact the Service Desk."}

The error I receive is:

Running a NTLM connection
[] Connecting to remote server failed with the following error message : A specified logon session does not exist. It may already have been terminated. For more information, see the about_Remote_Troubleshooting Help topic.

Not sure if I’m just fundamentally misunderstanding WinRM, or if there is an issue with the way I want to run this.

TL;DR

You are not misunderstanding WinRM. This is the Windows double-hop problem, and the error you are seeing is its exact signature. NTLM cannot delegate credentials to a second machine, so the Invoke-Command running on your Automation Server has nothing to authenticate to the target with. Two fixes below. Start with Option 1, since it needs no changes on the Windows side.

What is actually happening

The orchestrator authenticates to your Automation Server over NTLM. You can see this in your own log output:

Running a NTLM connection

NTLM does not support credential delegation. The session created on the Automation Server holds a network logon token with no usable credentials attached to it. When your script then calls Invoke-Command -ComputerName <target>, that second hop has no credentials to present, and Windows returns:

Connecting to remote server failed with the following error message :
A specified logon session does not exist. It may already have been terminated.

That maps to error code 0x8009030e (SEC_E_NO_CREDENTIALS), which literally means no credentials are available in the current session. Microsoft covers the behaviour and its supported workarounds in Multi-Hop Support in WinRM.

Option 1: pass credentials explicitly on the second hop (recommended)

This is the fastest path and requires no configuration changes on Windows.

The PowerShell plugin connection has two fields, Script Username and Password and Script Secret Key. Values placed there are injected into your script as PowerShell variables ($username, $password, $secret_key) before it runs.

  1. Populate Script Username and Password with an account that has admin rights on the target endpoints.
  2. Build a credential object in your script and pass it to Invoke-Command:
$cred = New-Object System.Management.Automation.PSCredential($username, $password)

Invoke-Command -ComputerName TARGET -Credential $cred -ScriptBlock {
    msg * "This device has been quarantined by the Security Operations Centre. Please contact the Service Desk."
}

Because the credentials are supplied explicitly, the Automation Server performs a fresh authentication to the target and no delegation is involved.

Two caveats:

  • $password is already provided to you as a SecureString. Do not run ConvertTo-SecureString on it again.
  • Avoid apostrophes and quotes in that password. The plugin builds the variable assignment using single-quoted interpolation, so those characters break parsing and you will get a ParserError.

Option 2: switch the connection to CredSSP

CredSSP exists for exactly this scenario. It delegates your real credentials to the Automation Server, so onward hops authenticate normally and your original script works unmodified.

In the plugin connection:

  • Set Auth Type to CredSSP
  • Set Port to 5986

The port matters. The plugin's CredSSP code path only builds an https:// endpoint, unlike the NTLM and Kerberos paths, which fall back to http on 5985. Setting port 5985 with CredSSP will fail regardless of how Windows is configured. A self-signed certificate is fine, since the plugin passes server_cert_validation="ignore".

Then, on the Automation Server only:

Enable-WSManCredSSP -Role Server

You do not need the -Role Client or -DelegateComputer half of that command. The CredSSP client in this setup is the Linux orchestrator rather than a Windows machine, so the AllowFreshCredentials policy does not apply.

Security note: CredSSP sends credentials to the Automation Server in a delegatable form. That is worth weighing against how well that server is hardened before choosing this route.

A note on Kerberos

Switching Auth Type to Kerberos will not solve the double hop with the current plugin. The underlying pywinrm library exposes a kerberos_delegation flag, off by default, that controls whether the TGT is forwarded to the target. The plugin does not set it. Constrained or unconstrained delegation configured in AD will not help until that flag is exposed.

Test the notification separately

Worth isolating: msg * runs non-interactively when invoked over WinRM, and it relies on Terminal Services session enumeration to find logged-in users. Confirm the notification actually displays by running the msg command locally on a target machine as SYSTEM. If nothing appears on screen, you will know whether you are chasing the remoting problem or the notification itself.

Consider skipping the jump box

If network segmentation is not what is driving the Automation Server design, the simplest architecture is to remove the second hop entirely. The Address field is set per action, so you can point the plugin directly at the endpoint you want to notify.

Hi Eric, thanks for your detailed response. I tested out Option 1 as you suggested and can now see the notification generating successfully.

It should also be worth noting that I’ve also taken into account your last suggestion of skipping the jump box in this scenario. I think I had it in my head that this was the ideal scenario and couldn’t see the simpler solution of just populating the IP itself in the automation step using the information in the trigger. Definitely the ideal solution going forward, but the information about passing the credentials in future invocations is going to be very helpful in the future!