Skip to main content

0209 | Automation in Scale | Remoting

Running a Remote Command | Steps

  • tcp
  • start process
  • load clr
  • load powershell
  • initialize powershell
  • run the profiles (up to 4)
  • take the code
  • run the code
  • throw all it away

Running a Remote Command | Takeaway

  • not efficient to build up everything and throw everything away just to execute a tiny little code
  • at least not with icm every time

Running a Remote Command | Solution

  • ps sessions

Bad Example | Much Overhead for Nothing | Session is destroyed

# create and assign a var on a remote machinge
icm -comp dc {$var=2}
# read out the var value from remote machine
# no result -- session is destroyed on rm after tearing down, variable is lost
icm -comp dc {write-out $var}

Right Way to do it with Sessions

# save created session into a variable
$sessions = New-PSSession -computername dc
# display the open ps sessions
get-pssession
# try the same again -- assign var -- read var from rm
icm -session $sessions {$var=2}
# this time it will work and return 2
icm -session $sessions {$var}

Measure the difference in time between the two Approaches

# build up connection, execute command, tear down connection -- 886 miliseconds
measure-command {icm -computername dc {get-process}}
# use an established connection/session -- 538 miliseconds
measure-command {icm -session $sessions {get-process}}

Demonstrate the Big difference between the two Approaches

# assing variables
$servers = 's1','s2'
# verify that there are no websites ready -- foreach -- for each object coming through do...
# error for each -- since none of them exists (yet)
$servers | foreach{start iexplore http://$_}
# create the sessions
$s = new-pssession -computername $servers
# display the established sessions / or verify
$s
# install the web server on each of the rms
# important to note: NOT SERIAL --> PARALELL
icm -session $s {install-windowsfeature web-server}
# check if web-servers are running -- they are :)
$servers | foreach{start iexplore http://$_}
# create a simple webpage to display -- "MVA and PowerShell Rocks!"
notepad c:\default.htm
# deploy the webpage -- $_ --> the servers; c$ --> admininstative share on the rms
$servers | foreach{copy-item c:\default.htm -destination \\$_\c$_inetpub\wwwroot}
# check the webpages -- they are diplaying the default htm
$servers | foreach{start iexplore http://$_}

How to avoid installing everything locally

# create and establish a session to the domain controller
$s = new-pssession -computername dc
# import a module from the session -- here from the dc rm -- prefix to name it differently
# add a prefix here because it is already installed -- easier to discard
import-pssession -session $s -module activedirectory -prefix remote

Difference between get-help and get-command

  • get-command is more structural, more programatic information
# assign a var the result
$c = get-command get-process
# display all the parameters
$c.parameters
# get more info about a specific one
$c.Parameters["Name"]

How import-pssession -module works | Implicit Remoting

  • go to the remote machine
  • load the asked module
  • do a get-command on all the things
  • get the datastructure
  • transfer it
  • on the local machine
    • get the information and recreate a set of scripts with exactly the same signature
    • dinamically generated code

How import-pssession -module works | TL;DR

  • get the datastructure from rm, dynamicall generate the ps script that has exactly the same signature as the .net cmdlet on the rm, gather up all the information and run it on the local machine

How import-pssession -module works | Takeaway

  • a program that generates cmdlets dinamically, does not transfer the .net code

Demonstrate that the imported module is not installed locally | Only Scripts

# diff between the one installed locally and the one imported: 
# commandtype: installed:cmdled (.net code) vs. imported:function
get-command get-*adcomputer
# get the dinamically generated code (on lhost) for the imported module
(get-command get-remoteadcomputer).definition

Demonstrate it locally

# create a local session -- alias for new-pssession
$s = nsn
# imprort the `get-process` command and prefix it with wow
import-pssession $s -commandname get-process -prefix wow
# run the imported command -- now working -- winrm service config needed
get-wowprocess