├── LICENSE ├── Private ├── Convert-FromUnixDate.ps1 ├── Convert-ToUnixDate.ps1 ├── ConvertTo-Object.ps1 ├── ConvertTo-UnifiObject.ps1 ├── Invoke-GetRestAPICall.ps1 ├── Invoke-PostRestAPICall.ps1 └── New-UnifiCommand.ps1 ├── Public ├── Clear-UnifiSiteAlarm.ps1 ├── Connect-UnifiController.ps1 ├── Disconnect-UnifiController.ps1 ├── Get-UnifiAdmin.ps1 ├── Get-UnifiControllerName.ps1 ├── Get-UnifiEventStrings.ps1 ├── Get-UnifiFirewallProtocol.ps1 ├── Get-UnifiProductList.ps1 ├── Get-UnifiSite.ps1 ├── Get-UnifiSiteAdmin.ps1 ├── Get-UnifiSiteAlarm.ps1 ├── Get-UnifiSiteBackup.ps1 ├── Get-UnifiSiteClient.ps1 ├── Get-UnifiSiteCountryCode.ps1 ├── Get-UnifiSiteDevice.ps1 ├── Get-UnifiSiteDynamicDNS.ps1 ├── Get-UnifiSiteEvent.ps1 ├── Get-UnifiSiteFirewallGroup.ps1 ├── Get-UnifiSiteFirewallRule.ps1 ├── Get-UnifiSiteHealth.ps1 ├── Get-UnifiSiteKnownAccessPoint.ps1 ├── Get-UnifiSiteNetwork.ps1 ├── Get-UnifiSitePortForwarding.ps1 ├── Get-UnifiSiteRadiusAccount.ps1 ├── Get-UnifiSiteRadiusProfile.ps1 ├── Get-UnifiSiteRouting.ps1 ├── Get-UnifiSiteSetting.ps1 ├── Get-UnifiSiteStatistic.ps1 ├── Get-UnifiSiteSwitchProfile.ps1 ├── Get-UnifiSiteSystemInformation.ps1 ├── Get-UnifiSiteTag.ps1 ├── Get-UnifiSiteWarning.ps1 ├── Get-UnifiSiteWhoAmI.ps1 ├── Get-UnifiSiteWirelessNetwork.ps1 ├── Get-UnifiSiteWirelessRFChannel.ps1 ├── Get-UnifiStatus.ps1 ├── Get-UnifiTimeZone.ps1 ├── Get-UnifiWhoAmI.ps1 ├── Grant-UnifiSuperAdmin.ps1 ├── New-UnifiSiteAdmin.ps1 ├── New-UnifiSiteFirewallRule.ps1 ├── Remove-UnifiAdmin.ps1 ├── Remove-UnifiSiteAdmin.ps1 ├── Revoke-UnifiSuperAdmin.ps1 ├── Set-UnifiSiteAdmin.ps1 ├── Set-UnifiSiteDevice.ps1 ├── Set-UnifiSiteSetting.ps1 └── Test-UnifiSiteKnownSetting.ps1 ├── README.md ├── Unifi.psd1 ├── Unifi.psm1 └── ubiquiti_icon.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Michael McCool 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Private/Convert-FromUnixDate.ps1: -------------------------------------------------------------------------------- 1 | Function Convert-FromUnixDate ($UnixDate) { 2 | [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($UnixDate)) 3 | } 4 | -------------------------------------------------------------------------------- /Private/Convert-ToUnixDate.ps1: -------------------------------------------------------------------------------- 1 | Function Convert-ToUnixDate { 2 | param ( 3 | $LocalDate, 4 | [ValidateSet('Seconds','Milliseconds', IgnoreCase=$false)]$units 5 | ) 6 | switch ($units){ 7 | "Seconds" { 8 | ([timezone]::CurrentTimeZone.ToUniversalTime((Get-date $LocalDate))-(Get-date "1/1/1970")).TotalSeconds 9 | } 10 | "Milliseconds" { 11 | ([timezone]::CurrentTimeZone.ToUniversalTime((Get-date $LocalDate))-(Get-date "1/1/1970")).TotalMilliseconds 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Private/ConvertTo-Object.ps1: -------------------------------------------------------------------------------- 1 | function ConvertTo-Object($hashtable) { 2 | # This function is used internally by other commands. It's purpose is to convert hashtables, arrays and other 3 | # types of objects into a PSCustomObject so a consistent method of accessing property names and values can be used. 4 | $object = New-Object PSCustomObject 5 | $hashtable.GetEnumerator() | 6 | ForEach-Object { Add-Member -inputObject $object -memberType NoteProperty -name $_.Name -value $_.Value } 7 | $object 8 | } -------------------------------------------------------------------------------- /Private/ConvertTo-UnifiObject.ps1: -------------------------------------------------------------------------------- 1 | 2 | function ConvertTo-UnifiObject { 3 | param ( 4 | [Parameter(Position=0, Mandatory = $true, ValueFromPipeline = $true)]$Object, 5 | [Parameter(Position=1, Mandatory = $true, ValueFromPipeline = $true)][String]$Delimiter, 6 | [Parameter(Position=2, Mandatory = $false, ValueFromPipeline = $true)][switch]$Filter 7 | ) 8 | $NewObject=$null 9 | $NewObject = [PSCustomObject]@{} 10 | foreach ($Item in $Object){ 11 | $NewSubObject=$null 12 | $NewSubObject=[PSCustomObject]@{} 13 | if ($Filter){ 14 | # There are some junk duplicates which contain a _id value only. This filters those out from the new object. 15 | if (($Item | Get-Member -MemberType NoteProperty).count -gt 2) { 16 | foreach ($SubItem in $Item) { 17 | $Props = $SubItem | get-member -membertype NoteProperty 18 | foreach($Prop in $Props) { 19 | $NewSubObject | Add-member -MemberType NoteProperty -Name $Prop.name -Value $SubItem.($Prop.name) 20 | } 21 | } 22 | $NewObject | add-member -MemberType NoteProperty -name $Item.$Delimiter -value $NewSubObject 23 | } 24 | } 25 | else { 26 | foreach ($SubItem in $Item) { 27 | $Props = $SubItem | get-member -membertype NoteProperty 28 | foreach($Prop in $Props) { 29 | $NewSubObject | Add-member -MemberType NoteProperty -Name $Prop.name -Value $SubItem.($Prop.name) 30 | } 31 | } 32 | $NewObject | add-member -MemberType NoteProperty -name $Item.$Delimiter -value $NewSubObject 33 | } 34 | 35 | } 36 | $NewObject 37 | <# 38 | .SYNOPSIS 39 | This function is used internally to help format certain REST API results. 40 | 41 | .DESCRIPTION 42 | This function is used internally to help format certain REST API results. Some results are simply an array of objects rather than something which is easily used. 43 | For example, in the raw REST API data, if you had the site settings stored in $UnifiSiteSettings, you would need the following command to view the provider upload speed: 44 | ($UnifiSiteSettings | where-object {$_.key -eq "provider_capabilities"}).upload. With this reformatted, one can simply use $UnifiSiteSettings.provider_capabilities.upload for the same results. 45 | 46 | .PARAMETER Object 47 | This is the object that will be converted. 48 | 49 | .PARAMETER Delimiter 50 | This is the key value in the Object data which is used for the reference when converting. This value must exist for all objects in the array. 51 | 52 | .PARAMETER Filter 53 | This is a switch parameter to indicate if the function should filter out subitems with just one entry. 54 | 55 | 56 | .INPUTS 57 | System.Object, System.String, Switch. 58 | 59 | .OUTPUTS 60 | System.Object. 61 | #> 62 | } -------------------------------------------------------------------------------- /Private/Invoke-GetRestAPICall.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Invoke-GetRestAPICall { 3 | [CmdletBinding()] 4 | param( 5 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] ` 6 | [string]$url, 7 | [Parameter(Position = 1, Mandatory = $false, ValueFromPipeline = $true)] ` 8 | [System.Collections.Generic.Dictionary[[String], [String]]]$headers 9 | ) 10 | try { 11 | if ($headers) { 12 | $request = Invoke-RestMethod -Method GET -Headers $headers -Uri $url -WebSession $Session 13 | } 14 | else { 15 | $request = Invoke-RestMethod -Uri $url -WebSession $Session 16 | } 17 | } 18 | catch [System.Net.WebException] { 19 | $exceptionMessage = $_.Exception.Message 20 | 21 | switch ($exceptionMessage) { 22 | # Refresh the login if the cookie times out. 23 | "The underlying connection was closed: An unexpected error occurred on a send." { 24 | write-verbose "Connection timed out. Refreshing session." 25 | Connect-UnifiController -Refresh 26 | if ($headers) { 27 | $request = Invoke-RestMethod -Method GET -Headers $headers -Uri $url -WebSession $Session 28 | } 29 | else { 30 | $request = Invoke-RestMethod -Uri $url -WebSession $Session 31 | } 32 | } 33 | default { 34 | write-host "Error Message: $exceptionmessage" 35 | exit 1 36 | } 37 | } 38 | } 39 | 40 | return $request 41 | } 42 | -------------------------------------------------------------------------------- /Private/Invoke-PostRestAPICall.ps1: -------------------------------------------------------------------------------- 1 | 2 | 3 | function Invoke-POSTRestAPICall { 4 | [CmdletBinding()] 5 | param( 6 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] ` 7 | [string]$url, 8 | [Parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)] ` 9 | [string]$payload, 10 | [Parameter(Position = 3, Mandatory = $false, ValueFromPipeline = $true)] ` 11 | [System.Collections.Generic.Dictionary[[String], [String]]]$headers 12 | ) 13 | 14 | try { 15 | if ($headers) { 16 | $request = Invoke-RestMethod -Method POST -Headers $headers -Body $payload -Uri $url -ContentType "application/json; charset=utf-8" -WebSession $Session 17 | } 18 | else { 19 | $request = Invoke-RestMethod -method POST -Body $payload -Uri $url -ContentType "application/json; charset=utf-8" -WebSession $Session 20 | } 21 | } 22 | 23 | catch [System.Net.WebException] { 24 | $exceptionError = $_.Exception 25 | $exceptionMessage = $_.Exception.Message 26 | 27 | switch ($exceptionMessage) { 28 | # Refresh the login if the cookie times out. 29 | "The remote server returned an error: (401) Unauthorized." { 30 | write-verbose "Connection timed out. Refreshing session." 31 | Connect-UnifiController -Refresh 32 | if ($headers) { 33 | $request = Invoke-RestMethod -Method POST -Headers $headers -Body $payload -Uri $url -ContentType "application/json; charset=utf-8" -WebSession $Session 34 | } 35 | else { 36 | $request = Invoke-RestMethod -Body $payload -Uri $url -ContentType "application/json; charset=utf-8" -WebSession $Session 37 | } 38 | } 39 | default { 40 | write-host "Error Message: $ExceptionMessage" 41 | exit 1 42 | } 43 | } 44 | } 45 | return $request 46 | } -------------------------------------------------------------------------------- /Private/New-UnifiCommand.ps1: -------------------------------------------------------------------------------- 1 | function New-UnifiCommand { 2 | param( 3 | [Parameter(Position = 0, Mandatory = $true)]$Object 4 | ) 5 | $Object | ConvertTo-Json 6 | 7 | <# 8 | .SYNOPSIS 9 | Converts the object into a JSON formated string. 10 | 11 | .DESCRIPTION 12 | Converts the object into a JSON formated string. This is a helper command for building the proper structure for sending instructions to the Unifi controller api. 13 | This will not be used in script creation directly, but is leveraged by other commands in a modular fashion. 14 | 15 | .PARAMETER Object 16 | This can be a PSCustomObject, Array, ArrayList, HashTable or other value set that will work with the ConvertTo-Json cmdlet. 17 | 18 | .INPUTS 19 | System.Object. You cannot pipe values into this command. 20 | 21 | .OUTPUTS 22 | System.String. JSON formatted. 23 | #> 24 | } 25 | -------------------------------------------------------------------------------- /Public/Clear-UnifiSiteAlarm.ps1: -------------------------------------------------------------------------------- 1 | function Clear-UnifiSiteAlarm { 2 | [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ID')] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName='ID')] 5 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName='ClearAll')] 6 | [string]$name, 7 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName='ID')] 8 | [string]$ID, 9 | [Parameter(ParameterSetName='ClearAll')][switch]$ClearAll 10 | ) 11 | if ($ClearAll) { 12 | $params = @{ 13 | cmd = "archive-all-alarms" 14 | } 15 | $body = New-UnifiCommand $params 16 | $URI = "$controller/api/s/$name/cmd/evtmgr" 17 | if ($PSCmdlet.ShouldProcess($URI,"Clear All Alarms")){ 18 | $null = Invoke-POSTRestAPICall -url $URI -payload $body 19 | } 20 | } 21 | else { 22 | $params = @{ 23 | cmd = "archive-alarm" 24 | _id = $ID 25 | } 26 | $body = New-UnifiCommand $params 27 | $URI = "$controller/api/s/$name/cmd/evtmgr" 28 | if ($PSCmdlet.ShouldProcess($URI,"Archive alarm $ID")){ 29 | $null = Invoke-POSTRestAPICall -url $URI -payload $body 30 | } 31 | } 32 | <# 33 | .SYNOPSIS 34 | Archive the specified site alarm. 35 | 36 | .DESCRIPTION 37 | Archive the specified site alarm. If the -ClearAll switch is used, all site alarms are archived. 38 | 39 | .PARAMETER Name 40 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 41 | 42 | .PARAMETER ID 43 | The _id value from the Get-UnifiSiteAlarm command. 44 | 45 | .PARAMETER ClearAll 46 | Switch value to indicate that all current alarms for the site should be archived. 47 | 48 | .INPUTS 49 | System.String. 50 | 51 | .OUTPUTS 52 | System.Object. 53 | #> 54 | } 55 | -------------------------------------------------------------------------------- /Public/Connect-UnifiController.ps1: -------------------------------------------------------------------------------- 1 | function Connect-UnifiController { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter(ParameterSetName = 'Connect', Mandatory = $true)]$ControllerURL, 5 | [Parameter(ParameterSetName = 'Connect', Mandatory = $true)][PSCredential]$credentials, 6 | [Parameter(ParameterSetName = 'Refresh')][switch]$Refresh, 7 | [Parameter(ParameterSetName = 'Connect')][switch]$UDMPro 8 | ) 9 | 10 | if (!$refresh){ 11 | 12 | if ($UDMPro) { 13 | $script:LoginURI="$ControllerURL/api/auth/login" 14 | $ControllerURL = $ControllerURL+"/proxy/network" 15 | } 16 | else { 17 | $script:LoginURI="$ControllerURL/api/login" 18 | } 19 | $script:Controller = $ControllerURL 20 | $script:Credentials = $credentials 21 | } 22 | 23 | $params = @{ 24 | username = $script:credentials.GetNetworkCredential().UserName 25 | password = $script:credentials.GetNetworkCredential().password 26 | } 27 | $body = New-UnifiCommand $params 28 | 29 | if ($null -eq $Script:Session){ 30 | write-verbose "Creating new Session object." 31 | $Script:Session = New-Object Microsoft.PowerShell.Commands.WebRequestSession 32 | } 33 | $Domain=([System.Uri]$Script:controller).host 34 | write-verbose "Domain is $Domain." 35 | try { 36 | $results = Invoke-Restmethod -Uri $LoginURI -method post -body $body -ContentType "application/json; charset=utf-8" -WebSession $Script:Session -TimeoutSec 600 37 | write-verbose $Script:Session.Cookies 38 | if ($results.meta.rc -eq "ok") { 39 | if (!$refresh){ 40 | Write-Verbose "Successfully connected to Unifi controller." 41 | } 42 | else { 43 | Write-Verbose "Successfully reconnected to Unifi controller." 44 | } 45 | # Set this as a script variable as it will be used for all other commands in the module. 46 | 47 | 48 | } 49 | } 50 | catch { 51 | $ErrorResponse=$_.errordetails.Message | ConvertFrom-Json 52 | # The 2FA Session cookie is created as part of the response details from a failed initial logon. 53 | # Add this to the session data. 54 | if (($ErrorResponse.data.mfa_cookie) -and (($Script:session.Cookies.GetCookies("https://$Domain")).name -notcontains 'UBIC_2FA')) { 55 | $MFACookie=$ErrorResponse.data.mfa_cookie 56 | $cookie = New-Object System.Net.Cookie 57 | $cookie.Name = "UBIC_2FA" 58 | $cookie.Value = $MFACookie 59 | $cookie.Domain = $Domain 60 | $Script:Session.Cookies.Add($cookie); 61 | } 62 | # If the error indicates a MFA token is required, ask for the MFA token. 63 | if ($ErrorResponse.meta.msg -match 'Ubic2faTokenRequired') { 64 | 65 | 66 | write-verbose "Unifi 2FA required." 67 | $params = @{ 68 | username = $script:credentials.GetNetworkCredential().UserName 69 | password = $script:credentials.GetNetworkCredential().password 70 | ubic_2fa_token = Read-Host -Prompt "Unfi 2FA for $($script:credentials.GetNetworkCredential().UserName)" 71 | } 72 | $body = New-UnifiCommand $params 73 | $results = Invoke-Restmethod -Uri $LoginURI -method post -body $body -ContentType "application/json; charset=utf-8" -WebSession $Script:Session -TimeoutSec 600 74 | write-verbose $Script:Session.Cookies.count 75 | $global:logonresults=$results 76 | if ($results.meta.rc -eq "ok") { 77 | if (!$refresh){ 78 | Write-Verbose "Successfully connected to Unifi controller." 79 | 80 | } 81 | else { 82 | Write-Verbose "Successfully reconnected to Unifi controller." 83 | } 84 | } 85 | } 86 | else { 87 | $APIerror = "API Connection Error: $($_.Exception.Message)" 88 | $APIerror 89 | $Global:APIError=$_ 90 | } 91 | 92 | } 93 | $Global:WebSession = $Script:Session 94 | <# 95 | .SYNOPSIS 96 | Connects to the Unifi controller. 97 | 98 | .DESCRIPTION 99 | Connects to the Unifi controller. If you are connecting to a UDMPro, make sure to use the '-UDMPro' switch. The connection 100 | to the Unifi controller will automatically be renewed when the current session expires. 101 | 102 | .PARAMETER ControllerURL 103 | Complete URI for the controller. i.e.: https://mycontroller:8443 104 | 105 | .PARAMETER Credentials 106 | PSCredential object containing the user name and a plaintext secure string for the password. 107 | 108 | .PARAMETER UDMPro 109 | Switch for connecting to UDMPro devices. The login endpoint and base URL is different for UDMPro devices vs. Unifi controllers. 110 | 111 | .NOTES 112 | Notes and code snippets for building required variables to use with this command: 113 | 114 | [String]$Hostname = '' 115 | [String]$Port = '8443' # Change this to match the listening port 116 | [String]$UnifiUsername = '' 117 | [String]$UnifiPassword = '' 118 | 119 | [String]$Controller = "https://$($hostname):$($port)" 120 | 121 | # Enables TLS1.2 -- this is a universal method that works for any dot net version 122 | [Net.ServicePointManager]::SecurityProtocol = [Enum]::ToObject([Net.SecurityProtocolType], 3072) 123 | 124 | # Ignore self-signed certificates 125 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 126 | 127 | # Create a secure credential object 128 | [securestring]$SecPassword=ConvertTo-SecureString $UnifiPassword -AsPlainText -Force 129 | [pscredential]$Credentials=New-Object System.Management.Automation.PSCredential ($UnifiUsername, $SecPassword) 130 | 131 | import-module Unifi 132 | 133 | Connect-UnifiController -ControllerURL $Controller -credentials $Credentials 134 | 135 | .INPUTS 136 | None. 137 | 138 | .OUTPUTS 139 | None. 140 | 141 | .EXAMPLE 142 | Connect-UnifiController -ControllerURL $Controller -credentials $Credentials 143 | 144 | Connects to the Unifi controller URI specified in the $controller variable and uses the credentials provided in the $Credentials variable. 145 | $Controller is the full URI and port required for accessing the controller's web UI. The $Credentials variable is a PSCredential object. 146 | Please see notes for more information about how to create these variables. 147 | #> 148 | } -------------------------------------------------------------------------------- /Public/Disconnect-UnifiController.ps1: -------------------------------------------------------------------------------- 1 | function Disconnect-UnifiController { 2 | [CmdletBinding()] 3 | # Disconnect from Unifi controller 4 | $results = Invoke-Restmethod -Uri "$controller/api/logout" -method post -ContentType "application/json; charset=utf-8" -Websession $session 5 | if ($results.meta.rc -eq "ok") { 6 | write-host "Successfully disconnected from Unifi controller." 7 | } 8 | <# 9 | .SYNOPSIS 10 | Disconnects from the Unifi controller. 11 | 12 | .DESCRIPTION 13 | Disconnects from the Unifi controller. This will invalidate the current session. This command really isn't needed, 14 | but is included for completeness. The API supports a session logout, so this functionality is present in the module. 15 | 16 | .INPUTS 17 | None. 18 | 19 | .OUTPUTS 20 | None. 21 | #> 22 | } -------------------------------------------------------------------------------- /Public/Get-UnifiAdmin.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-UnifiAdmin { 3 | [CmdletBinding()] 4 | param () 5 | $URI = "$controller/api/stat/admin" 6 | (Invoke-GetRestAPICall $URI).data 7 | <# 8 | .SYNOPSIS 9 | List all administrators and permissions. 10 | 11 | .DESCRIPTION 12 | List all administrators and permissions. 13 | 14 | .INPUTS 15 | None. 16 | 17 | .OUTPUTS 18 | System.Object. 19 | #> 20 | } -------------------------------------------------------------------------------- /Public/Get-UnifiControllerName.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiControllerName { 2 | [CmdletBinding()] 3 | param() 4 | $URI = "$controller/manage/site/default/dashboard" 5 | 6 | $results=(Invoke-GetRestAPICall $URI) 7 | 8 | if ($results -match "(?<=angular\/).*?(?=\/)") { 9 | write-verbose "Successfully extracted controller name from webpage." 10 | $matches.0 11 | } 12 | else { 13 | write-verbose "Unable to extract controller name from dashboard webpage." 14 | } 15 | 16 | <# 17 | .SYNOPSIS 18 | Returns the short name for the controller itself. 19 | 20 | .DESCRIPTION 21 | Returns the short name for the controller itself. This is needed for pulling locale specific strings from the controller. 22 | 23 | This is an ugly hack to get the required data as the controller name doesn't seem to be available elsewhere in the API. 24 | It is however part of the image resource URIs inside the dashboard webpage. This command simply extracts that short name 25 | so we can pull the other locale strings dynamically. 26 | 27 | .INPUTS 28 | None. 29 | 30 | .OUTPUTS 31 | System.String. 32 | #> 33 | } 34 | -------------------------------------------------------------------------------- /Public/Get-UnifiEventStrings.ps1: -------------------------------------------------------------------------------- 1 | 2 | Function Get-UnifiEventStrings { 3 | [CmdletBinding()] 4 | Param( 5 | [string]$Language = "en" 6 | ) 7 | $ControllerName=Get-UnifiControllerName 8 | write-verbose "Extracting event strings for language: $Language" 9 | $URI = "$controller/manage/angular/$ControllerName/locales/$($Language.tolower())/eventStrings.json" 10 | (Invoke-GetRestAPICall $URI) 11 | 12 | <# 13 | .SYNOPSIS 14 | Extracts the event strings from the controller language files. 15 | 16 | .DESCRIPTION 17 | Extracts the event strings from the controller language files. This can be useful when developing certain scripts which require 18 | knowledge of all possible events which can be generated. 19 | 20 | .PARAMETER Language 21 | The two letter code for the language. Languages other than English (en) are a beta feature in the Unifi product and may not be available. 22 | If this value is ommited, English (en) will be used. 23 | 24 | .INPUTS 25 | None. 26 | 27 | .OUTPUTS 28 | System.Object. 29 | #> 30 | } -------------------------------------------------------------------------------- /Public/Get-UnifiFirewallProtocol.ps1: -------------------------------------------------------------------------------- 1 | # Get the list of valid protocols for creating firewall rules. 2 | function Get-UnifiFirewallProtocol { 3 | [CmdletBinding()] 4 | param () 5 | $ControllerName=Get-UnifiControllerName 6 | $URI = "$controller/manage/angular/$ControllerName/js/app.js" 7 | $WebResults=(Invoke-GetRestAPICall $URI) 8 | 9 | # To convert this properly we need a raw data stream. 10 | $Webresults | out-file -FilePath "$env:TEMP\Webresults.txt" 11 | $TempData = Get-content $env:temp\Webresults.txt -raw 12 | Remove-Item -Path "$env:TEMP\Webresults.txt" 13 | 14 | # Extract the relevant function from the javascript. 15 | $FullRegex='(?<=957:\[function\(e,t,n\)).*(?=,\{\}\],958:\[function\(e,t,n\))' 16 | [void]($tempData -match $FullRegex) 17 | $FunctionData=$Matches.0 18 | 19 | # Extract the json data and convert into a powershell object. 20 | $GroupRegex='(?<="FIREWALL",).*(?=\)\})' 21 | [void]($FunctionData -match $GroupRegex) 22 | $GroupData=$Matches.0 | ConvertFrom-Json 23 | 24 | # Make a new PSCustomObject with just the protocol data. 25 | $Protocols= [PSCustomObject] @{ 26 | IPV4 = $GroupData.IPV4 27 | IPV6 = $GroupData.IPV6 28 | } 29 | 30 | # The ICMP types include an empty value in the data. Remove the empty value. 31 | $Protocols.IPV4.ICMP_TYPES = $Protocols.IPV4.ICMP_TYPES | where-object {!([string]::IsNullOrWhiteSpace($_))} 32 | $Protocols.IPV6.ICMP_TYPES = $Protocols.IPV6.ICMP_TYPES | where-object {!([string]::IsNullOrWhiteSpace($_))} 33 | 34 | # Return the modified data for use elsewhere. 35 | $Protocols 36 | 37 | <# 38 | .SYNOPSIS 39 | Returns information on the various valid protocol selections for firewall rules. 40 | 41 | .DESCRIPTION 42 | Returns information on the various valid protocol selections for firewall rules. 43 | 44 | .INPUTS 45 | None. 46 | 47 | .OUTPUTS 48 | System.Object. 49 | #> 50 | } -------------------------------------------------------------------------------- /Public/Get-UnifiProductList.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiProductList { 2 | [CmdletBinding()] 3 | param ( 4 | [switch]$Detailed 5 | ) 6 | 7 | function StreamCount { 8 | [CmdletBinding()] 9 | param ( 10 | [int]$start, 11 | $object 12 | ) 13 | $i=$Start 14 | $brcount=0 15 | $Loopbreak=$false 16 | $InLoop=$false 17 | while ($loopbreak -eq $false){ 18 | $char=$object[$i] 19 | if ($char -eq "{"){ 20 | $brcount++ 21 | } 22 | if ($brcount -gt 0){ 23 | $InLoop=$true 24 | } 25 | if ($char -eq "}"){ 26 | $brcount-- 27 | } 28 | if ($inloop -eq $true){ 29 | if ($brcount -eq 0){ 30 | $loopbreak=$true 31 | } 32 | } 33 | write-verbose "Char: $char - Count: $i - BR: $brcount $Inloop" 34 | if ($InLoop -eq $true){ 35 | if ($brcount -eq 0){ 36 | $loopbreak=$true 37 | } 38 | } 39 | if ($i -ge $object.length) { 40 | $Loopbreak=$true 41 | } 42 | $i++ 43 | } 44 | $i 45 | } 46 | 47 | function StreamString { 48 | param ( 49 | $Start, 50 | $End, 51 | $Data 52 | ) 53 | $RelLength=$End-$Start 54 | $Data.substring($start,$Rellength) 55 | } 56 | 57 | # The product list data entry is different under different Unifi controller versions. 58 | $UnifiVersion=(Get-UnifiStatus).server_version 59 | $ControllerName=Get-UnifiControllerName 60 | 61 | $URI = "$controller/manage/angular/$ControllerName/js/app.js" 62 | $WebResults=(Invoke-GetRestAPICall $URI) 63 | 64 | $Webresults | out-file -FilePath "$env:TEMP\Webresults.txt" 65 | switch ($UnifiVersion){ 66 | # This part contains the regex code to extract the product list data from the javascript code. 67 | "5.13.32" { 68 | $FullRegex='(?<={1:\[function\(e,t,n\)\{t\.exports=\{).*(?=,\{\}\],2:\[function\(e,t,n\))' 69 | } 70 | } 71 | 72 | 73 | $TempData = Get-content "$env:TEMP\webresults.txt" -raw 74 | Remove-Item -Path "$env:TEMP\Webresults.txt" 75 | [void]($tempData -match $FullRegex) 76 | $DataToParse=$Matches.0 77 | 78 | $i=0 79 | $Start=0 80 | $DeviceData=[System.Collections.ArrayList]@() 81 | do { 82 | $EndCount=StreamCount -start $Start -object $DataToParse 83 | # $Start 84 | # $Endcount 85 | if ($endcount -gt $DataToParse.Length){ 86 | $Endcount=$DataToParse.Length 87 | } 88 | $String=(StreamString -start $start -end $EndCount -data $DataToParse).replace("`n","") 89 | if ($string.length -gt 5){ 90 | [void]$DeviceData.Add($string) 91 | } 92 | $Start=$EndCount+1 93 | } 94 | until ($Endcount -ge $DataToParse.Length) 95 | 96 | if ($Detailed){ 97 | # This object conversion script created by reddit user /u/marsonreddit 98 | $DeviceList = [System.Collections.Generic.List[psobject]]::new() 99 | # Apart from an illegal character in your data set, everything after : appear to be valid JSON 100 | $regex = '(:)(?!["{}\[\]])(?[*~@#$%^&*()_+=> 152 | } 153 | 154 | 155 | -------------------------------------------------------------------------------- /Public/Get-UnifiSite.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSite { 2 | [CmdletBinding(DefaultParameterSetName='None')] 3 | param ( 4 | [Parameter(Mandatory=$true, ParameterSetName="IncludeHealth")][switch]$IncludeHealth, 5 | [Parameter(Mandatory=$false, ParameterSetName="IncludeHealth")][switch]$Raw 6 | ) 7 | 8 | if ($IncludeHealth) { 9 | $URI = "$controller/api/stat/sites" 10 | } 11 | else { 12 | $URI = "$controller/api/self/sites" 13 | } 14 | $RawResults=(Invoke-GetRestAPICall $URI).data 15 | if ($raw){ 16 | $RawResults 17 | } 18 | else { 19 | if ($IncludeHealth){ 20 | ForEach ($result in $RawResults){ 21 | $result.health = ConvertTo-UnifiObject $result.health -Delimiter 'subsystem' 22 | } 23 | } 24 | $RawResults 25 | } 26 | 27 | <# 28 | .SYNOPSIS 29 | Retrieves the list of sites from the Unifi controller. 30 | 31 | .DESCRIPTION 32 | Retrieves the list of sites from the Unifi controller and optionally the health status and new alarm count. 33 | 34 | .PARAMETER IncludeHealth 35 | Switch to also return basic health information and new alarm count. 36 | 37 | .PARAMETER Raw 38 | Switch to return the raw health results as received from the API. 39 | 40 | .INPUTS 41 | None. 42 | 43 | .OUTPUTS 44 | System.Object. 45 | #> 46 | } 47 | -------------------------------------------------------------------------------- /Public/Get-UnifiSiteAdmin.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteAdmin { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $params = @{ 7 | cmd = "get-admins" 8 | } 9 | $body = New-UnifiCommand $params 10 | $URI = "$controller/api/s/$name/cmd/sitemgr" 11 | (Invoke-POSTRestAPICall -url $URI -payload $body).data 12 | <# 13 | .SYNOPSIS 14 | List all administrators and permissions for this site. 15 | 16 | .DESCRIPTION 17 | List all administrators and permissions for this site. 18 | 19 | .PARAMETER Name 20 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 21 | 22 | .INPUTS 23 | System.String. You can pipe id values into this command. 24 | 25 | .OUTPUTS 26 | System.Object. 27 | #> 28 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteAlarm.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-UnifiSiteAlarm { 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 6 | [switch]$IncludeArchived 7 | ) 8 | if ($IncludeArchived){ 9 | $URI = "$controller/api/s/$name/stat/alarm" 10 | } 11 | else { 12 | $URI = "$controller/api/s/$name/stat/alarm?archived=false" 13 | } 14 | 15 | 16 | $Results = (Invoke-GetRestAPICall $URI).data 17 | 18 | # Each device type has its own set of name/model/displayname properties. Add in a generic "device" identifier for ease of use. 19 | foreach ($Result in $Results){ 20 | switch ($Result.key) { 21 | {$_ -match "EVT_AP"} { 22 | # Access Point 23 | $Result | add-member -memberType AliasProperty -name device -value ap 24 | $Result | add-member -memberType AliasProperty -name device_name -value ap_name 25 | $Result | add-member -memberType AliasProperty -name device_model -value ap_model 26 | $Result | add-member -memberType AliasProperty -name device_displayName -value ap_displayName 27 | } 28 | {$_ -match "EVT_DM"} { 29 | # Dream Machine 30 | $Result | add-member -memberType AliasProperty -name device -value dm 31 | $Result | add-member -memberType AliasProperty -name device_name -value dm_name 32 | $Result | add-member -memberType AliasProperty -name device_model -value dm_model 33 | $Result | add-member -memberType AliasProperty -name device_displayName -value dm_displayName 34 | } 35 | {$_ -match "EVT_GW"} { 36 | # Gateway 37 | $Result | add-member -memberType AliasProperty -name device -value gw 38 | $Result | add-member -memberType AliasProperty -name device_name -value gw_name 39 | $Result | add-member -memberType AliasProperty -name device_model -value gw_model 40 | $Result | add-member -memberType AliasProperty -name device_displayName -value gw_displayName 41 | } 42 | {$_ -match "EVT_ULTE"} { 43 | # LTE 44 | $Result | add-member -memberType AliasProperty -name device -value ulte 45 | $Result | add-member -memberType AliasProperty -name device_name -value ulte_name 46 | $Result | add-member -memberType AliasProperty -name device_model -value ulte_model 47 | $Result | add-member -memberType AliasProperty -name device_displayName -value ulte_displayName 48 | } 49 | {$_ -match "EVT_USP_RPS"} { 50 | # RPS 51 | $Result | add-member -memberType AliasProperty -name device -value usp_rps 52 | $Result | add-member -memberType AliasProperty -name device_name -value usp_rps_name 53 | $Result | add-member -memberType AliasProperty -name device_model -value usp_rps_model 54 | $Result | add-member -memberType AliasProperty -name device_displayName -value usp_rps_displayName 55 | } 56 | {$_ -match "EVT_SW"} { 57 | # Switch 58 | $Result | add-member -memberType AliasProperty -name device -value sw 59 | $Result | add-member -memberType AliasProperty -name device_name -value sw_name 60 | $Result | add-member -memberType AliasProperty -name device_model -value sw_model 61 | $Result | add-member -memberType AliasProperty -name device_displayName -value sw_displayName 62 | } 63 | {$_ -match "EVT_XG"} { 64 | # NeXt-Gen Gateway 65 | $Result | add-member -memberType AliasProperty -name device -value xg 66 | $Result | add-member -memberType AliasProperty -name device_name -value xg_name 67 | $Result | add-member -memberType AliasProperty -name device_model -value xg_model 68 | $Result | add-member -memberType AliasProperty -name device_displayName -value xg_displayName 69 | } 70 | {$_ -match "EVT_BB"} { 71 | # Bridge 72 | $Result | add-member -memberType AliasProperty -name device -value bb 73 | $Result | add-member -memberType AliasProperty -name device_name -value bb_name 74 | $Result | add-member -memberType AliasProperty -name device_model -value bb_model 75 | $Result | add-member -memberType AliasProperty -name device_displayName -value bb_displayName 76 | } 77 | default {} 78 | } 79 | } 80 | $Results 81 | <# 82 | .SYNOPSIS 83 | List site alarms by most recent first, 3000 result limit. 84 | 85 | .DESCRIPTION 86 | List site alarms by most recent first, 3000 result limit. A generic "device" alias* has been added to many of the alarm events. 87 | This allows for a common reference when retrieving the device's MAC, friendly name, model or display name rather than needing 88 | to change the object property to support each different hardware model. The properties added to the API results are: device, 89 | device_name, device_model, and device_displayName. 90 | 91 | *Please note that there were several gueses as to which properties and hardware would be available for the various alarms. If 92 | you find an alarm which is missing the generic device entries or find one that has blank values where values should be present, 93 | please let the module author know. 94 | 95 | .PARAMETER Name 96 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 97 | 98 | .PARAMETER IncludeArchived 99 | Switch to return all alarms, including archived. 100 | 101 | .INPUTS 102 | System.String. Can take value from pipeline. 103 | 104 | .OUTPUTS 105 | System.Object. 106 | #> 107 | } 108 | -------------------------------------------------------------------------------- /Public/Get-UnifiSiteBackup.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiBackup { 2 | [CmdletBinding()] 3 | param () 4 | $params = @{ 5 | cmd = "list-backups" 6 | } 7 | $body = New-UnifiCommand $params 8 | $URI = "$controller/api/s/default/cmd/backup" 9 | (Invoke-POSTRestAPICall -url $URI -payload $body).data 10 | <# 11 | .SYNOPSIS 12 | List of autobackup files. 13 | 14 | .DESCRIPTION 15 | List of autobackup files. 16 | 17 | .NOTES 18 | This particular command is issued with a site specified, but it global for the controller. As such, I have 19 | hard coded the command to use the 'default' site and to be a global command rather than site specific command. 20 | If this is determined not to be the case, please let me know. 21 | 22 | .INPUTS 23 | None. 24 | 25 | .OUTPUTS 26 | System.Object. 27 | #> 28 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteClient.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteClient { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Known 6 | ) 7 | if ($Known){ 8 | $URI = "$controller/api/s/$name/rest/user" 9 | } 10 | else { 11 | $URI = "$controller/api/s/$name/stat/sta" 12 | } 13 | (Invoke-GetRestAPICall $URI).data 14 | <# 15 | .SYNOPSIS 16 | List current devices attached to the network. 17 | 18 | .DESCRIPTION 19 | List current devices attached to the network. Use the -Known switch to return a list of all known devices. (This list can be quite long.) 20 | 21 | .PARAMETER Name 22 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 23 | 24 | .PARAMETER Known 25 | Switch to retrieve a list of all known devices. (This list can be quite long.) 26 | 27 | .INPUTS 28 | System.String. Can take value from pipeline. 29 | 30 | .OUTPUTS 31 | System.Object. 32 | #> 33 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteCountryCode.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteCountryCode { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name = 'default' 5 | ) 6 | $URI = "$controller/api/s/$name/stat/ccode" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List all country code information. 11 | 12 | .DESCRIPTION 13 | List all country code information. 14 | 15 | .NOTES 16 | The country code information does not appear to change for any site queried. However, the API lists this 17 | as site level information, so that it why this is a site level command. If not supplied a specific site to 18 | query, it will use the value of 'default'. 19 | 20 | .PARAMETER Name 21 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 22 | 23 | .INPUTS 24 | System.String. Can take value from pipeline. 25 | 26 | .OUTPUTS 27 | System.Object. 28 | #> 29 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteDevice.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteDevice { 2 | [CmdletBinding(DefaultParameterSetName = 'Basic')] 3 | param ( 4 | [Parameter(ParameterSetName="Detailed", Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 5 | [Parameter(ParameterSetName="Basic", Position = 0, Mandatory = $true, ValueFromPipeline = $true)] 6 | [string]$name, 7 | [Parameter(ParameterSetName="Detailed")][switch]$Detailed, 8 | [Parameter(ParameterSetName="Detailed")]$MAC 9 | ) 10 | $BasicURI="$controller/api/s/$name/stat/device-basic" 11 | $DetailedURI="$controller/api/s/$name/stat/device" 12 | 13 | 14 | if (!$Detailed){ 15 | #Return basic information only. 16 | (Invoke-GetRestAPICall $BasicURI).data 17 | } 18 | else { 19 | if ($PSBoundParameters.ContainsKey('mac')){ 20 | 21 | if ($mac -is [array]){ 22 | # Normalize the mac addresses in the array to colon separated pairs. 23 | for ($i=0; $i -lt $mac.Length; $i++){ 24 | $mac[$i] = $mac[$i] -replace "([0-9a-f]{2})[^0-9a-f]?(?=.)",'$1:' 25 | } 26 | # If $mac is an array, use it as is. 27 | $Params=@{ 28 | macs = $mac 29 | } 30 | } 31 | else { 32 | # If $mac isn't an array, it should be a string. 33 | # Normalize the mac address to colon separated pairs. 34 | $mac = $mac -replace "([0-9a-f]{2})[^0-9a-f]?(?=.)",'$1:' 35 | 36 | # If $mac is a string, turn it into an array. 37 | $Params=@{ 38 | macs = @($mac) 39 | } 40 | } 41 | $body = New-UnifiCommand $params 42 | write-verbose $body 43 | $DeviceDetailed=(Invoke-POSTRestAPICall -url $DetailedURI -payload $body).data 44 | } 45 | else { 46 | $DeviceDetailed=(Invoke-GetRestAPICall $DetailedURI).data 47 | } 48 | $DeviceBasic=(Invoke-GetRestAPICall $BasicURI).data 49 | 50 | # The detailed results are missing the 'disabled' property, so the basic info is not a subset of the detailed info. 51 | # Add the 'disabled' property to the deatiled device information. 52 | write-verbose "Adding missing property `'disabled`' to detailed device information if needed." 53 | foreach ($entry in $DeviceDetailed){ 54 | if ([bool]($entry.PSObject.Properties.name -match 'disabled') -eq $false){ 55 | $Basic=$DeviceBasic | Where-Object {$_.mac -eq $entry.mac} 56 | $entry | Add-Member -MemberType NoteProperty -name 'disabled' -value $Basic.disabled 57 | } 58 | } 59 | $DeviceDetailed 60 | } 61 | <# 62 | .SYNOPSIS 63 | List site devices. 64 | 65 | .DESCRIPTION 66 | List site devices. For all device information, use the -Detailed switch. 67 | 68 | .NOTES 69 | The detailed results are missing the 'disabled' property from the API, so the basic device information is not a true subset of the detailed information. 70 | This has been "fixed" in this command by adding the missing property from the basic device information to the detailed device information. 71 | 72 | .PARAMETER Name 73 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 74 | 75 | .PARAMETER Detailed 76 | Switch to include full device details. 77 | 78 | .PARAMETER Mac 79 | Limit results to a specific MAC address(es). Value may be an array or string. 80 | 81 | .INPUTS 82 | System.String. Can take value from pipeline. 83 | 84 | .OUTPUTS 85 | System.Object. 86 | #> 87 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteDynamicDNS.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteDynamicDNS { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Status 6 | ) 7 | if ($status){ 8 | $URI = "$controller/api/s/$name/stat/dynamicdns" 9 | } 10 | else { 11 | $URI = "$controller/api/s/$name/rest/dynamicdns" 12 | } 13 | 14 | (Invoke-GetRestAPICall $URI).data 15 | <# 16 | .SYNOPSIS 17 | List Dynamic DNS configuration and optionally status. 18 | 19 | .DESCRIPTION 20 | List Dynamic DNS configuration and optionally status. Requires a USG. 21 | 22 | .PARAMETER Name 23 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 24 | 25 | .PARAMETER Status 26 | Switch to include Dynamic DNS status as well as configuration. (Current IP, last updated, and status.) 27 | 28 | .INPUTS 29 | System.String. Can take value from pipeline. 30 | 31 | .OUTPUTS 32 | System.Object. 33 | #> 34 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteEvent.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteEvent { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 5 | [switch]$IncludeArchived 6 | ) 7 | If ($IncludeArchived){ 8 | $URI = "$controller/api/s/$name/stat/event" 9 | } 10 | else { 11 | $URI = "$controller/api/s/$name/stat/event?archived=false" 12 | } 13 | (Invoke-GetRestAPICall $URI).data 14 | <# 15 | .SYNOPSIS 16 | List site events by most recent first, 3000 result limit. 17 | 18 | .DESCRIPTION 19 | List site events by most recent first, 3000 result limit. 20 | 21 | .PARAMETER Name 22 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 23 | 24 | .PARAMETER IncludeArchived 25 | Switch to return all events, including archived. 26 | 27 | .INPUTS 28 | System.String. Can take value from pipeline. 29 | 30 | .OUTPUTS 31 | System.Object. 32 | #> 33 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteFirewallGroup.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteFirewallGroup { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Known 6 | ) 7 | $URI = "$controller/api/s/$name/rest/firewallgroup" 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List current firewall groups. 12 | 13 | .DESCRIPTION 14 | List current firewall groups. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteFirewallRule.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteFirewallRule { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Known 6 | ) 7 | $URI = "$controller/api/s/$name/rest/firewallrule" 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List user defined firewall rules. 12 | 13 | .DESCRIPTION 14 | List user defined firewall rules. Auto-generated rules will not be listed. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteHealth.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteHealth { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$Name, 5 | [Parameter(Mandatory = $false)][switch]$Raw 6 | ) 7 | $URI = "$controller/api/s/$name/stat/health" 8 | 9 | $Results = (Invoke-GetRestAPICall $URI).data 10 | if ($Raw) { 11 | $Results 12 | } 13 | else { 14 | ConvertTo-UnifiObject -Object $Results -Delimiter "subsystem" 15 | } 16 | <# 17 | .SYNOPSIS 18 | Reports the health status of the specified site. 19 | 20 | .DESCRIPTION 21 | Reports the health status of the specified site. 22 | 23 | .PARAMETER Name 24 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 25 | 26 | .PARAMETER Raw 27 | Switch to return the raw health results as received from the API. 28 | 29 | .INPUTS 30 | System.String. Can take value from pipeline. 31 | 32 | .OUTPUTS 33 | System.Object. 34 | #> 35 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteKnownAccessPoint.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteKnownAccessPoint { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$Name, 5 | [Parameter(Position = 1, Mandatory = $false)][int]$Hours 6 | ) 7 | $URI = "$controller/api/s/$name/stat/rogueap" 8 | if ($Hours){ 9 | $params = @{ 10 | within = $Hours 11 | } 12 | $body = New-UnifiCommand $params 13 | (Invoke-POSTRestAPICall -url $URI -payload $body).data 14 | } 15 | else { 16 | (Invoke-GetRestAPICall $URI).data 17 | } 18 | 19 | <# 20 | .SYNOPSIS 21 | List known access points. 22 | 23 | .DESCRIPTION 24 | List known access points. These are all neighboring access points seen by connected APs. 25 | 26 | .PARAMETER Name 27 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 28 | 29 | .PARAMETER Hours 30 | Limit known access point results to the last X hours. 31 | 32 | .EXAMPLE 33 | Get-UnifiSiteKnownAccessPoint -Name default -Hours 24 34 | 35 | Returns a list of all neighboring access points seen in the last 24 hours for the default site. 36 | 37 | .INPUTS 38 | System.String. Can take value from pipeline. 39 | 40 | .OUTPUTS 41 | System.Object. 42 | #> 43 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteNetwork.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteNetwork { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/rest/networkconf" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List network configuration. 11 | 12 | .DESCRIPTION 13 | List network configuration. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSitePortForwarding.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSitePortForwarding { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Known 6 | ) 7 | $URI = "$controller/api/s/$name/rest/portforward" 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List configured port forwards. 12 | 13 | .DESCRIPTION 14 | List configured port forwards. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteRadiusAccount.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteRadiusAccount { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/rest/account" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List accounts for RADIUS. 11 | 12 | .DESCRIPTION 13 | List accounts for RADIUS. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteRadiusProfile.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteRadiusProfile { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/rest/radiusprofile" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List profiles for RADIUS. 11 | 12 | .DESCRIPTION 13 | List profiles for RADIUS. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteRouting.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteRouting { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 5 | [switch]$All 6 | ) 7 | if ($All){ 8 | $URI = "$controller/api/s/$name/stat/routing" 9 | } 10 | else { 11 | $URI = "$controller/api/s/$name/rest/routing" 12 | } 13 | 14 | (Invoke-GetRestAPICall $URI).data 15 | <# 16 | .SYNOPSIS 17 | List site routing information. 18 | 19 | .DESCRIPTION 20 | List site routing information. Only user defined routing information is returned by default. 21 | 22 | .PARAMETER Name 23 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 24 | 25 | .PARAMETER All 26 | Switch to include both user defined and default routes. 27 | 28 | .INPUTS 29 | System.String. Can take value from pipeline. 30 | 31 | .OUTPUTS 32 | System.Object. 33 | #> 34 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteSetting.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteSetting { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 5 | [switch]$Raw 6 | ) 7 | $URI = "$controller/api/s/$name/rest/setting" 8 | $Results = (Invoke-GetRestAPICall $URI).data 9 | if ($Raw) { 10 | $Results 11 | } 12 | else { 13 | ConvertTo-UnifiObject -Object $Results -Delimiter "key" -Filter 14 | } 15 | <# 16 | .SYNOPSIS 17 | Lists settings for a site. 18 | 19 | .DESCRIPTION 20 | Lists settings for a site. Not all settings will exist for newly created sites. Settings may only be available if the site 21 | setting in question has been edited and saved in the web UI first. 22 | 23 | .PARAMETER Name 24 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 25 | 26 | .PARAMETER Raw 27 | Indicates if the command should return the raw REST API data. If this switch is ommited, the data will be returned in a more usable format. 28 | 29 | .INPUTS 30 | System.String. Can take value from pipeline. 31 | 32 | .OUTPUTS 33 | System.Object. 34 | #> 35 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteStatistic.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteStatistic { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name, 5 | [Parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $true)][ValidateSet('ap','site','sw', 'gw', IgnoreCase=$false)]$type, 6 | [Parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $true)][ValidateSet('hourly','5minutes','daily')][string]$timescale, 7 | $MAC, 8 | $DateStart, 9 | $DateEnd 10 | ) 11 | $params = @{ 12 | attrs = @( 13 | 'satisfaction', 14 | 'bytes', 15 | 'num_sta', 16 | 'time', 17 | 'tx_packets', 18 | 'rx_packets', 19 | 'wan-tx_packets', 20 | 'wan-rx_packets', 21 | 'lan-tx_packets', 22 | 'lan-rx_packets', 23 | 'lan2-tx_packets', 24 | 'lan2-rx_packets', 25 | 'tx_dropped', 26 | 'rx_dropped', 27 | 'wan-tx_dropped', 28 | 'wan-rx_dropped', 29 | 'lan-tx_dropped', 30 | 'lan-rx_dropped', 31 | 'lan2-tx_dropped', 32 | 'lan2-tx_dropped', 33 | 'wifi_tx_attempts', 34 | 'wifi_tx_dropped', 35 | 'rx_errors', 36 | 'tx_errors', 37 | 'wan-rx_errors', 38 | 'wan-tx_errors', 39 | 'lan-rx_errors', 40 | 'lan-tx_errors', 41 | 'lan2-rx_errors', 42 | 'lan2-tx_errors', 43 | 'tx_retries', 44 | 'rx_frags', 45 | 'rx_crypts', 46 | 'wan-tx_bytes', 47 | 'wan-rx_bytes', 48 | 'lan-rx_bytes', 49 | 'lan-tx_bytes', 50 | 'lan2-rx_bytes', 51 | 'lan2-tx_bytes', 52 | 'wlan_bytes', 53 | 'lan-num_sta', 54 | 'wlan-num_sta', 55 | 'rx_bytes', 56 | 'tx_bytes', 57 | 'mem', 58 | 'cpu', 59 | 'loadavg_5' 60 | ) 61 | n = 1 62 | } 63 | # Use the provided start and end times if provided, if not, generate a date range based on the time scale selected. 64 | if ($PSBoundParameters.ContainsKey('DateStart')){ 65 | $start=Convert-ToUnixDate -LocalDate $DateStart -units Milliseconds 66 | } 67 | else { 68 | switch ($timescale){ 69 | '5minutes' { 70 | $start=Convert-ToUnixDate -LocalDate (Get-Date(Get-Date -Format "MM/dd/yyyy HH:00:00")).addhours(-1) -units Milliseconds 71 | } 72 | 'hourly' { 73 | $start=Convert-ToUnixDate -LocalDate (Get-Date).Date -units Milliseconds 74 | } 75 | 'daily' { 76 | $start=Convert-ToUnixDate -LocalDate ((Get-Date).Date).AddDays(-6) -units Milliseconds 77 | } 78 | } 79 | } 80 | if ($PSBoundParameters.ContainsKey('DateEnd')){ 81 | $end=Convert-ToUnixDate -LocalDate $DateEnd -units Milliseconds 82 | } 83 | else { 84 | switch ($timescale){ 85 | '5minutes' { 86 | $end=Convert-ToUnixDate -LocalDate (Get-Date(Get-Date -Format "MM/dd/yyyy HH:00:00")).AddHours(1) -units Milliseconds 87 | } 88 | 'hourly' { 89 | $end=Convert-ToUnixDate -LocalDate (Get-Date).Date.AddDays(1) -units Milliseconds 90 | } 91 | 'daily' { 92 | $end=Convert-ToUnixDate -LocalDate ((Get-Date).Date).AddDays(1) -units Milliseconds 93 | } 94 | } 95 | } 96 | 97 | # Add the start and end times. 98 | $Params.add('start',$start) 99 | $Params.add('end',$end) 100 | 101 | # Standardize MAC entries and add to params table. 102 | if ($PSBoundParameters.ContainsKey('mac')){ 103 | if ($mac -is [array]){ 104 | # Normalize the mac addresses in the array to colon separated pairs. 105 | for ($i=0; $i -lt $mac.Length; $i++){ 106 | $mac[$i] = $mac[$i] -replace "([0-9a-f]{2})[^0-9a-f]?(?=.)",'$1:' 107 | } 108 | # If $mac is an array, use it as is. 109 | $Params.add('macs',$mac) 110 | } 111 | else { 112 | # If $mac isn't an array, it should be a string. 113 | # Normalize the mac address to colon separated pairs. 114 | $mac = $mac -replace "([0-9a-f]{2})[^0-9a-f]?(?=.)",'$1:' 115 | 116 | # If $mac is a string, turn it into an array. 117 | $Params.add('macs',@($mac)) 118 | } 119 | } 120 | 121 | 122 | $body = New-UnifiCommand $params 123 | $URI = "$controller/api/s/$name/stat/report/$timescale.$type" 124 | write-verbose $uri 125 | 126 | (Invoke-PostRestAPICall $URI -payload $body).data 127 | <# 128 | .SYNOPSIS 129 | Report the statistics. 130 | 131 | .DESCRIPTION 132 | Report the statistics for the specified site. Can show site, AP, gateway or switch data. 133 | 134 | All datapoints are returned. The following is a list of datapoints used for each performance table: 135 | 136 | Description Field 137 | ----------------------------- ---------------- 138 | Avg. WiFi User Experience [%] satisfaction 139 | User Count (Clients) num_sta 140 | LAN User Count (Clients) lan-num_sta 141 | WiFi User Count (Clients) wlan-num_sta 142 | Performance 143 | Memory [%] mem 144 | CPU [%] cpu 145 | 5 minute load average loadavg_5 146 | Traffic 147 | Received [bytes] rx_bytes 148 | Tranmitted [bytes] tx_bytes 149 | Traffic [Gateway] 150 | WAN1 Received [bytes] wan-rx_bytes 151 | WAN1 Transmitted [bytes] wan-tx_bytes 152 | LAN1 Received [bytes] lan-rx_bytes 153 | LAN1 Transmitted [bytes] lan-tx_bytes 154 | LAN2 Received [bytes] lan2-rx_bytes 155 | LAN2 Transmitted [bytes] lan2-tx_bytes 156 | Packets 157 | Received rx_packets 158 | Transmitted tx_packets 159 | Packets [Gateway] 160 | WAN1 Received wan-rx_packets 161 | WAN1 Transmitted wan-tx_packets 162 | LAN1 Received lan-rx_packets 163 | LAN1 Transmitted lan-tx_packets 164 | LAN2 Received lan2-rx_packets 165 | LAN2 Transmitted lan2-tx_packets 166 | Dropped Packets 167 | Received rx_dropped 168 | Transmitted tx_dropped 169 | Dropped Packets [Gateway] 170 | WAN1 Received wan-rx_dropped 171 | WAN1 Transmitted wan-tx_dropped 172 | LAN1 Received lan-rx_dropped 173 | LAN1 Transmitted lan-tx_dropped 174 | LAN2 Received lan2-rx_dropped 175 | LAN2 Transmitted lan2-tx_dropped 176 | WiFi Transmit Attempts wifi_tx_attempts 177 | WiFi Transmit Dropped wifi_tx_dropped 178 | Errors 179 | Receive Errors rx_errors 180 | Transmit Errors tx_errors 181 | Errors [Gateway] 182 | WAN1 Received Errors wan-rx_errors 183 | WAN1 Transmitted Errors wan-tx_errors 184 | LAN1 Received Errors lan-rx_errors 185 | LAN1 Transmitted Errors lan-tx_errors 186 | LAN2 Received Errors lan2-rx_errors 187 | LAN2 Transmitted Errors lan2-tx_errors 188 | Transmit Retries tx_retries 189 | Fragmentation rx_frags 190 | Rx Invalid Crypts rx_crypts 191 | 192 | .PARAMETER Name 193 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 194 | 195 | .PARAMETER type 196 | The type of statistics to obtain--Access Point (ap), Site, Gateway (gw), Switch (sw). 197 | 198 | .PARAMETER timescale 199 | Data interval--daily,hourly,5minutes. 200 | 201 | .PARAMETER MAC 202 | List of MAC addresses to filter upon. Can be a string or array. If ommited, only the first 203 | device of the specified report type will be selected. 204 | 205 | .PARAMETER DateStart 206 | Start time. Default values will be generated based on timescale if ommited. 207 | 208 | .PARAMETER DateEnd 209 | End time. Default values will be generated based on timescale if ommited. 210 | 211 | .INPUTS 212 | System.Object. Can take value from pipeline. 213 | 214 | .OUTPUTS 215 | System.Object. 216 | #> 217 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteSwitchProfile.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-UnifiSiteSwitchProfile { 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 6 | ) 7 | $URI = "$controller/api/s/$name/rest/portconf" 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List profiles for switch ports. 12 | 13 | .DESCRIPTION 14 | List profiles for switch ports. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteSystemInformation.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-UnifiSiteSystemInformation { 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/stat/sysinfo" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | Lists high-level information about the controller and site. 11 | 12 | .DESCRIPTION 13 | Lists high-level information about the controller and site. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } 25 | -------------------------------------------------------------------------------- /Public/Get-UnifiSiteTag.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteTag { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/rest/tag" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List tagged MACs. 11 | 12 | .DESCRIPTION 13 | List tagged MACs. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteWarning.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteWarning { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/stat/widget/warnings" 7 | (Invoke-GetRestAPICall $URI).data 8 | <# 9 | .SYNOPSIS 10 | List site warnings. 11 | 12 | .DESCRIPTION 13 | List site warnings. 14 | 15 | .PARAMETER Name 16 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 17 | 18 | .INPUTS 19 | System.String. Can take value from pipeline. 20 | 21 | .OUTPUTS 22 | System.Object. 23 | #> 24 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteWhoAmI.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteWhoAmI { 2 | param ( 3 | [Parameter(Position=0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 4 | ) 5 | $URI = "$controller/api/s/$name/self" 6 | (Invoke-GetRestAPICall $URI).data 7 | <# 8 | .SYNOPSIS 9 | Returns information about the logged in user. 10 | 11 | .DESCRIPTION 12 | Returns information about the logged in user. 13 | 14 | .PARAMETER Name 15 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 16 | 17 | .INPUTS 18 | System.String. Can take value from pipeline. 19 | 20 | .OUTPUTS 21 | System.Object. 22 | #> 23 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteWirelessNetwork.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Get-UnifiSiteWirelessNetwork { 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$name 6 | ) 7 | $URI = "$controller/api/s/$name/rest/wlanconf" 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List wireless network configuration. 12 | 13 | .DESCRIPTION 14 | List wireless network configuration. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiSiteWirelessRFChannel.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiSiteWirelessRFChannel { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position = 0, ValueFromPipeline = $true)][string]$name 5 | ) 6 | $URI = "$controller/api/s/$name/stat/current-channel" 7 | 8 | (Invoke-GetRestAPICall $URI).data 9 | <# 10 | .SYNOPSIS 11 | List of all RF channels based on the site's country code. 12 | 13 | .DESCRIPTION 14 | List of all RF channels based on the site's country code. 15 | 16 | .PARAMETER Name 17 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 18 | 19 | .INPUTS 20 | System.String. Can take value from pipeline. 21 | 22 | .OUTPUTS 23 | System.Object. 24 | #> 25 | } -------------------------------------------------------------------------------- /Public/Get-UnifiStatus.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiStatus { 2 | [CmdletBinding()] 3 | param() 4 | $URI = "$controller/status" 5 | (Invoke-GetRestAPICall $URI).meta 6 | <# 7 | .SYNOPSIS 8 | Basic controller status. 9 | 10 | .DESCRIPTION 11 | Basic controller status. Data includes request response code, up status, controller version and uuid. 12 | 13 | .INPUTS 14 | None. 15 | 16 | .OUTPUTS 17 | System.Object. 18 | #> 19 | } 20 | -------------------------------------------------------------------------------- /Public/Get-UnifiTimeZone.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiTimeZone { 2 | $URI = "$controller/v2/api/timezones" 3 | (Invoke-GetRestAPICall $URI) 4 | <# 5 | .SYNOPSIS 6 | Returns information about the supported timezones. 7 | 8 | .DESCRIPTION 9 | Returns information about the supported timezones. 10 | 11 | .INPUTS 12 | None. 13 | 14 | .OUTPUTS 15 | System.Object. 16 | #> 17 | } -------------------------------------------------------------------------------- /Public/Get-UnifiWhoAmI.ps1: -------------------------------------------------------------------------------- 1 | function Get-UnifiWhoAmI { 2 | param () 3 | $URI = "$controller/api/self" 4 | (Invoke-GetRestAPICall $URI).data 5 | <# 6 | .SYNOPSIS 7 | Returns information about the logged in user. 8 | 9 | .DESCRIPTION 10 | Returns information about the logged in user. 11 | 12 | .PARAMETER Name 13 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 14 | 15 | .INPUTS 16 | System.String. Can take value from pipeline. 17 | 18 | .OUTPUTS 19 | System.Object. 20 | #> 21 | } -------------------------------------------------------------------------------- /Public/Grant-UnifiSuperAdmin.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Grant-UnifiSuperAdmin { 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$ID 5 | ) 6 | $params = @{ 7 | cmd = "grant-super-admin" 8 | admin = $ID 9 | } 10 | $body = New-UnifiCommand $params 11 | $URI = "$controller/api/s/default/cmd/sitemgr" 12 | $null = Invoke-POSTRestAPICall -url $URI -payload $body 13 | <# 14 | .SYNOPSIS 15 | Grants SuperAdmin role for the specified account id. 16 | 17 | .DESCRIPTION 18 | Grants SuperAdmin role for the specified account id. 19 | 20 | .PARAMETER ID 21 | Account id. This is listed as _id property from the Get-UnifiAdmin command. 22 | 23 | .NOTES 24 | The grant-super-admin command will only function on accounts that show the property 'is_verified' as 'true'. 25 | 26 | .INPUTS 27 | System.String. You can pipe id values into this command. 28 | 29 | .OUTPUTS 30 | None. 31 | #> 32 | } -------------------------------------------------------------------------------- /Public/New-UnifiSiteAdmin.ps1: -------------------------------------------------------------------------------- 1 | function New-UnifiSiteAdmin { 2 | [CmdletBinding(SupportsShouldProcess)] 3 | param( 4 | [Parameter(Mandatory=$true, ParameterSetName="Existing")] 5 | [Parameter(Mandatory=$true, ParameterSetName='SuperAdmin')] 6 | [Parameter(Mandatory=$true, ParameterSetName='Admin')] 7 | [Parameter(Mandatory=$true, ParameterSetName='Email')] 8 | [string]$name, 9 | 10 | [Parameter(Mandatory=$true, ParameterSetName="Existing")] 11 | [string]$ID, 12 | 13 | [Parameter(Mandatory=$true, ParameterSetName='SuperAdmin')] 14 | [Parameter(Mandatory=$true, ParameterSetName='Admin')] 15 | [Parameter(Mandatory=$true, ParameterSetName='Email')] 16 | [ValidateNotNull()] 17 | [System.Management.Automation.PSCredential]$Credentials, 18 | 19 | [Parameter(ParameterSetName='SuperAdmin')] 20 | [Parameter(ParameterSetName='Admin')] 21 | [switch]$ForcePasswordChange, 22 | 23 | [Parameter(Mandatory=$true, ParameterSetName='SuperAdmin')] 24 | [Parameter(Mandatory=$true, ParameterSetName='Admin')] 25 | [Parameter(Mandatory=$true, ParameterSetName='Email')] 26 | [string]$Email, 27 | 28 | [Parameter(Mandatory=$true, ParameterSetName="Existing")] 29 | [Parameter(Mandatory=$true, ParameterSetName='Admin')] 30 | [Parameter(Mandatory=$true, ParameterSetName='Email')] 31 | [ValidateSet('admin','readonly', IgnoreCase=$false)] 32 | [string]$Role, 33 | 34 | [Parameter(Mandatory=$true, ParameterSetName='SuperAdmin')] 35 | [boolean]$SuperAdmin, 36 | 37 | [Parameter(Mandatory=$true, ParameterSetName='Email')] 38 | [Switch]$EmailInvite, 39 | 40 | [Parameter(ParameterSetName='Email')] 41 | [switch]$SSO, 42 | 43 | [Parameter(ParameterSetName="Existing")] 44 | [Parameter(ParameterSetName='Admin')] 45 | [Parameter(ParameterSetName='Email')] 46 | [boolean]$AdoptDevices, 47 | 48 | [Parameter(ParameterSetName="Existing")] 49 | [Parameter(ParameterSetName='Admin')] 50 | [Parameter(ParameterSetName='Email')] 51 | [boolean]$PendingDevices, 52 | 53 | [Parameter(ParameterSetName="Existing")] 54 | [Parameter(ParameterSetName='Admin')] 55 | [Parameter(ParameterSetName='Email')] 56 | [boolean]$DashboardEdit, 57 | 58 | [Parameter(ParameterSetName="Existing")] 59 | [Parameter(ParameterSetName='Admin')] 60 | [Parameter(ParameterSetName='Email')] 61 | [boolean]$SystemStats, 62 | 63 | [Parameter(ParameterSetName="Existing")] 64 | [Parameter(ParameterSetName='Admin')] 65 | [Parameter(ParameterSetName='Email')] 66 | [boolean]$GlobalReadOnly 67 | ) 68 | function GlobalPermissions { 69 | $Permissions = [System.Collections.ArrayList]@() 70 | if ($PendingDevices -eq $true){ 71 | [void]$Permissions.add("API_STAT_DEVICE_ACCESS_SUPER_SITE_PENDING") 72 | } 73 | if ($DashboardEdit -eq $true){ 74 | [void]$Permissions.add("API_DASHBOARD_EDIT") 75 | } 76 | if ($SystemStats -eq $true){ 77 | [void]$Permissions.add("API_WIDGET_OS_STATS") 78 | } 79 | if ($GlobalReadOnly -eq $true){ 80 | [void]$Permissions.add("GLOBAL_READONLY_ADMIN_ACCESS") 81 | } 82 | $Permissions 83 | } 84 | 85 | $URI = "$controller/api/s/$name/cmd/sitemgr" 86 | # Username may only be upper case, lower case, numbers and underscore. Spaces are automatically stripped out as this is 87 | # the most likely error to be present. 88 | if ($Credentials){ 89 | [ValidatePattern("^[a-zA-Z0-9_]*$")][string]$Username=($Credentials.GetNetworkCredential().UserName).replace(' ','') 90 | [string]$Password=$Credentials.GetNetworkCredential().Password 91 | } 92 | 93 | 94 | $GlobalPermissions=GlobalPermissions 95 | write-verbose $GlobalPermissions.count 96 | 97 | 98 | if ($AdoptDevices -eq $true){ 99 | $SitePermissions = @('API_DEVICE_ADOPT') 100 | } 101 | else { 102 | $SitePermissions = @() 103 | } 104 | 105 | 106 | switch ($PsCmdlet.ParameterSetName){ 107 | {'Admin' -or 'SuperAdmin'} { 108 | write-verbose "ParameterSet $_ was used." 109 | # Set ParameterSet specific options. 110 | if ($ForcePasswordChange){ 111 | $PasswordChange=$true 112 | } 113 | else { 114 | $PasswordChange=$false 115 | } 116 | # The administrator role will always be 'readonly' when creating a SuperAdmin. 117 | if ($SuperAdmin -eq $true){ 118 | $Role = 'readonly' 119 | } 120 | #Create Admin 121 | $Params=@{ 122 | cmd = 'create-admin' 123 | email = $Email 124 | name = $Username 125 | requires_new_password = $PasswordChange 126 | role = $Role 127 | x_password = $Password 128 | permissions = $SitePermissions 129 | } 130 | $target=$username 131 | $command='create-admin' 132 | 133 | } 134 | 'Email' { 135 | write-verbose "ParameterSet $_ was used." 136 | if ($SSO){ 137 | $ForSSO = $true 138 | } 139 | else { 140 | $ForSSO = $false 141 | } 142 | 143 | $Params=@{ 144 | cmd = 'invite-admin' 145 | email = $Email 146 | for_sso = $ForSSO 147 | name = $Username 148 | role = $Role 149 | permissions = $SitePermissions 150 | super_site_permissions = $GlobalPermissions 151 | } 152 | $target=$username 153 | $command='invite-admin' 154 | } 155 | 'Existing' { 156 | write-verbose "ParameterSet $_ was used." 157 | $Params=@{ 158 | cmd = 'grant-admin' 159 | admin = $ID 160 | role = $Role 161 | permissions = $SitePermissions 162 | } 163 | $target=$ID 164 | $command='grant-admin' 165 | } 166 | default { 167 | write-verbose "No ParameterSet used. $_" 168 | } 169 | } 170 | 171 | # admin command 172 | $body = New-UnifiCommand $params 173 | write-verbose "Command parameters for admin role:" 174 | write-verbose $body 175 | 176 | if ($PSCmdlet.ShouldProcess($target,$command)){ 177 | $Response=Invoke-POSTRestAPICall -url $URI -payload $body 178 | } 179 | 180 | #Superadmin command -- The superadmin permissions are already part of the invite-admin command. 181 | if (($GlobalPermissions.count -ge 1) -AND ($PsCmdlet.ParameterSetName -ne 'Email')){ 182 | if ([string]::IsNullOrEmpty($ID)){ 183 | write-verbose "No admin ID found. Using value from previous controller response." 184 | $ID=$Response.data._id 185 | } 186 | $SuperParams=@{ 187 | cmd = 'grant-super-admin' 188 | admin = $ID 189 | role = 'nobody' 190 | permissions = $GlobalPermissions 191 | } 192 | $body = New-UnifiCommand $SuperParams 193 | write-verbose "Command parameters for superadmin role:" 194 | write-verbose $body 195 | if ($PSCmdlet.ShouldProcess($target,'grant-super-admin')){ 196 | $SAResponse=Invoke-POSTRestAPICall -url $URI -payload $body 197 | } 198 | } 199 | 200 | 201 | <# 202 | .SYNOPSIS 203 | Creates a new site administrator. 204 | 205 | .DESCRIPTION 206 | Creates a new site administrator. 207 | 208 | .PARAMETER Name 209 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 210 | 211 | .PARAMETER Credentials 212 | A PSCrendentials object containing the username and password. The password needs to be in plain text. 213 | 214 | .PARAMETER Email 215 | Email address for the new admin user. 216 | 217 | .PARAMETER Role 218 | Specify if the new account will be an 'admin' or 'readonly' account. 219 | 220 | .PARAMETER EmailInvite 221 | Specify that this user should be sent an email invite to manage the site rather than creating the credentials manually. 222 | 223 | .PARAMETER SSO 224 | Switch to specify that this account will have remote access through a Unifi SSO account. Without this switch, direct access to the controller will be needed. 225 | 226 | .PARAMETER SuperAdmin 227 | Specify that this account will be a SuperAdmin with access to all sites rather than limited to the site specified. 228 | 229 | .PARAMETER ForcePasswordChange 230 | Prompts for a new password upon initial logon. 231 | 232 | .PARAMETER AdoptDevices 233 | Allows for device adoptions. 234 | 235 | .PARAMETER PendingDevices 236 | Allows for viewing of pending devices. 237 | 238 | .PARAMETER DashboardEdit 239 | Allows for editing dashboard. 240 | 241 | .PARAMETER SystemStats 242 | Allows for viewing system statistics. 243 | 244 | .PARAMETER GlobalReadOnly 245 | Assigns readonly rights for all other sites. 246 | 247 | 248 | .INPUTS 249 | None. 250 | 251 | .OUTPUTS 252 | System.Object 253 | #> 254 | } 255 | -------------------------------------------------------------------------------- /Public/New-UnifiSiteFirewallRule.ps1: -------------------------------------------------------------------------------- 1 | function New-UnifiSiteFirewallRule { 2 | [CmdletBinding(SupportsShouldProcess)] 3 | param( 4 | [string]$RuleSet, 5 | [int]$RuleIndex, 6 | [string]$RuleName, 7 | [boolean]$Enabled, 8 | [ValidateSet('drop','reject','accept', IgnoreCase=$false)] 9 | [string]$Action, 10 | [boolean]$ProtocalMatchExcepted, 11 | [boolean]$Logging, 12 | [boolean]$StateNew, 13 | [boolean]$StateEstablished, 14 | [boolean]$StateInvalid, 15 | [boolean]$StateRelated, 16 | [string]$IpSec, 17 | [array]$SourceFirewallGroupIds, 18 | [string]$SourceMacAddress, 19 | [array]$DestinationFirewallGroupIds, 20 | [string]$DestinationAddress, 21 | [string]$SourceAddress, 22 | [string]$Protocol, 23 | [string]$IcmpTypeName, 24 | [string]$SourceNetworkConfigurationId, 25 | [string]$SourceNetworkConfigurationType, 26 | [string]$DestinationNetworkConfigurationId, 27 | [string]$DestinationNetworkConfigurationType 28 | ) 29 | Register-ArgumentCompleter -CommandName 'New-UnifiSiteFirewallRule' -ParameterName 'ProtocalMatchExcepted' -ScriptBlock { 30 | [System.Management.Automation.CompletionResult]::new( 31 | '$False', 32 | '$False', 33 | 'ParameterValue', 34 | '[bool] False' 35 | ) 36 | [System.Management.Automation.CompletionResult]::new( 37 | '$True', 38 | '$True', 39 | 'ParameterValue', 40 | '[bool] True' 41 | ) 42 | } 43 | } 44 | 45 | New-UnifiSiteFirewallRule -ProtocalMatchExcepted -------------------------------------------------------------------------------- /Public/Remove-UnifiAdmin.ps1: -------------------------------------------------------------------------------- 1 | function Remove-UnifiAdmin { 2 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] 3 | param( 4 | [Parameter(Position = 1, Mandatory = $true)][string]$ID, 5 | [switch]$force 6 | ) 7 | # Make sure the specified ID actually exists. 8 | write-verbose "Looking up admin account information for admin $id." 9 | $AccountInfo=get-unifiadmin | where-object {$_._id -eq $ID} 10 | if ($null -eq $AccountInfo){ 11 | Write-Error -Message "Specified account id not found." -ErrorAction Stop 12 | } 13 | else { 14 | write-verbose "Found account for admin user $($AccountInfo.name)." 15 | } 16 | if ($AccountInfo.is_super -eq $true) { 17 | if (!$force){ 18 | write-error "Specified account is a super-admin. Aborting removal. Use '-force' to remove super-admin accounts." -ErrorAction Stop 19 | } 20 | } 21 | if ($force){ 22 | $ConfirmPreference='None' 23 | } 24 | if ($confirm){ 25 | $ConfirmPreference='High' 26 | } 27 | if ($PSCmdlet.ShouldProcess($AccountInfo.name,"Remove-UnifiSiteAdmin")){ 28 | if ($AccountInfo.is_super -eq $true){ 29 | write-verbose "Revoking super_admin privileges." 30 | Revoke-UnifiSuperAdmin -ID $ID 31 | } 32 | $ResponseDetails = [System.Collections.Generic.List[psobject]]::new() 33 | $params = @{ 34 | cmd = "revoke-admin" 35 | admin = $ID 36 | } 37 | $body = New-UnifiCommand $params 38 | foreach ($site in ($AccountInfo.roles | sort-object -property "site_desc")){ 39 | $URI = "$controller/api/s/$($site.site_name)/cmd/sitemgr" 40 | write-verbose "Removing account $($AccountInfo.name) from $($site.site_desc)." 41 | $Response=Invoke-POSTRestAPICall -url $URI -payload $body 42 | $ResponseDetails.Add( 43 | [PSCustomObject]@{ 44 | AccountID = $ID 45 | AccountName = $AccountInfo.name 46 | SiteName = $site.site_name 47 | SiteDescription = $site.site_desc 48 | Results = $Response.meta.rc 49 | } 50 | ) 51 | 52 | } 53 | # Refresh the account information. 54 | $AccountInfo=get-unifiadmin | where-object {$_._id -eq $ID} 55 | if ($null -ne $AccountInfo){ 56 | if ($accountinfo.roles.count -eq 0){ 57 | $ResponseDetails 58 | Write-Error "Ghost account detected. Please assign SuperAdmin rights to this account, then attempt removal again." -ErrorAction Stop 59 | } 60 | else { 61 | $ResponseDetails 62 | Write-Error "Some site permissions still exist for this account." -ErrorAction Continue 63 | } 64 | } 65 | else { 66 | $ResponseDetails 67 | } 68 | } 69 | <# 70 | .SYNOPSIS 71 | Remove the administrator account specified. 72 | 73 | .DESCRIPTION 74 | Remove the administrator account specified. This will automatically remove the account from any assigned sites. Output will 75 | contain a object with site specific of response details. Use '-force' to remove accounts which have the SuperAdmin role. 76 | 77 | .PARAMETER ID 78 | Account id. This is listed as _id property from the Get-UnifiAdmin command. 79 | 80 | .PARAMETER Force 81 | Force removal of SuperAdmin accounts. 82 | 83 | .NOTES 84 | On occasion, it is possible to have an admin account assigned to no sites. If this happens, granting the SuperAdmin role to the account 85 | and removing the account again should fix it. 86 | 87 | .INPUTS 88 | None. 89 | 90 | .OUTPUTS 91 | System.Object 92 | #> 93 | } -------------------------------------------------------------------------------- /Public/Remove-UnifiSiteAdmin.ps1: -------------------------------------------------------------------------------- 1 | function Remove-UnifiSiteAdmin { 2 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName='Default')] 5 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName='Others')] 6 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName='All')] 7 | [string]$name, 8 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName='Default')] 9 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName='Others')] 10 | [Parameter(Position = 1, Mandatory = $false, ParameterSetName='All')] 11 | [string]$ID, 12 | [Parameter(Mandatory = $true, ParameterSetName='Others')][Switch]$Others, 13 | [Parameter(Mandatory = $true, ParameterSetName='All')][Switch]$All, 14 | [Parameter(ParameterSetName='Default')] 15 | [Parameter(ParameterSetName='Others')] 16 | [Parameter(ParameterSetName='All')][switch]$Force 17 | ) 18 | # Make sure the specified ID actually exists. 19 | write-verbose "Looking up admin account information for admin $id." 20 | #$AccountInfo=get-unifiadmin | where-object {$_._id -eq $ID} 21 | $AccountInfo=Get-UnifiSiteAdmin -name $name | where-object {$_._id -eq $ID} 22 | if ($null -eq $AccountInfo){ 23 | Write-Error -Message "Specified account id not found." -ErrorAction Stop 24 | } 25 | else { 26 | write-verbose "Found account for admin user $($AccountInfo.name)." 27 | } 28 | if ($AccountInfo.is_super -eq $true) { 29 | if (!$force){ 30 | write-error "Specified account is a super-admin. Aborting removal. Use '-force' to remove super-admin accounts." -ErrorAction Stop 31 | } 32 | } 33 | 34 | 35 | if ($force){ 36 | $ConfirmPreference='None' 37 | } 38 | if ($confirm){ 39 | $ConfirmPreference='High' 40 | } 41 | if ($PSCmdlet.ShouldProcess($AccountInfo.name,"Remove-UnifiSiteAdmin")){ 42 | if ($AccountInfo.is_super -eq $true){ 43 | write-verbose "Revoking super_admin privileges." 44 | Revoke-UnifiSuperAdmin -ID $ID 45 | } 46 | if ($all){ 47 | $AccountInfo=get-unifiadmin | where-object {$_._id -eq $ID} 48 | $ResponseDetails = [System.Collections.Generic.List[psobject]]::new() 49 | $params = @{ 50 | cmd = "revoke-admin" 51 | admin = $ID 52 | } 53 | $body = New-UnifiCommand $params 54 | foreach ($site in ($AccountInfo.roles | sort-object -property "site_desc")){ 55 | $URI = "$controller/api/s/$($site.site_name)/cmd/sitemgr" 56 | write-verbose "Removing account $($AccountInfo.name) from $($site.site_desc)." 57 | $Response=Invoke-POSTRestAPICall -url $URI -payload $body 58 | $ResponseDetails.Add( 59 | [PSCustomObject]@{ 60 | AccountID = $ID 61 | AccountName = $AccountInfo.name 62 | SiteName = $site.site_name 63 | SiteDescription = $site.site_desc 64 | Results = $Response.meta.rc 65 | } 66 | ) 67 | 68 | } 69 | $ResponseDetails 70 | } 71 | if ($Others){ 72 | $AccountInfo=get-unifiadmin | where-object {$_._id -eq $ID} 73 | $ResponseDetails = [System.Collections.Generic.List[psobject]]::new() 74 | $params = @{ 75 | cmd = "revoke-admin" 76 | admin = $ID 77 | } 78 | $body = New-UnifiCommand $params 79 | foreach ($site in ($AccountInfo.roles | sort-object -property "site_desc")){ 80 | if ($site.site_name -eq $name){ 81 | $ResponseDetails.Add( 82 | [PSCustomObject]@{ 83 | AccountID = $ID 84 | AccountName = $AccountInfo.name 85 | SiteName = $site.site_name 86 | SiteDescription = $site.site_desc 87 | Results = "skipped" 88 | } 89 | ) 90 | } 91 | else { 92 | $URI = "$controller/api/s/$($site.site_name)/cmd/sitemgr" 93 | write-verbose "Removing account $($AccountInfo.name) from $($site.site_desc)." 94 | $Response=Invoke-POSTRestAPICall -url $URI -payload $body 95 | $ResponseDetails.Add( 96 | [PSCustomObject]@{ 97 | AccountID = $ID 98 | AccountName = $AccountInfo.name 99 | SiteName = $site.site_name 100 | SiteDescription = $site.site_desc 101 | Results = $Response.meta.rc 102 | } 103 | ) 104 | } 105 | 106 | 107 | } 108 | $ResponseDetails 109 | } 110 | if (!$All -or !$Others){ 111 | $ResponseDetails = [System.Collections.Generic.List[psobject]]::new() 112 | $params = @{ 113 | cmd = "revoke-admin" 114 | admin = $ID 115 | } 116 | $body = New-UnifiCommand $params 117 | $URI = "$controller/api/s/$name/cmd/sitemgr" 118 | $site=Get-UnifiSite | where-object {$_.name -eq $name} 119 | write-verbose "Removing account $($AccountInfo.name) from $($site.desc)." 120 | $Response=Invoke-POSTRestAPICall -url $URI -payload $body 121 | $ResponseDetails.Add( 122 | [PSCustomObject]@{ 123 | AccountID = $ID 124 | AccountName = $AccountInfo.name 125 | SiteName = $site.name 126 | SiteDescription = $site.desc 127 | Results = $Response.meta.rc 128 | } 129 | ) 130 | } 131 | $ResponseDetails 132 | } 133 | 134 | #Remove superadmin role if 135 | # $params = @{ 136 | # cmd = "revoke-super-admin" 137 | # admin = $ID 138 | # } 139 | # $body = New-UnifiCommand $params 140 | # $URI = "$controller/api/s/default/cmd/sitemgr" 141 | 142 | # $null = Invoke-POSTRestAPICall -url $URI -payload $body 143 | <# 144 | .SYNOPSIS 145 | Remove the administrator account specified. 146 | 147 | .DESCRIPTION 148 | Remove the administrator account specified. Optionally, can remove it from all sites, or only other sites. 149 | When switch -all or -others are specified, output will contain a object with site specific of response details. 150 | 151 | .PARAMETER Name 152 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 153 | 154 | .PARAMETER ID 155 | Account id. This is listed as _id property from the Get-UnifiSiteAdmin command. 156 | 157 | .PARAMETER Others 158 | Remove the administrator account from all other sites except the one specified. When this command is specified, output will contain a object with site specific of response details. 159 | 160 | .PARAMETER All 161 | Remove the administrator account from all sites. When this command is specified, output will contain a object with site specific of response details. 162 | 163 | .INPUTS 164 | None. 165 | 166 | .OUTPUTS 167 | System.Object 168 | #> 169 | } -------------------------------------------------------------------------------- /Public/Revoke-UnifiSuperAdmin.ps1: -------------------------------------------------------------------------------- 1 | function Revoke-UnifiSuperAdmin { 2 | param ( 3 | [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][string]$ID 4 | ) 5 | $params = @{ 6 | cmd = "revoke-super-admin" 7 | admin = $ID 8 | } 9 | $body = New-UnifiCommand $params 10 | $URI = "$controller/api/s/default/cmd/sitemgr" 11 | $null = Invoke-POSTRestAPICall -url $URI -payload $body 12 | <# 13 | .SYNOPSIS 14 | Revokes SuperAdmin role for the specified account id. 15 | 16 | .DESCRIPTION 17 | Revokes SuperAdmin role for the specified account id. 18 | 19 | .PARAMETER ID 20 | Account id. This is listed as _id property from the Get-UnifiAdmin command. 21 | 22 | .INPUTS 23 | System.String. You can pipe id values into this command. 24 | 25 | .OUTPUTS 26 | None. 27 | #> 28 | } -------------------------------------------------------------------------------- /Public/Set-UnifiSiteAdmin.ps1: -------------------------------------------------------------------------------- 1 | # {"cmd":"update-admin","admin":"6047ea436f6bb00c641fe5c2","name":"TestAdmin7","email":"mmccool7@tmgit.com","email_alert_enabled":false,"email_alert_grouping_enabled":false,"email_alert_grouping_delay":60,"push_alert_enabled":true} 2 | # {"cmd":"set-admin-permissions","admin":"6047ea436f6bb00c641fe5c2","permissions":["API_DEVICE_ADOPT"]} 3 | # {"cmd":"grant-super-admin","admin":"6047ea436f6bb00c641fe5c2","role":"nobody","permissions":["API_STAT_DEVICE_ACCESS_SUPER_SITE_PENDING","API_WIDGET_OS_STATS","API_DASHBOARD_EDIT","GLOBAL_READONLY_ADMIN_ACCESS"]} 4 | 5 | 6 | #{"cmd":"update-admin","admin":"6047ea436f6bb00c641fe5c2","name":"TestAdmin99","x_password":"kljlkjekrjklejfi9oj39nfnvlnkljfdf","email":"mmccool99@tmgit.com","email_alert_enabled":false,"email_alert_grouping_enabled":false,"email_alert_grouping_delay":60,"push_alert_enabled":false} 7 | function Set-UnifiSiteAdmin { 8 | [CmdletBinding(SupportsShouldProcess)] 9 | param( 10 | [Parameter(Mandatory=$true)] 11 | [string]$name, # site name 12 | [Parameter(Mandatory=$true)] 13 | [string]$ID, #acount id 14 | [string]$Username, 15 | [securestring]$Password, 16 | [string]$Email, 17 | [ValidateSet('admin','readonly', IgnoreCase=$false)] 18 | [string]$Role, 19 | [boolean]$EmailAlert, 20 | [boolean]$AlertGrouping, 21 | [int]$GroupingDelay, 22 | [boolean]$PushAlert, 23 | [boolean]$SuperAdmin, 24 | [boolean]$AdoptDevices, 25 | [boolean]$PendingDevices, 26 | [boolean]$DashboardEdit, 27 | [boolean]$SystemStats, 28 | [boolean]$GlobalReadOnly 29 | ) 30 | # @{cmd ="update-admin" 31 | # admin = $ID 32 | # name = $Username 33 | # email = $email 34 | # email_alert_enabled = $EmailAlert 35 | # email_alert_grouping_enabled = $AlertGrouping 36 | # email_alert_grouping_delay = $GroupingDelay 37 | # push_alert_enabled = "" 38 | # } 39 | $URI = "$controller/api/s/$name/cmd/sitemgr" 40 | write-verbose $PSBoundParameters.Keys 41 | $admin = Get-UnifiSiteAdmin -name $name | where-object {$_._id -eq $ID} 42 | if ($null -eq $admin){ 43 | write-error "Specified ID not found." 44 | } 45 | write-verbose $admin 46 | if ($PSBoundParameters.ContainsKey('Username')){ 47 | $Admin.name = $Username 48 | } 49 | if ($PSBoundParameters.ContainsKey('Email')){ 50 | $Admin.email = $Email 51 | } 52 | if ($PSBoundParameters.ContainsKey('Role')){ 53 | $Admin.role = $Role 54 | } 55 | if ($PSBoundParameters.ContainsKey('EmailAlert')){ 56 | $Admin.email_alert_enabled = $EmailAlert 57 | } 58 | if ($PSBoundParameters.ContainsKey('AlertGrouping')){ 59 | $Admin.email_alert_grouping_enabled = $AlertGrouping 60 | } 61 | if ($PSBoundParameters.ContainsKey('GroupingDelay')){ 62 | $Admin.email_alert_grouping_delay = $GroupingDelay 63 | } 64 | if ($PSBoundParameters.ContainsKey('PushAlert')){ 65 | $Admin.push_alert_enabled = $PushAlert 66 | } 67 | 68 | #{"cmd":"update-admin", 69 | # "admin":"6047ea436f6bb00c641fe5c2", 70 | # "name":"TestAdmin7", 71 | # "email":"mmccool7@tmgit.com", 72 | # "email_alert_enabled":false, 73 | # "email_alert_grouping_enabled":false, 74 | # "email_alert_grouping_delay":60, 75 | # "push_alert_enabled":true} 76 | 77 | #Update Admin 78 | $UpdateAdmin=@{ 79 | cmd = 'update-admin' 80 | admin = $admin._id 81 | name = $admin.name 82 | email = $admin.email 83 | email_alert_enabled = $admin.email_alert_enabled 84 | email_alert_grouping_enabled = $admin.email_alert_grouping_enabled 85 | email_alert_grouping_delay = $admin.email_alert_grouping_delay 86 | push_alert_enabled = $admin.push_alert_enabled 87 | } 88 | if ($PSBoundParameters.ContainsKey('Password')){ 89 | #Creating a dummy PSCredentials object just so we can safely use the password securestring. 90 | [pscredential]$DummyCredential=New-Object System.Management.Automation.PSCredential ('Dummy', $Password) 91 | $UpdateAdmin | Add-Member -MemberType NoteProperty -Name 'x_password' -Value $DummyCredential.GetNetworkCredential().password 92 | } 93 | 94 | # Update Admin command 95 | $body = New-UnifiCommand $UpdateAdmin 96 | write-verbose $body 97 | if ($PSCmdlet.ShouldProcess($admin.name,'update-admin')){ 98 | $UpdateResponse=Invoke-POSTRestAPICall -url $URI -payload $body 99 | } 100 | 101 | #{"cmd":"update-admin", 102 | # "admin":"6047ea436f6bb00c641fe5c2", 103 | # "name":"TestAdmin99", 104 | # "x_password":"kljlkjekrjklejfi9oj39nfnvlnkljfdf", 105 | # "email":"mmccool99@tmgit.com", 106 | # "email_alert_enabled":false, 107 | # "email_alert_grouping_enabled":false, 108 | # "email_alert_grouping_delay":60, 109 | # "push_alert_enabled":false} 110 | 111 | 112 | 113 | # Create arraylist of current permissions 114 | $SitePermissions= new-object system.collections.arraylist($null) 115 | if ($null -ne $admin.permissions){ 116 | $SitePermissions.addRange($admin.permissions) 117 | } 118 | # if specified, update the permissions list. 119 | if ($PSBoundParameters.ContainsKey('AdoptDevices')){ 120 | if (($AdoptDevices -eq $true) -AND ($SitePermissions -notcontains "API_DEVICE_ADOPT")){ 121 | [void]$SitePermissions.add("API_DEVICE_ADOPT") 122 | } 123 | if ($AdoptDevices -eq $false){ 124 | [void]$SitePermissions.Remove("API_DEVICE_ADOPT") 125 | } 126 | } 127 | #{"cmd":"set-admin-permissions","admin":"6047ea436f6bb00c641fe5c2","permissions":["API_DEVICE_ADOPT"]} 128 | # Create the command to send to the unifi controller. 129 | if ($admin.is_super -eq $false){ 130 | $SetAdminPermissions=@{ 131 | cmd = 'set-admin-permissions' 132 | admin = $admin._id 133 | permissions = $SitePermissions.ToArray() 134 | } 135 | $body = New-UnifiCommand $SetAdminPermissions 136 | write-verbose $body 137 | if ($PSCmdlet.ShouldProcess($admin.name,'set-admin-permissions')){ 138 | $AdminPermissionsResponse=Invoke-POSTRestAPICall -url $URI -payload $body 139 | } 140 | 141 | # Add any missing value needed in order to set the super admin permissions. 142 | if (($admin | get-member -type "NoteProperty").name -notcontains "super_site_role"){ 143 | $admin | Add-Member -MemberType NoteProperty -name "super_site_role" -value "nobody" 144 | } 145 | } 146 | # Now work on the superadmin permissions 147 | 148 | # Create arraylist of current permissions 149 | $SuperPermissions= new-object system.collections.arraylist($null) 150 | if ($null -ne $admin.super_site_permissions){ 151 | $SuperPermissions.addRange($admin.super_site_permissions) 152 | } 153 | # if specified, update the permissions list. 154 | if ($PSBoundParameters.ContainsKey('PendingDevices')){ 155 | $key='API_STAT_DEVICE_ACCESS_SUPER_SITE_PENDING' 156 | if (($PendingDevices -eq $true) -AND ($SuperPermissions -notcontains $key)){ 157 | [void]$SuperPermissions.add($key) 158 | } 159 | if ($PendingDevices -eq $false){ 160 | [void]$SuperPermissions.Remove($key) 161 | } 162 | } 163 | if ($PSBoundParameters.ContainsKey('DashboardEdit')){ 164 | $key='API_DASHBOARD_EDIT' 165 | if (($DashboardEdit -eq $true) -AND ($SuperPermissions -notcontains $key)){ 166 | [void]$SuperPermissions.add($key) 167 | } 168 | if ($DashboardEdit -eq $false){ 169 | [void]$SuperPermissions.Remove($key) 170 | } 171 | } 172 | if ($PSBoundParameters.ContainsKey('SystemStats')){ 173 | $key='API_WIDGET_OS_STATS' 174 | if (($SystemStats -eq $true) -AND ($SuperPermissions -notcontains $key)){ 175 | [void]$SuperPermissions.add($key) 176 | } 177 | if ($SystemStats -eq $false){ 178 | [void]$SuperPermissions.Remove($key) 179 | } 180 | } 181 | if ($PSBoundParameters.ContainsKey('GlobalReadOnly')){ 182 | $key='GLOBAL_READONLY_ADMIN_ACCESS' 183 | if (($GlobalReadOnly -eq $true) -AND ($SuperPermissions -notcontains $key)){ 184 | [void]$SuperPermissions.add($key) 185 | } 186 | if ($GlobalReadOnly -eq $false){ 187 | [void]$SuperPermissions.Remove($key) 188 | } 189 | } 190 | if ($PSBoundParameters.ContainsKey('SuperAdmin')){ 191 | if ($SuperAdmin -eq $true){ 192 | # $admin.super_site_role = 'admin' 193 | # $SuperPermissions=new-object system.collections.arraylist($null) 194 | Grant-UnifiSuperAdmin -ID $admin._id 195 | $admin.is_super=$true 196 | } 197 | if ($SuperAdmin -eq $false){ 198 | Revoke-UnifiSuperAdmin -ID $admin._id 199 | $admin.super_site_role = 'nobody' 200 | $admin.is_super=$false 201 | } 202 | } 203 | if ($admin.is_super -eq $false){ 204 | $SetSuperAdminPermissions=@{ 205 | cmd = 'grant-super-admin' 206 | admin = $admin._id 207 | role = $admin.super_site_role 208 | permissions = $SuperPermissions.ToArray() 209 | } 210 | $body = New-UnifiCommand $SetSuperAdminPermissions 211 | write-verbose $body 212 | if ($PSCmdlet.ShouldProcess($admin.name,'grant-super-admin')){ 213 | $UpdateSAPermissionsResponse=Invoke-POSTRestAPICall -url $URI -payload $body 214 | } 215 | } 216 | 217 | # {"cmd":"grant-super-admin", 218 | # "admin":"6047ea436f6bb00c641fe5c2", 219 | # "role":"nobody", 220 | # "permissions":[ 221 | # "API_STAT_DEVICE_ACCESS_SUPER_SITE_PENDING", 222 | # "API_WIDGET_OS_STATS", 223 | # "API_DASHBOARD_EDIT", 224 | # "GLOBAL_READONLY_ADMIN_ACCESS"]} 225 | 226 | 227 | 228 | 229 | <# 230 | .SYNOPSIS 231 | Updates settings for a site administrator. 232 | 233 | .DESCRIPTION 234 | Updates settings for a site administrator. This command will update any supplied settings for the specified administrator. 235 | 236 | .PARAMETER Name 237 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 238 | 239 | .PARAMETER ID 240 | Unique id value for the administrator account. This value is listed as _id value in the Get-UnifiSiteAdmin command. 241 | 242 | .PARAMETER Username 243 | Name for the specified admin. 244 | 245 | .PARAMETER Password 246 | SecureString value for a new password for the specified account. This is for local accounts only. 247 | 248 | .PARAMETER Email 249 | Email address for the admin user. 250 | 251 | .PARAMETER Role 252 | Specify if the account will be an 'admin' or 'readonly' account. 253 | 254 | .PARAMETER EmailInvite 255 | Switch to specify that this user should be sent an email invite to manage the site rather than creating the credentials manually. 256 | 257 | .PARAMETER SSO 258 | Switch to specify that this account will have remote access through a Unifi SSO account. Without this switch, direct access to the controller will be needed. 259 | 260 | .PARAMETER SuperAdmin 261 | Switch to specify that this account will be a SuperAdmin with access to all sites rather than limited to the site specified. 262 | 263 | .PARAMETER ForcePasswordChange 264 | Prompts for a new password upon initial logon. 265 | 266 | .PARAMETER AdoptDevices 267 | Allows for device adoptions. 268 | 269 | .PARAMETER PendingDevices 270 | Allows for viewing of pending devices. 271 | 272 | .PARAMETER DashboardEdit 273 | Allows for editing dashboard. 274 | 275 | .PARAMETER SystemStats 276 | Allows for viewing system statistics. 277 | 278 | .PARAMETER GlobalReadOnly 279 | Assigns readonly rights for all other sites. 280 | 281 | 282 | .INPUTS 283 | None. 284 | 285 | .OUTPUTS 286 | System.Object 287 | #> 288 | } -------------------------------------------------------------------------------- /Public/Set-UnifiSiteDevice.ps1: -------------------------------------------------------------------------------- 1 | function Set-UnifiSiteDevice { 2 | [CmdletBinding(SupportsShouldProcess)] 3 | param ( 4 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Adopt")] 5 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Restart")] 6 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Provision")] 7 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="PowerCycle")] 8 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="SpeedTest")] 9 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Locate")] 10 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Upgrade")] 11 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Migrate")] 12 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="Scan")] 13 | [string]$name, 14 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Adopt")] 15 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Restart")] 16 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Provision")] 17 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="PowerCycle")] 18 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Locate")] 19 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Upgrade")] 20 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Migrate")] 21 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="Scan")] 22 | [string]$mac, 23 | [Parameter(ParameterSetName="Adopt", Mandatory = $true)][switch]$Adopt, 24 | [Parameter(ParameterSetName="Restart", Mandatory = $true)][switch]$Restart, 25 | [Parameter(ParameterSetName="Provision", Mandatory = $true)][switch]$Provision, 26 | [Parameter(ParameterSetName="PowerCycle", Mandatory = $true)][switch]$PowerCycle, 27 | [Parameter(ParameterSetName="PowerCycle", Mandatory = $true)][int]$Port, 28 | [Parameter(ParameterSetName="SpeedTest", Mandatory = $true)][switch]$SpeedTest, 29 | [Parameter(ParameterSetName="SpeedTest")][switch]$Status, 30 | [Parameter(ParameterSetName="Locate", Mandatory = $true)][Boolean]$Locate, 31 | [Parameter(ParameterSetName="Upgrade", Mandatory = $true)][switch]$Upgrade, 32 | [Parameter(ParameterSetName="Upgrade")] 33 | [Parameter(ParameterSetName="Migrate", Mandatory = $true)][string]$URL, 34 | [Parameter(ParameterSetName="Migrate", Mandatory = $true)][Boolean]$migrate, 35 | [Parameter(ParameterSetName="Scan", Mandatory = $true)] 36 | [switch]$Scan 37 | ) 38 | 39 | $URI="$controller/api/s/$name/cmd/devmgr" 40 | 41 | # Get the detailed device information for this device. 42 | if ($PsCmdlet.ParameterSetName -ne 'SpeedTest'){ 43 | # Normalize the Mac address 44 | $mac = $mac -replace "([0-9a-f]{2})[^0-9a-f]?(?=.)",'$1:' 45 | 46 | $Device=Get-UnifiSiteDevice -name $name -Detailed -mac $mac 47 | } 48 | 49 | switch ($PsCmdlet.ParameterSetName) { 50 | 'Adopt' { 51 | write-verbose $_ 52 | $params = @{ 53 | cmd = "adopt" 54 | mac = $mac 55 | } 56 | $body = New-UnifiCommand $params 57 | write-verbose $body 58 | if ($PSCmdlet.ShouldProcess($mac,'Adopt')){ 59 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 60 | } 61 | } 62 | 'Restart' { 63 | write-verbose $_ 64 | $params = @{ 65 | cmd = "restart" 66 | mac = $mac 67 | } 68 | $body = New-UnifiCommand $params 69 | write-verbose $body 70 | if ($PSCmdlet.ShouldProcess($mac,'Restart')){ 71 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 72 | } 73 | } 74 | 'Provision' { 75 | write-verbose $_ 76 | $params = @{ 77 | cmd = "force-provision" 78 | mac = $mac 79 | } 80 | $body = New-UnifiCommand $params 81 | write-verbose $body 82 | if ($PSCmdlet.ShouldProcess($mac,'Provision')){ 83 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 84 | } 85 | } 86 | 'PowerCycle' { 87 | write-verbose $_ 88 | if ($device.type -eq 'usw'){ 89 | $params = @{ 90 | cmd = "power-cycle" 91 | mac = $mac 92 | port_idx = $Port 93 | } 94 | $body = New-UnifiCommand $params 95 | write-verbose $body 96 | if ($PSCmdlet.ShouldProcess($mac,'Power cycle')){ 97 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 98 | 99 | } 100 | } 101 | else { 102 | write-host "Device $mac is not a switch." 103 | } 104 | 105 | } 106 | 'SpeedTest' { 107 | write-verbose $_ 108 | if ($PSBoundParameters.ContainsKey('Status')) { 109 | $params = @{ 110 | cmd = "speedtest-status" 111 | } 112 | $body = New-UnifiCommand $params 113 | write-verbose $body 114 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 115 | $Response.data 116 | } 117 | else { 118 | $params = @{ 119 | cmd = "speedtest" 120 | } 121 | $body = New-UnifiCommand $params 122 | write-verbose $body 123 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 124 | write-host "Started speed test. Please wait a minute before checking results." 125 | } 126 | } 127 | 'Locate' { 128 | write-verbose $_ 129 | if ($locate -eq $true){ 130 | $params = @{ 131 | cmd = "set-locate" 132 | mac = $mac 133 | } 134 | $body = New-UnifiCommand $params 135 | write-verbose $body 136 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 137 | write-host "Blinking LED." 138 | } 139 | else { 140 | $params = @{ 141 | cmd = "unset-locate" 142 | mac = $mac 143 | } 144 | $body = New-UnifiCommand $params 145 | write-verbose $body 146 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 147 | write-host "Unblinking LED." 148 | } 149 | } 150 | 'Upgrade' { 151 | write-verbose $_ 152 | if ($Device.State -ne 1){ 153 | write-host "Device $mac is not ready." 154 | exit 155 | } 156 | if ($PSBoundParameters.ContainsKey('URL')) { 157 | # This is the custom-upgrade section by specifying a URL. 158 | $params = @{ 159 | cmd = "upgrade-external" 160 | mac = $mac 161 | url = $URL 162 | } 163 | $body = New-UnifiCommand $params 164 | write-verbose $body 165 | if ($PSCmdlet.ShouldProcess($mac,'Upgrade firmware')){ 166 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 167 | if ($response.meta.rc -eq 'ok'){ 168 | write-host "Started firmware installation on device $mac." 169 | } 170 | else { 171 | write-host "Recieved error `"${$response.meta.rc}`" for device $mac." 172 | } 173 | } 174 | } 175 | else { 176 | # This is the auto-upgrade section handled by the controller. 177 | if ($Device.upgradable -eq $true) { 178 | # It appears that the firmware is always updated to the latest no matter what value is specified for upgrade_to_firmware 179 | $params = @{ 180 | cmd = "upgrade" 181 | mac = $mac 182 | upgrade_to_firmware = $device.upgrade_to_firmware 183 | } 184 | $body = New-UnifiCommand $params 185 | write-verbose $body 186 | if ($PSCmdlet.ShouldProcess($mac,'Upgrade firmware')){ 187 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 188 | if ($response.meta.rc -eq 'ok'){ 189 | write-host "Started firmware upgrade on device $mac." 190 | } 191 | else { 192 | write-host "Recieved error `"${$response.meta.rc}`" for device $mac." 193 | } 194 | } 195 | } 196 | else { 197 | write-host "No updates found for device $mac." 198 | } 199 | } 200 | } 201 | 'Migrate' { 202 | write-verbose $_ 203 | if ($migrate -eq $true){ 204 | $params = @{ 205 | cmd = "migrate" 206 | inform_url = $URL 207 | mac = $mac 208 | } 209 | $body = New-UnifiCommand $params 210 | write-verbose $body 211 | if ($PSCmdlet.ShouldProcess("Update Inform URL ($URL) for target `"$mac`"?",$mac,'Migrate')){ 212 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 213 | } 214 | } 215 | else { 216 | $params = @{ 217 | cmd = "cancel-migrate" 218 | mac = $mac 219 | } 220 | $body = New-UnifiCommand $params 221 | write-verbose $body 222 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 223 | } 224 | 225 | } 226 | 'Scan'{ 227 | write-verbose $_ 228 | if ($device.type -eq 'uap'){ 229 | $params = @{ 230 | cmd = "spectrum-scan" 231 | mac = $mac 232 | } 233 | $body = New-UnifiCommand $params 234 | write-verbose $body 235 | $Response=(Invoke-POSTRestAPICall -url $URI -payload $body) 236 | $response 237 | write-host "Started spectrum scan." 238 | 239 | } 240 | 241 | } 242 | default {throw "Unknown command $_."} 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Public/Set-UnifiSiteSetting.ps1: -------------------------------------------------------------------------------- 1 | function Set-UnifiSiteSetting { 2 | [CmdletBinding(SupportsShouldProcess)] 3 | param ( 4 | [Parameter(Position=0, Mandatory = $true)][string]$name, 5 | [ValidateSet( 6 | "auto_speedtest", 7 | "connectivity", 8 | "country", 9 | "dpi", 10 | "element_adopt", 11 | "global_ap", 12 | "global_switch", 13 | "guest_access", 14 | "ips", 15 | "lcm", 16 | "locale", 17 | "mgmt", 18 | "network_optimization", 19 | "ntp", 20 | "porta", 21 | "provider_capabilities", 22 | "radio_ai", 23 | "radius", 24 | "rsyslogd", 25 | "snmp", 26 | "super_cloudaccess", 27 | "super_events", 28 | "super_fingerbank", 29 | "super_fwupdate", 30 | "super_identity", 31 | "super_mail", 32 | "super_mgmt", 33 | "super_sdn", 34 | "super_smtp", 35 | "teleport", 36 | "usg", 37 | "usw" 38 | )] 39 | [Parameter(Position=1, Mandatory = $true)][string]$Setting, 40 | [Parameter(Position=2, Mandatory = $true)]$Object 41 | ) 42 | # Converts hash tables to objects. 43 | if (($object.gettype()).name -ne "PSCustomObject"){ 44 | $object=ConvertTo-Object $object 45 | } 46 | # validate the setting defined actually exists. 47 | $SiteSpecificSettings=Get-UnifiSiteSetting $name 48 | $Props = ($SiteSpecificSettings | get-member -membertype NoteProperty).Name 49 | write-verbose "Available settings: $props" 50 | if ($props -notcontains $Setting){ 51 | Throw "Setting `"$Setting`" not found. Valid options are: $props." 52 | } 53 | # Now since this is a valid section, grab the settings for this section. 54 | $SectionOptions=$SiteSpecificSettings.$Setting 55 | write-verbose "Original $setting settings: $($SiteSpecificSettings.$Setting)" 56 | $SectionProps=($SectionOptions | get-member -membertype NoteProperty).name 57 | foreach ($item in $object){ 58 | $ItemName=($item | get-member -MemberType NoteProperty).name 59 | if ($SectionProps -notcontains $ItemName) { 60 | Throw "Property $ItemName not valid for $setting setting." 61 | } 62 | else { 63 | write-verbose "Found property $itemname with value of $($item.$itemname)" 64 | $SiteSpecificSettings.$setting.$ItemName=$item.$itemname 65 | } 66 | } 67 | 68 | write-verbose "Updated $setting settings: $($SiteSpecificSettings.$Setting)" 69 | $URI="$controller/api/s/$name/set/setting/$setting/$($SiteSpecificSettings.$setting._id)" 70 | $body=New-UnifiCommand $SiteSpecificSettings.$Setting 71 | write-verbose "Command URI: $URI" 72 | write-verbose "Payload: $body" 73 | if ($PSCmdlet.ShouldProcess($URI,"Invoke-PostRestAPICall")){ 74 | (Invoke-POSTRestAPICall -url $URI -payload $body).meta.rc 75 | } 76 | 77 | <# 78 | .SYNOPSIS 79 | Configures site settings. 80 | 81 | .DESCRIPTION 82 | Configures site settings. The method for generating the setting _id value is not known, so it is not possible to modify a setting 83 | that doesn't already exist when running the Get-UnifiSiteSetting command. Many site settings do not exist in the API until they 84 | have been saved at least once via the Web UI. 85 | 86 | .PARAMETER Name 87 | Short name for the site. This is the 'name' value from the Get-UnifiSite command. 88 | 89 | .PARAMETER Setting 90 | The site setting section to update. Valid options are auto_speedtest, connectivity, country, dpi, element_adopt, guest_access, global_ap, 91 | global_switch, ips, lcm, locale, mgmt, network_optimization, ntp, porta, provider_capabilities, radio_ai, radius, rsyslogd, snmp, 92 | super_cloudaccess, super_events, super_identity, super_mail, super_mgmt, super_sdn, super_smtp, teleport, usg, and usw. These are further 93 | limited to only settings that currently exist when running the Get-UnifiSiteSetting command for the specified site. 94 | 95 | To check for currently unsupported options, please run the Test-UnifiSiteKnownSetting command. If this test script finds any additional values, 96 | please inform the module author so these can be added. 97 | 98 | .PARAMETER Object 99 | This is an object containing the key/value pairs for any updated settings. Only updated values need to be included. The updated values 100 | will be merged with the existing values. Including key/value pairs which do not exist in the current settings will generate an error. 101 | 102 | .INPUTS 103 | None. 104 | 105 | .OUTPUTS 106 | System.String - This is the response status value from the Unifi controller. It should report 'ok' unless there is an error with the update process. 107 | 108 | .EXAMPLE 109 | Set-UnifiSiteSetting -name 'default' -setting 'locale' -object @{timezone='America/Chicago'} -confirm 110 | 111 | Changes the timezone parameter for the locale settings to 'America/Chicago with a confirmation prompt before executing the update. 112 | 113 | .EXAMPLE 114 | $Params=@{timezone = 'UTC'}; Set-UnifiSiteSetting -Name 'default' -Setting 'locale' -Object $Params -WhatIf -Verbose 115 | 116 | Uses -WhatIf switch to test changing the timezone parameter for the local setting to 'UTC'. The -Verbose switch is used to output various 117 | other bits of data from the function to confirm that it is executing as expected before actually making the change to the controller. 118 | 119 | VERBOSE: GET /api/s//rest/setting with 0-byte payload 120 | VERBOSE: received -1-byte response of content type application/json;charset=UTF-8 121 | VERBOSE: Available settings: auto_speedtest connectivity country dpi element_adopt guest_access lcm locale mgmt network_optimization 122 | ntp provider_capabilities rsyslogd super_cloudaccess super_events super_identity super_mail super_mgmt super_sdn super_smtp usg usw 123 | VERBOSE: Original locale settings: @{key=locale; site_id=; timezone=America/Chicago; _id=<_id>} 124 | VERBOSE: Found property timezone with value of UTC 125 | VERBOSE: Updated locale settings: @{key=locale; site_id=; timezone=UTC; _id=<_id>} 126 | VERBOSE: Command URI: /api/s//set/setting/locale/<_id> 127 | VERBOSE: Payload: { 128 | "key": "locale", 129 | "site_id": "", 130 | "timezone": "UTC", 131 | "_id": "<_id>"" 132 | } 133 | What if: Performing the operation "Invoke-PostRestAPICall" on target "/api/s//set/setting/locale/<_id>". 134 | 135 | .NOTES 136 | While this function has been designed to be as robust as possible, it is not possible to validate the property values provided to the command. When updating 137 | the controller, it will gladly accept any value provided, including invalid options. Please make sure you have a good backup of your controller data 138 | before making changes. 139 | 140 | Do not under any circumstances change the _id or site_id key/value pairs. 141 | 142 | Any update to the site settings will force all devices to reprovision. This cannot be disabled. 143 | #> 144 | } -------------------------------------------------------------------------------- /Public/Test-UnifiSiteKnownSetting.ps1: -------------------------------------------------------------------------------- 1 | function Test-UnifiSiteKnownSetting { 2 | [CmdletBinding()] 3 | param() 4 | $SettingList=@( 5 | "auto_speedtest", 6 | "connectivity", 7 | "country", 8 | "dpi", 9 | "element_adopt", 10 | "global_ap", 11 | "global_switch", 12 | "guest_access", 13 | "ips", 14 | "lcm", 15 | "locale", 16 | "mgmt", 17 | "network_optimization", 18 | "ntp", 19 | "porta", 20 | "provider_capabilities", 21 | "radio_ai", 22 | "radius", 23 | "rsyslogd", 24 | "snmp", 25 | "super_cloudaccess", 26 | "super_events", 27 | "super_fingerbank", 28 | "super_fwupdate", 29 | "super_identity", 30 | "super_mail", 31 | "super_mgmt", 32 | "super_sdn", 33 | "super_smtp", 34 | "teleport", 35 | "usg", 36 | "usw" 37 | ) 38 | $UnifiSites=Get-UnifiSite | sort-object -property desc 39 | $SettingNames=[System.Collections.ArrayList]@() 40 | write-host "Building list of Unifi site settings..." 41 | foreach ($site in $UnifiSites){ 42 | $UnifiSettings=Get-UnifiSiteSetting -name $site.name 43 | write-host "`tProcessing $($site.desc)..." 44 | ($UnifiSettings| get-member -MemberType NoteProperty | select-object name) | foreach-object {[void]$settingNames.add($_.name)} 45 | } 46 | $UniqueSettings=$SettingNames | sort-object -Unique 47 | $NewSettings=$false 48 | foreach ($Setting in $UniqueSettings){ 49 | if ($settinglist -notcontains $setting){ 50 | write-host "Found new site setting: "-nonewline -ForegroundColor Yellow 51 | write-host "$setting" -NoNewline -ForegroundColor Green 52 | write-host ". Please inform module maintainer." -ForegroundColor Yellow 53 | $NewSettings=$true 54 | } 55 | } 56 | if ($NewSettings -eq $false){ 57 | write-host "No new site settings found. No further action necessary." 58 | } 59 | 60 | <# 61 | .SYNOPSIS 62 | Runs diagnostic test to determine if any unknown site settings exist. 63 | 64 | .DESCRIPTION 65 | Runs diagnostic test to determine if any unknown site settings exist. The list of possible settings are embedded in various modules to 66 | assist with tab auto-completion. Settings do not exist until they have been configured at least once through the Unifi WebUI as the 67 | method to generate the setting ID value is unknown. This makes it difficult to precisely know all possible settings available. If any 68 | previously known site settings exist, they will displayed at the end of the script output. 69 | 70 | .INPUTS 71 | None 72 | 73 | .OUTPUTS 74 | Diagnostic text. 75 | #> 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unifi 2 | This module is designed to provide programmatic access to the various commands and functions in the Unifi controller module via powershell. 3 | The functions here are based on information from the [Ubiquiti Community Wiki](https://ubntwiki.com/products/software/unifi-controller/api) along with reverse engineering the controller's web UI. 4 | ## Installation instructions 5 | install-module Unifi 6 | ## Usage 7 | To get started with using the module and connecting to the controller, you will need an administrator account on the Unifi controller. 8 | The following code will provide the necessary data and commands to setup the connection: 9 | 10 | 11 | [String]$Hostname = '' 12 | [String]$Port = '8443' # Change this to match the listening port 13 | [String]$UnifiUsername = '' 14 | [String]$UnifiPassword = '' 15 | 16 | [String]$Controller = "https://$($hostname):$($port)" 17 | 18 | # Enables TLS1.2 -- this is a universal method that works for any dot net version 19 | [Net.ServicePointManager]::SecurityProtocol = [Enum]::ToObject([Net.SecurityProtocolType], 3072) 20 | 21 | # Ignore self-signed certificates 22 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 23 | 24 | # Create a secure credential object 25 | [securestring]$SecPassword=ConvertTo-SecureString $UnifiPassword -AsPlainText -Force 26 | [pscredential]$Credentials=New-Object System.Management.Automation.PSCredential ($UnifiUsername, $SecPassword) 27 | 28 | import-module Unifi 29 | 30 | # If connecting to a UDMPro, add '-UDMPro' to the following line. 31 | Connect-UnifiController -ControllerURL $Controller -credentials $Credentials 32 | 33 | *Note: After the initial connection, the module will automatically refresh the connection as needed.* 34 | *Note: The module now supports Unifi 2FA, however, you will be prompted for 2FA any time the credentials need to be refreshed.* 35 | 36 | To end the session and disconnect from the controller: 37 | 38 | Disconnect-UnifiController 39 | *Note: it is not necessary to disconnect from the controller specifically as the session will end on its own after a few minutes.* 40 | 41 | The command to ignore self-signed certificates will prevent successful communication with other sites. To restore normal functionality, set the value to $null. This is only needed if you want to reuse the current powershell session. 42 | 43 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null 44 | 45 | ### Example commands 46 | Retrieve a list of all sites. 47 | 48 | Get-UnifiSite 49 | 50 | Retrieve a list of all products supported by the controller. (This is not functional on controller versions newer than 5.x at the moment.) 51 | 52 | Get-UnifiProductList 53 | 54 | Model Type ProductName 55 | ----- ---- ----------- 56 | BZ2 uap UAP 57 | BZ2LR uap UAP-LR 58 | U2HSR uap UAP-Outdoor+ 59 | U2IW uap UAP-IW 60 | U2L48 uap UAP-LR 61 | U2Lv2 uap UAP-LRv2 62 | U2M uap UAP-Mini 63 | U2O uap UAP-Outdoor 64 | U2S48 uap UAP 65 | U2Sv2 uap UAPv2 66 | U5O uap UAP-Outdoor5 67 | U7E uap UAP-AC 68 | U7EDU uap UAP-AC-EDU 69 | U7Ev2 uap UAP-AC 70 | ... 71 | 72 | 73 | Retrieve a list of all administrator accounts 74 | 75 | Get-UnifiAdmin 76 | 77 | Retrieve a list of all administrators for a specific site 78 | 79 | Get-UnifiSiteAdmin -name 80 | 81 | Retrieve a list of all site devices 82 | 83 | Get-UnifiSiteDevice -name 84 | 85 | Reboot a device 86 | 87 | Set-UnifiSiteDevice -name -mac -restart 88 | 89 | Force provision a device 90 | 91 | Set-UnifiSiteDevice -name -mac -provision 92 | 93 | Upgrade device firmware 94 | 95 | Set-UnifiSiteDevice -name -mac -upgrade 96 | 97 | Upgrade device firmware with specific firmware 98 | 99 | Set-UnifiSiteDevice -name -mac -upgrade -URL 100 | 101 | 102 | ## Documentation 103 | Documentation for all commands have been included in the comment based help. To see all available information, please use the *-full* switch. 104 | 105 | Get-Help -full 106 | 107 | List all available commands 108 | 109 | Get-Command -module Unifi 110 | 111 | # Contributions 112 | Feel free to send pull requests or submit issues when you encounter them. 113 | ### Help needed! 114 | The way the site settings are stored in the controller database, the settings themselves aren't present until they are actually used. I could not determine all possible settings, just the ones that were configured in my environment. I have made a test tool to go through and evaluate all existing sites and their settings and it will list any settings that have not already been accounted for. Please run this tool on your environment and report any new settings it finds. Thanks! 115 | 116 | Test-UnifiSiteKnownSetting 117 | 118 | # Future Plans 119 | 120 | This initial release covers all the functionality needed in my environment. I do have plans to eventually support the rest of the callable commands listed in the [Ubiquity Community Wiki](https://ubntwiki.com/products/software/unifi-controller/api), although I have no specific ETA. If you have a specific feature request, send me a note! 121 | -------------------------------------------------------------------------------- /Unifi.psd1: -------------------------------------------------------------------------------- 1 | 2 | @{ 3 | 4 | # Script module or binary module file associated with this manifest. 5 | RootModule = 'Unifi.psm1' 6 | 7 | # Version number of this module. 8 | ModuleVersion = '1.0.7' 9 | 10 | # Supported PSEditions 11 | # CompatiblePSEditions = @() 12 | 13 | # ID used to uniquely identify this module 14 | GUID = '202e268d-610c-48ec-b0e1-52e9f091e82b' 15 | 16 | # Author of this module 17 | Author = 'Michael McCool' 18 | 19 | # Company or vendor of this module 20 | CompanyName = 'Michael McCool' 21 | 22 | # Copyright statement for this module 23 | Copyright = '(c)2021 Michael McCool' 24 | 25 | # Description of the functionality provided by this module 26 | Description = 'This module allows you to connect to the Unifi controller REST API.' 27 | 28 | # Minimum version of the Windows PowerShell engine required by this module 29 | PowerShellVersion = '5.0' 30 | 31 | # Name of the Windows PowerShell host required by this module 32 | # PowerShellHostName = '' 33 | 34 | # Minimum version of the Windows PowerShell host required by this module 35 | # PowerShellHostVersion = '' 36 | 37 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 38 | # DotNetFrameworkVersion = '' 39 | 40 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 41 | # CLRVersion = '' 42 | 43 | # Processor architecture (None, X86, Amd64) required by this module 44 | # ProcessorArchitecture = '' 45 | 46 | # Modules that must be imported into the global environment prior to importing this module 47 | # RequiredModules = @() 48 | 49 | # Assemblies that must be loaded prior to importing this module 50 | # RequiredAssemblies = @() 51 | 52 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 53 | # ScriptsToProcess = @() 54 | 55 | # Type files (.ps1xml) to be loaded when importing this module 56 | # TypesToProcess = @() 57 | 58 | # Format files (.ps1xml) to be loaded when importing this module 59 | # FormatsToProcess = @() 60 | 61 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 62 | # NestedModules = @() 63 | 64 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 65 | FunctionsToExport = @( 66 | 'Clear-UnifiSiteAlarm', 67 | 'Connect-UnifiController', 68 | 'Disconnect-UnifiController', 69 | 'Get-UnifiAdmin', 70 | 'Get-UnifiControllerName', 71 | 'Get-UnifiSite', 72 | 'Get-UnifiSiteAdmin', 73 | 'Get-UnifiSiteAlarm', 74 | 'Get-UnifiSiteBackup', 75 | 'Get-UnifiSiteClient', 76 | 'Get-UnifiSiteCountryCode', 77 | 'Get-UnifiSiteDevice', 78 | 'Get-UnifiSiteDynamicDNS', 79 | 'Get-UnifiSiteEvent', 80 | 'Get-UnifiSiteFirewallGroup', 81 | 'Get-UnifiSiteFirewallRule', 82 | 'Get-UnifiSiteHealth', 83 | 'Get-UnifiSiteKnownAccessPoint', 84 | 'Get-UnifiSiteNetwork', 85 | 'Get-UnifiSitePortForwarding', 86 | 'Get-UnifiSiteRadiusAccount', 87 | 'Get-UnifiSiteRadiusProfile', 88 | 'Get-UnifiSiteWirelessRFChannel', 89 | 'Get-UnifiSiteSetting', 90 | 'Get-UnifiSiteStatistic', 91 | 'Get-UnifiStatus', 92 | 'Get-UnifiSiteDevice', 93 | 'Get-UnifiSiteRouting', 94 | 'Get-UnifiSiteSwitchProfile', 95 | 'Get-UnifiSiteSystemInformation', 96 | 'Get-UnifiSiteTag', 97 | 'Get-UnifiSiteWarning', 98 | 'Get-UnifiSiteWhoAmI', 99 | 'Get-UnifiSiteWirelessNetwork', 100 | 'Get-UnifiTimeZone', 101 | 'Get-UnifiWhoAmI', 102 | 'Get-UnifiEventStrings', 103 | 'Get-UnifiProductList', 104 | 'Grant-UnifiSuperAdmin', 105 | 'New-UnifiSiteAdmin', 106 | 'New-UnifiSiteFirewallRule', 107 | 'Remove-UnifiAdmin', 108 | 'Remove-UnifiSiteAdmin', 109 | 'Revoke-UnifiSuperAdmin', 110 | 'Set-UnifiSiteAdmin', 111 | 'Set-UnifiSiteDevice', 112 | 'Set-UnifiSiteSetting', 113 | 'Test-UnifiSiteKnownSetting' 114 | ) 115 | 116 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 117 | CmdletsToExport = @() 118 | 119 | # Variables to export from this module 120 | VariablesToExport = '*' 121 | 122 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 123 | AliasesToExport = @() 124 | 125 | # DSC resources to export from this module 126 | # DscResourcesToExport = @() 127 | 128 | # List of all modules packaged with this module 129 | # ModuleList = @() 130 | 131 | # List of all files packaged with this module 132 | # FileList = @() 133 | 134 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 135 | PrivateData = @{ 136 | 137 | PSData = @{ 138 | 139 | # Tags applied to this module. These help with module discovery in online galleries. 140 | Tags = @('Unifi','api','REST','Ubiquiti','Wireless','controller','cloudkey') 141 | 142 | # A URL to the license for this module. 143 | LicenseUri = 'https://github.com/MichaelMcCool/Unifi/blob/main/LICENSE' #MIT license 144 | 145 | # A URL to the main website for this project. 146 | ProjectUri = 'https://github.com/MichaelMcCool/Unifi' 147 | 148 | # A URL to an icon representing this module. 149 | IconUri = 'https://github.com/MichaelMcCool/Unifi/blob/main/ubiquiti_icon.png' 150 | 151 | # ReleaseNotes of this module 152 | ReleaseNotes = 'This module allows for management of Unifi Controllers using PowerShell. This is the initial release.' 153 | 154 | } # End of PSData hashtable 155 | 156 | } # End of PrivateData hashtable 157 | 158 | # HelpInfo URI of this module 159 | #HelpInfoURI = '' 160 | 161 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 162 | # DefaultCommandPrefix = '' 163 | 164 | } 165 | -------------------------------------------------------------------------------- /Unifi.psm1: -------------------------------------------------------------------------------- 1 | $Public = @(Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue) + @(Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue) 2 | foreach ($import in @($Public)) 3 | { 4 | try 5 | { 6 | . $import.FullName 7 | } 8 | catch 9 | { 10 | Write-Error -Message "Failed to import function $($import.FullName): $_" 11 | } 12 | } -------------------------------------------------------------------------------- /ubiquiti_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MichaelMcCool/Unifi/f7824f36e3c34fb0096e09f52e413b14a7a1cb5b/ubiquiti_icon.png --------------------------------------------------------------------------------