SSH with Powershell

SSH with Powershell

Recently I went over how to get information from the Unifi Controller. Now I want to show you how to grab information from the unifi device itself. In this example, we are going to use SSH with Powershell to pull some basic information from an unifi AP.

SSH with Powershell

The first thing you will need is to make an ssh connection. Most computers have open ssh installed and you can type in ssh username@ipaddress and access it after inputting passwords and such. However, I want to work with powershell and not whatever shell the unifi will present me. Thus, we will run through a module called POSH-SSH by darkoperator.

Install Posh-ssh

The first thing you will need to do, if you haven’t already, is installing the module. This module lives in the standard repos, which makes life so much easier. Here is the command:

Install-Module -Name Posh-SSH

Once you have the command installed, that’s when we import with the import module command.

Making a connection

The next step is to make the connection. The feel of this command is just the same as that of enter-pssession. We call the computer name, normally an IP address, and we add the credentials. The biggest difference is we add an acceptkey flag. You can also give your session an ID number, this is good if you are doing more than one at a time. Today we are only focusing on one connection. So it’s not needed, but it becomes very useful with loops. Like always, these sessions start at 0.

New-SSHSession -ComputerName 10.0.0.8 -AcceptKey -Credential (Get-Credential)

This creates a session of 0 which we can send commands to later. Remember, each session connection adds another session number. So the next one will be 1 and so on so forth. if you need more information or become lost with which sessions you are using, get-sshsession will help resolve this question.

Invoking SSH commands with Powershell

The next thing we need to do is invoke commands. What is the point of just connecting when we have the power of ssh and powershell? The command we can use is called invoke-sshcommand. When working with any system, you need to be mindful of that system’s shell. Ssh gives you the connection, and that system determines what you can use. This took me a while to figure out. One of the commands inside the unifi devices is info. This gives you useful information. So when you are connected, typing info will telling you IP addresses, mac address, inform statuses, and more. However, with the SSHcommand, it produces nothing useful. As the image below shows.

So, what is needed to do from here is adding a flag to let it know you are coming from somewhere else. This flag is “mca-cli-op” followed by the command you want. However, as the image below suggests, it parses the output as a single object. We need to go deeper by selecting the output.

$Output = (Invoke-SSHCommand -Command "mca-cli-op info" -SessionId 0).output

This is nice to know, however… It’s a string. You will need to parse this data out accordingly. I do this by using select-string then from there working each item. When I select the string, for example, model. I take the output and select-string model. Then i convert that to a string as select string make it into an match info object. Which isn’t as helpful as you would think. Then from there, I replace any spaces and split from the : to get the information I need. Below is the code.

$Return = [PSCustomObject]@{
        model = ($output | select-string model).tostring().replace(' ','').split(":")[1]
        version = ($output | select-string version).tostring().replace(' ','').split(":")[1]
        MacAddress = ($output | select-string mac).tostring().split(' ')[-1]
        IPaddress = ($output | select-string ip).tostring().replace(' ','').split(":")[1]
        Hostname = ($output | select-string hostname).tostring().replace(' ','').split(":")[1]
        UptimeSeconds = ($output | select-string uptime).tostring().replace(' ','').split(":")[1] -replace("\D",'')
        Status = ($output | select-string status).tostring().split(':').split('(').replace(' ','')[1]
        Inform = ($output | select-string status).tostring().split(' ')[-1] -replace('[()]','')
    }

From here you can change the inform, or other items using the flag and the command accordingly. Once you are finished with your session, make sure to remove it with the Remove-SSHSession command.

The Script

Here is the script. This script allows you to do more than one IP address.

function Get-UnifiSSHDeviceInformation {
    param (
        [parameter(
            ValueFromPipeline = $True,
            ValueFromPipelineByPropertyName = $True,    
            HelpMessage = "Unifi Username and Password", 
            Mandatory = $true)][alias('IP')][ipaddress[]]$IPaddress,
        [parameter( 
            HelpMessage = "Unifi Username and Password", 
            Mandatory = $true)][alias('UserNamePassword')][System.Management.Automation.PSCredential]$Credential
    )
    $return = @()
    foreach ($IP in $IPaddress) {
        New-SSHSession -ComputerName $IP -AcceptKey -Credential $Credential
        $Output = (Invoke-SSHCommand -Command "mca-cli-op info" -SessionId 0).output
        Remove-SSHSession -SessionId 0
        $Return += [PSCustomObject]@{
            model = ($output | select-string model).tostring().replace(' ','').split(":")[1]
            version = ($output | select-string version).tostring().replace(' ','').split(":")[1]
            MacAddress = ($output | select-string mac).tostring().split(' ')[-1]
            IPaddress = ($output | select-string ip).tostring().replace(' ','').split(":")[1]
            Hostname = ($output | select-string hostname).tostring().replace(' ','').split(":")[1]
            UptimeSeconds = ($output | select-string uptime).tostring().replace(' ','').split(":")[1] -replace("\D",'')
            Status = ($output | select-string status).tostring().split(':').split('(').replace(' ','')[1]
            Inform = ($output | select-string status).tostring().split(' ')[-1] -replace('[()]','')
        }
    }
    $Return
}

Additional Reading