PowerShell – Working with CIM – Remoting

Originally posted on 2018-08-08 on the old blog

Running your commands on a local machine is all well and good, but most admins work with remote servers.

So lets talk about using CIM over network and using CIM sessions!

CIM sessions

Using CIM remotely involves working with the concept of CIM sessions. CIM sessions is similar to PowerShell sessions in that they are based on WsMan for connection, with the difference being that a CIM session is limited to CIM commands only. For reference WMI works with the legacy system DCOM instead.

Some of the advantages compared to WMI is that you can re-use sessions, and you will only need to open the firewall ports required for WsMan (which reduces attack surface which is good in these security conscious days). It also has the advantage of being able to execute in parallel which can speed things up significantly at scale.

Using CIM Sessions

CIM sessions can be made in two ways: You can create a temporary one by specifying -ComputerName in Get-CimInstance (This is quick and easy):

Get-CimInstance -ComputerName "COMPUTER1" -Namespace <namespace> -ClassName <class>

Or you can create a session that is open until you close it, by using  New-CimSession to create, and Remove-CimSession to close:

#Create a session named "Session1"
New-CimSession -Name Session1 -ComputerName "COMPUTER1" 

#Remove Cim "session1"
Remove-CimSession -CimSession Session1

There are advantages and disadvantages to both.

Usually if you only need to run one command against your targets then -ComputerName would the the best choice, it starts and stops the sessions automatically and is straight forward and easy to use. But it can be slow when you want to run many commands against the same target.

The CIM session cmdlets show their power when you need to run multiple commands against your remote targets, since you only create the session once this can significantly speed up your script. Depending on the script this can actually shave off seconds off processing for each remote target. It does require you to pay a bit more attention though on your script. Sessions should close when you close the shell, but if your script exits out into a shell it is possible the connections are kept open.

That's basically it for how CIM sessions works in practice, but lets show a real example of how this can be used.

#Array of hostnames
$computerlist = ,
"Computer1",
"Computer2"

#Create empty array for use with successful connections
$availableComputers = @()

#Foreach loop that runs connection test against hostnames in $computerlist
#Then it adds the successful connections to the $availabelComputers array
Foreach ($computer in $computerlist){
    $Test = Test-Connection $computer -Quiet -Count 1 -TimeToLive 10
    if($Test -eq "True" ){
      "Connection to $Computer"
      $availableComputers += $computer
    }
    
    else{
      "No connection to $computer"
    }
}

#Creates named sessions for all computers in $availableComputers
New-CimSession -Name RDPEnable -ComputerName $availableComputers | Out-Null

#Store the class object for all computers with the session name RDPEnable
$CIM_TerminalServiceSetting = Get-CimSession -Name RDPEnable | Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TerminalServiceSetting
$CIM_TSGeneralSetting = Get-CimSession -Name RDPEnable | Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting
 
#Invoke CIM methods against the class object variables.
$CIM_TerminalServiceSetting | Invoke-CimMethod -MethodName SetAllowTSConnections -Arguments @{AllowTSConnections=1;ModifyFirewallException=1} | Format-Table -Property PSComputerName,ReturnValue -AutoSize
$CIM_TSGeneralSetting | Invoke-CimMethod -MethodName SetUserAuthenticationRequired -Arguments @{UserAuthenticationRequired=1} | Out-Null

#Remove all sessions with the name RDPEnable
Get-CimSession -Name RDPEnable | Remove-CimSession

This builds on the previous post example regarding enabling RDP. Here you feed it a list of hostnames, then it will do a basic connection test before it creates a named session containing all the available computers. After that it uses the session to set the correct RDP flags.

That's it for the basics of working with CIM cmdlets in PowerShell. For those that has taken the time to read my posts; i hope you have learned something new that you can use be it at work, the lab or at home.

So until my next post; have a good one!