Functions/Public/Locations.ps1
|
# Location management and geography functions Function Get-NectarLocation { <# .SYNOPSIS Returns a list of Nectar DXP locations .DESCRIPTION Returns a list of Nectar DXP locations .PARAMETER SearchQuery The name of the location to get information on based on either network, networkName, City, StreetAddress, State, SiteName or SiteCode. Can be a partial match, and may return more than one entry. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER ResultSize The number of results to return. Defaults to 1000. .EXAMPLE Get-NectarLocation Returns the first 10 locations .EXAMPLE Get-NectarLocation -ResultSize 100 Returns the first 100 locations .EXAMPLE Get-NectarLocation -LocationName Location2 Returns up to 10 locations that contains "location2" anywhere in the name. The search is not case-sensitive. This example would return Location2, Location20, Location214, MyLocation299 etc .EXAMPLE Get-NectarLocation -LocationName ^Location2 Returns up to 10 locations that starts with "location2" in the name. The search is not case-sensitive. This example would return Location2, Location20, Location214 etc, but NOT MyLocation299 .EXAMPLE Get-NectarLocation -LocationName ^Location2$ Returns a location explicitly named "Location2". The search is not case-sensitive. .NOTES Version 1.1 #> [Alias("gnl")] Param ( [Parameter(Mandatory=$False)] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [ValidateRange(1,100000)] [int]$ResultSize = 5000 ) Begin { Connect-NectarCloud } Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } $URI = "https://$Global:NectarCloud/aapi/config/locations?pageNumber=1&tenant=$TenantName&pageSize=$ResultSize&searchQuery=$SearchQuery" Write-Verbose $URI $Response = [Text.Encoding]::UTF8.GetString((Invoke-WebRequest $URI -UseBasicParsing -Method 'GET' -Headers $Global:NectarAuthHeader).RawContentStream.ToArray()) # This is required to get the data in UTF8 format $JSON = $Response | ConvertFrom-JSON If (!$JSON.elements) { Write-Error "Location $SearchQuery not found." } Else { If ($TenantName) { $JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty } # Add the tenant name to the output which helps pipelining $JSON.elements | Add-Member -TypeName 'Nectar.LocationList' Return $JSON.elements } } Catch { Write-Error "Unable to get location details. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Set-NectarLocation { <# .SYNOPSIS Update a Nectar DXP location in the location database .DESCRIPTION Update a Nectar DXP location in the location database. This command can use the Google Geocode API to automatically populate the latitude/longitude for each location. You can register for an API key and save it as persistent environment variable called GoogleGeocode_API_Key on this machine. This command will prompt for the GeoCode API key and will save it in the appropriate location. Follow this link to get an API Key - https://developers.google.com/maps/documentation/geocoding/get-api-key. If this is not an option, then use the -SkipGeoLocate switch .PARAMETER SearchQuery A string to search for. Will search in Network, NetworkName, City, Street Address, Region etc. .PARAMETER Network The IP subnet of the network .PARAMETER NetworkRange The subnet mask of the network .PARAMETER ExtNetwork The IP subnet of the external/public network. Optional. Used to help differentiate calls from corporate locations that use common home subnets (192.168.x.x) .PARAMETER ExtNetworkRange The subnet mask of the external/public network. Optional. Used to help differentiate calls from corporate locations that use common home subnets (192.168.x.x) .PARAMETER NetworkName The name to give to the network .PARAMETER SiteName The name to give to the siteCode .PARAMETER SiteCode A site code to assign to the site .PARAMETER Region The name of the region. Typically is set to country name or whatever is appropriate for the company .PARAMETER StreetAddress The street address of the location .PARAMETER City The city of the location .PARAMETER State The state/province of the location .PARAMETER PostCode The postal/zip code of the location .PARAMETER Country The 2-letter ISO country code of the location .PARAMETER Description A description to apply to the location .PARAMETER IsWireless True or false if the network is strictly wireless .PARAMETER IsExternal True or false if the network is outside the corporate network .PARAMETER IsVPN True or false if the network is a VPN .PARAMETER NetworkRangeType The type of network range. Choose from Sequential or Subnet .PARAMETER Latitude The geographical latitude of the location. If not specified, will attempt automatic geolocation. .PARAMETER Longitude The geographical longitude of the location. If not specified, will attempt automatic geolocation. .PARAMETER SkipGeoLocate Don't attempt geolocation. Do this if you don't have a valid Google Maps API key. .PARAMETER Identity The numerical ID of the location to update. Can be obtained via Get-NectarLocation and pipelined to Set-NectarLocation .EXAMPLE Set-NectarLocation HeadOffice -Region WestUS Changes the region for HeadOffice to WestUS .EXAMPLE Get-NectarLocation | Set-NectarLocation Will go through each location and update the latitude/longitude. Useful if a Google Geocode API key was obtained after initial location loading .NOTES Version 1.11 #> [Alias("snl")] Param ( [Parameter(Mandatory=$False)] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("subnet")] [string]$Network, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(0,32)] [string]$NetworkRange, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('ExternalNetwork')] [string]$ExtNetwork, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('ExternalNetworkRange')] [ValidateRange(0,32)] [string]$ExtNetworkRange, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateLength(1,99)] [Alias("Network Name")] [string]$NetworkName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$SiteName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("Site Code")] [string]$SiteCode, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$Region, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("address")] [string]$StreetAddress, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$City, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("province")] [string]$State, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("zipcode")] [string]$PostCode, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateLength(0,2)] [string]$Country, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$Description, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet("True","False","Yes","No",0,1, IgnoreCase=$True)] [Alias("isWirelessNetwork","Wireless(Yes/No)","Wireless","Wifi")] [string]$IsWireless, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet("True","False","Yes","No",0,1, IgnoreCase=$True)] [Alias("External(Yes/No)","External")] [string]$IsExternal, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet("True","False","Yes","No",0,1, IgnoreCase=$True)] [Alias("VPN","VPN(Yes/No)")] [string]$IsVPN, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('Sequential','Subnet','Virtual', IgnoreCase=$True)] [string]$NetworkRangeType, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(-90,90)] [Alias("CoordinatesLatitude")] [double]$Latitude, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(-180,180)] [Alias("CoordinatesLongitude")] [double]$Longitude, [Parameter(Mandatory=$False)] [switch]$ForceGeoLocate, [Parameter(Mandatory=$False)] [switch]$SkipGeoLocate, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("id")] [int]$Identity ) Begin { Connect-NectarCloud } Process { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } Try { If ($SearchQuery) { $LocationInfo = Get-NectarLocation -SearchQuery $SearchQuery -Tenant $TenantName -ResultSize 1 $Identity = $LocationInfo.id #.ToString() } If (-not $Network) {$Network = $LocationInfo.network} If (-not $NetworkRange) {$NetworkRange = $LocationInfo.networkRange} If (-not $ExtNetwork) {$ExtNetwork = $LocationInfo.externalNetwork} If (-not $ExtNetworkRange) {$ExtNetworkRange = $LocationInfo.externalNetworkRange} If (-not $NetworkRangeType) {$NetworkRangeType = $LocationInfo.networkRangeType} If (-not $NetworkName) {$NetworkName = $LocationInfo.networkName} If (-not $SiteName) {$SiteName = $LocationInfo.siteName} If (-not $SiteCode) {$SiteCode = $LocationInfo.siteCode} If (-not $Region) {$Region = $LocationInfo.region} If (-not $StreetAddress) {$StreetAddress = $LocationInfo.streetAddress} If (-not $City) {$City = $LocationInfo.city} If (-not $State) {$State = $LocationInfo.state} If (-not $PostCode) {$PostCode = $LocationInfo.zipCode} If (-not $Country) {$Country = $LocationInfo.country} If (-not $Description) {$Description = $LocationInfo.description} If (-not $IsWireless) {$IsWireless = $LocationInfo.isWirelessNetwork} If (-not $IsExternal) {$IsExternal = $LocationInfo.isExternal} If (-not $IsVPN) {$IsVPN = $LocationInfo.vpn} If ($NULL -eq $Latitude -or $Latitude -eq 0) {$Latitude = $LocationInfo.latitude} If ($NULL -eq $Longitude -or $Longitude -eq 0) {$Longitude = $LocationInfo.longitude} If (-not $IsVPN) {$IsVPN = $LocationInfo.vpn} If ((($NULL -eq $Latitude -Or $NULL -eq $Longitude) -Or ($Latitude -eq 0 -And $Longitude -eq 0)) -Or $ForceGeoLocate -And !$SkipGeoLocate) { Write-Verbose "Lat/Long missing. Getting Lat/Long." $LatLong = Get-LatLong "$StreetAddress, $City, $State, $PostCode, $Region" $Latitude = $LatLong.Latitude $Longitude = $LatLong.Longitude } $URI = "https://$Global:NectarCloud/aapi/config/location/$($Identity)?tenant=$TenantName" Write-Verbose $URI $Body = @{ city = $City description = $Description id = $Identity isExternal = ParseBool $IsExternal isWirelessNetwork = ParseBool $IsWireless latitude = $Latitude.ToString() longitude = $Longitude.ToString() network = $Network networkRange = $NetworkRange externalNetwork = $ExtNetwork externalNetworkRange = $ExtNetworkRange networkName = $NetworkName networkRangeIpEnd = $NULL networkRangeIpStart = $NULL networkRangeType = $NetworkRangeType region = $Region siteCode = $SiteCode siteName = $SiteName state = $State streetAddress = $StreetAddress country = $Country vpn = ParseBool $IsVPN zipCode = $PostCode } $JSONBody = $Body | ConvertTo-Json Try { Write-Verbose $JSONBody $NULL = Invoke-RestMethod -Method PUT -URI $URI -Headers $Global:NectarAuthHeader -Body $JSONBody -ContentType 'application/json; charset=utf-8' } Catch { If ($NetworkName) { $IDText = $NetworkName } Else { $IDText = "with ID $Identity" } Write-Error "Unable to apply changes for location $IDText. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } Catch { Write-Error $($_.Exception.Message) } } } Function New-NectarLocation { <# .SYNOPSIS Creates a Nectar DXP location in the location database .DESCRIPTION Creates a Nectar DXP location in the location database. This command can use the Google Geocode API to automatically populate the latitude/longitude for each location. You can register for an API key and save it as persistent environment variable called GoogleGeocode_API_Key on this machine. This command will prompt for the GeoCode API key and will save it in the appropriate location. Follow this link to get an API Key - https://developers.google.com/maps/documentation/geocoding/get-api-key. If this is not an option, then use the -SkipGeoLocate switch .PARAMETER Network The IP subnet of the network .PARAMETER NetworkRange The subnet mask of the network .PARAMETER ExtNetwork The IP subnet of the external/public network. Optional. Used to help differentiate calls from corporate locations that use common home subnets (192.168.x.x) .PARAMETER ExtNetworkRange The subnet mask of the external/public network. Optional. Used to help differentiate calls from corporate locations that use common home subnets (192.168.x.x) .PARAMETER NetworkName The name to give to the network .PARAMETER SiteName The name to give to the site .PARAMETER SiteCode A site code to assign to the site .PARAMETER Region The name of the region. Typically is set to country name or whatever is appropriate for the company .PARAMETER StreetAddress The street address of the location .PARAMETER City The city of the location .PARAMETER State The state/province of the location .PARAMETER PostCode The postal/zip code of the location .PARAMETER Country The 2-letter ISO country code of the location .PARAMETER Description A description to apply to the location .PARAMETER IsWireless True or false if the network is strictly wireless .PARAMETER IsExternal True or false if the network is outside the corporate network .PARAMETER IsVPN True or false if the network is a VPN .PARAMETER NetworkRangeType The type of network range. Choose from Sequential, Subnet or Virtual .PARAMETER SkipGeoLocate Don't attempt geolocation. Do this if you don't have a valid Google Maps API key. .PARAMETER Latitude The geographical latitude of the location. If not specified, will attempt automatic geolocation. .PARAMETER Longitude The geographical longitude of the location. If not specified, will attempt automatic geolocation. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .EXAMPLE New-NectarLocation -Network 10.14.3.0 -NetworkRange 24 -NetworkName Corp5thFloor -SiteName 'Head Office' Creates a new location using the minimum required information .EXAMPLE New-NectarLocation -Network 10.15.1.0 -NetworkRange 24 -ExtNetwork 79.23.155.71 -ExtNetworkRange 28 -NetworkName Corp3rdFloor -SiteName 'Head Office' -SiteCode HO3 -IsWireless True -IsVPN False -Region EastUS -StreetAddress '366 North Broadway' -City Jericho -State 'New York' -Country US -PostCode 11753 -Description 'Head office 3rd floor' -Latitude 40.7818283 -Longitude -73.5351438 Creates a new location using all available fields .EXAMPLE Import-Csv LocationData.csv | New-NectarLocation Imports a CSV file called LocationData.csv and creates new locations .EXAMPLE Import-Csv LocationData.csv | New-NectarLocation -SkipGeolocate Imports a CSV file called LocationData.csv and creates new locations but will not attempt geolocation .NOTES Version 1.1 #> [Alias("nnl")] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('subnet','searchquery')] [string]$Network, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(0,32)] [string]$NetworkRange, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('ExternalNetwork')] [string]$ExtNetwork, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('ExternalNetworkRange')] [ValidateRange(0,32)] [string]$ExtNetworkRange, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [ValidateLength(1,99)] [Alias('Network Name')] [string]$NetworkName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)] [Alias('Site Name')] [string]$SiteName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('Site Code')] [string]$SiteCode, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$Region, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('Street Address', 'address')] [string]$StreetAddress, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$City, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('province')] [string]$State, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias('Zip Code', 'zipcode')] [string]$PostCode, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateLength(0,2)] [string]$Country, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$Description, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('True','False','Yes','No',0,1, IgnoreCase=$True)] [Alias('isWirelessNetwork','Wireless(Yes/No)','Wireless(True/False)','Wireless','Wifi')] [string]$IsWireless, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('True','False','Yes','No',0,1, IgnoreCase=$True)] [Alias('External(Yes/No)','External(True/False)','External','Internal/External')] [string]$IsExternal, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('True','False','Yes','No',0,1, IgnoreCase=$True)] [Alias('VPN','VPN(Yes/No)','VPN(True/False)')] [string]$IsVPN, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('Sequential','Subnet','Virtual', IgnoreCase=$True)] [string]$NetworkRangeType = 'Subnet', [Parameter(Mandatory=$False)] [switch]$SkipGeoLocate, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(-90,90)] [Alias('Coordinates Latitude','CoordinatesLatitude')] [double]$Latitude, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateRange(-180,180)] [Alias('Coordinates Longitude','CoordinatesLongitude')] [double]$Longitude, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName ) Begin { Connect-NectarCloud } Process { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } $URI = "https://$Global:NectarCloud/aapi/config/location?tenant=$TenantName" Write-Verbose $URI If (-not $Latitude -Or -not $Longitude -And !$SkipGeoLocate) { $LatLong = Get-LatLong "$StreetAddress, $City, $State, $PostCode, $Country" [double]$Latitude = $LatLong.Latitude [double]$Longitude = $LatLong.Longitude } $Body = @{ city = $City description = $Description isExternal = ParseBool $IsExternal isWirelessNetwork = ParseBool $IsWireless latitude = $Latitude.ToString() longitude = $Longitude.ToString() network = $Network networkName = $NetworkName externalNetwork = $ExtNetwork externalNetworkRange = $ExtNetworkRange region = $Region siteCode = $SiteCode siteName = $SiteName state = $State streetAddress = $StreetAddress country = $Country vpn = ParseBool $IsVPN zipCode = $PostCode networkRangeType = $NetworkRangeType } # This is to get around a bug where Nectar DXP throws an error if a location is built around externalNetworkRange # DXP expects that networkRange be explictly NULL, but PowerShell sends an empty string which causes a 500 error # The error doesn't occur if networkRange is simply not present. If ($NetworkRange) { $Body.Add('networkRange', $NetworkRange) } $JSONBody = $Body | ConvertTo-Json Try { Write-Verbose $JSONBody $NULL = Invoke-RestMethod -Method POST -URI $URI -Headers $Global:NectarAuthHeader -Body $JSONBody -ContentType 'application/json; charset=utf-8' } Catch { Write-Error "Unable to create location $NetworkName with network $Network/$NetworkRange. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Remove-NectarLocation { <# .SYNOPSIS Removes a Nectar DXP location from the location database .DESCRIPTION Removes a Nectar DXP location from the location database .PARAMETER SearchQuery The name of the location to remove. Can be a partial match. To return an exact match and to avoid ambiguity, enclose location name with ^ at the beginning and $ at the end. .PARAMETER NetworkRangeType The type of network range to delete. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER Identity The numerical ID of the location to remove. Can be obtained via Get-NectarLocation and pipelined to Remove-NectarLocation .NOTES Version 1.1 #> [Alias("rnl")] Param ( [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("networkName")] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [ValidateSet('Sequential','Subnet','Virtual', IgnoreCase=$True)] [string]$NetworkRangeType = 'Subnet', [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [Alias("id")] [string]$Identity ) Begin { Connect-NectarCloud } Process { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } If ($SearchQuery -And !$Identity) { $LocationInfo = Get-NectarLocation -SearchQuery $SearchQuery -Tenant $TenantName -ResultSize 1 -ErrorVariable GetLocationError $Identity = $LocationInfo.id $NetworkName = $LocationInfo.networkName } If (!$GetLocationError) { $URI = "https://$Global:NectarCloud/aapi/config/location/$($Identity)?networkRangeType=$NetworkRangeType&tenant=$TenantName" Write-Verbose $URI Try { $NULL = Invoke-RestMethod -Method DELETE -URI $URI -Headers $Global:NectarAuthHeader Write-Verbose "Successfully deleted $LocationName." } Catch { Write-Error "Unable to delete location $NetworkName. Ensure you typed the name of the location correctly. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } } Function Import-NectarLocations { <# .SYNOPSIS Imports a CSV list of locations into Nectar DXP .DESCRIPTION Import a CSV list of locations into Nectar DXP. This will overwrite any existing locations with the same network ID. Useful for making wholesale changes without wiping and replacing everything. Assumes you are working from an export from the existing Nectar DXP location list. .PARAMETER Path The path to the CSV file to import into Nectar DXP. The CSV file must use the standard column heading template used by Nectar DXP exports. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER SkipGeoLocate Don't attempt geolocation. Do this if you don't have a valid Google Maps API key or the lat/long is already included in the CSV. .NOTES Version 1.1 #> Param ( [Parameter(Mandatory=$True)] [string]$Path, [Parameter(Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [switch]$SkipGeoLocate ) $LocTable = ((Get-Content -Path $Path -Raw) -replace '\(Yes/No\)','') $LocTable = $LocTable -replace '\"?Network\"?\,',"""SearchQuery""," $LocationList = ConvertFrom-Csv $LocTable | Select-Object 'Network','NetworkRange','ExtNetwork','ExtNetworkRange','NetworkRangeType','NetworkName','SiteName','SiteCode','City','PostCode','Country','State','Region','Description','IsExternal','IsVPN','IsWireless','Latitude','Longitude' ForEach ($Location in $LocationList) { $LocationHashTable = @{} $Location.psobject.properties | ForEach-Object { $LocationHashTable[$_.Name] = $_.Value } If ($TenantName) { $LocationHashTable += @{TenantName = $TenantName } } # Add the tenant name to the hashtable If ($SkipGeoLocate) { $LocationHashTable += @{SkipGeoLocate = $TRUE} } Try { Write-Host "Updating location with subnet $($Location.SearchQuery)" Write-Verbose $LocationHashTable Set-NectarLocation @LocationHashTable -ErrorAction:Stop } Catch { Write-Host "Location does not exist. Creating location $($Location.SearchQuery)" New-NectarLocation @LocationHashTable } } } Function Import-MSTeamsLocations { <# .SYNOPSIS Imports a CSV list of locations downloaded from Microsoft CQD into Nectar DXP .DESCRIPTION Import a CSV list of locations downloaded from Microsoft CQD into Nectar DXP. This will overwrite any existing locations with the same network ID. Useful for making wholesale changes without wiping and replacing everything. .PARAMETER Path The path to the CSV file to import into Nectar DXP. The CSV file must be in the same format as downloaded from Microsoft CQD as per https://docs.microsoft.com/en-us/microsoftteams/cqd-upload-tenant-building-data .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER SkipGeoLocate Don't attempt geolocation. Do this if you don't have a valid Google Maps API key. .NOTES Version 1.0 #> Param ( [Parameter(Mandatory=$True)] [string]$Path, [Parameter(Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [switch]$SkipGeoLocate ) $Header = 'SearchQuery', 'NetworkName', 'NetworkRange', 'SiteName', 'OwnershipType', 'BuildingType', 'BuildingOfficeType', 'City', 'PostCode', 'Country', 'State', 'Region', 'IsExternal', 'ExpressRoute', 'IsVPN' $LocationList = Import-Csv $Path -Header $Header | Select-Object 'SearchQuery','NetworkRange','NetworkName','SiteName','City','PostCode','Country','State','Region','IsExternal','IsVPN' ForEach ($Location in $LocationList) { If ($Location.IsExternal -eq 0) { $Location.IsExternal = 1 } Else { $Location.IsExternal = 0 } If ($Location.IsVPN -eq 1) { $Location.IsVPN = 1 } Else { $Location.IsVPN = 0 } $LocationHashTable = @{} $Location.psobject.properties | ForEach-Object { $LocationHashTable[$_.Name] = $_.Value } If ($TenantName) { $LocationHashTable += @{TenantName = $TenantName } }# Add the tenant name to the hashtable If ($SkipGeoLocate) { $LocationHashTable += @{SkipGeoLocate = $TRUE} } Try { Write-Host "Updating location with subnet $($Location.SearchQuery)" Write-Verbose $LocationHashTable Set-NectarLocation @LocationHashTable -ErrorAction:Stop } Catch { Write-Host "Location does not exist. Creating location $($Location.SearchQuery)" New-NectarLocation @LocationHashTable } } } ################################################################################################################################################# # # # Tenant Alert Functions # # # Function Get-NectarExtCities { <# .SYNOPSIS Returns a list of cities found via IP geolocation .DESCRIPTION Most call records include the user's external IP address. Nectar DXP does a geo-IP lookup of the external IP address and stores the geographic information for later use. This command will return all the cities where Nectar DXP was able to successfully geolocate an external IP address. .PARAMETER SearchQuery The name of the city to locate. Can be a partial match, and may return more than one entry. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER ResultSize The number of results to return. Defaults to 10000. .EXAMPLE Get-NectarExtCities Returns the first 1000 cities sorted alphabetically. .EXAMPLE Get-NectarExtCities -ResultSize 5000 Returns the first 5000 cities sorted alphabetically. .EXAMPLE Get-NectarExtCities -SearchQuery Gu Returns all cities that contain the letters 'gu' .NOTES Version 1.0 #> [Alias("gneci")] Param ( [Parameter(Mandatory=$False)] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [ValidateRange(1,100000)] [int]$ResultSize = 10000 ) Begin { Connect-NectarCloud } Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } $URI = "https://$Global:NectarCloud/dapi/info/external/cities" Write-Verbose $URI $Params = @{ 'pageSize' = $ResultSize } If ($SearchQuery) { $Params.Add('searchQuery',$SearchQuery) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty} $JSON.elements } Catch { Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-NectarExtCountries { <# .SYNOPSIS Returns a list of 2-letter country codes found via IP geolocation .DESCRIPTION Most call records include the user's external IP address. Nectar DXP does a geo-IP lookup of the external IP address and stores the geographic information for later use. This command will return all the countries where Nectar DXP was able to successfully geolocate an external IP address. .PARAMETER SearchQuery The 2-letter country code to locate. Can be a partial match, and may return more than one entry. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER ResultSize The number of results to return. Defaults to 1000. .EXAMPLE Get-NectarExtCountries Returns all country codes sorted alphabetically. .EXAMPLE Get-NectarExtCountries -SearchQuery US Returns all country codes that contain the letters 'US' .NOTES Version 1.0 #> [Alias("gneco")] Param ( [Parameter(Mandatory=$False)] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [ValidateRange(1,100000)] [int]$ResultSize = 1000 ) Begin { Connect-NectarCloud } Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } $URI = "https://$Global:NectarCloud/dapi/info/external/countries" Write-Verbose $URI $Params = @{ 'pageSize' = $ResultSize } If ($SearchQuery) { $Params.Add('searchQuery',$SearchQuery) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty} $JSON.elements } Catch { Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } Function Get-NectarExtISPs { <# .SYNOPSIS Returns a list of ISPs found via IP geolocation .DESCRIPTION Most call records include the user's external IP address. Nectar DXP does a geo-IP lookup of the external IP address and stores the geographic information for later use. This command will return all the ISPs where Nectar DXP was able to successfully geolocate an external IP address. .PARAMETER SearchQuery The name of the city to locate. Can be a partial match, and may return more than one entry. .PARAMETER TenantName The name of the Nectar DXP tenant. Used in multi-tenant configurations. .PARAMETER ResultSize The number of results to return. Defaults to 10000. .EXAMPLE Get-NectarExtISPs Returns the first 1000 ISPs sorted alphabetically. .EXAMPLE Get-NectarExtISPs -ResultSize 5000 Returns the first 5000 ISPs sorted alphabetically. .EXAMPLE Get-NectarExtISPs -SearchQuery Be Returns all ISPs that contain the letters 'be' .NOTES Version 1.0 #> [Alias("gneci")] Param ( [Parameter(Mandatory=$False)] [string]$SearchQuery, [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)] [string]$TenantName, [Parameter(Mandatory=$False)] [ValidateRange(1,100000)] [int]$ResultSize = 10000 ) Begin { Connect-NectarCloud } Process { Try { # Use globally set tenant name, if one was set and not explicitly included in the command If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { $TenantName = $Global:NectarTenantName } ElseIf ($TenantName) { If ($TenantName -NotIn $Global:NectarTenantList) { $TList = $Global:NectarTenantList -join ', ' Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)" } } $URI = "https://$Global:NectarCloud/dapi/info/external/isps" Write-Verbose $URI $Params = @{ 'pageSize' = $ResultSize } If ($SearchQuery) { $Params.Add('searchQuery',$SearchQuery) } If ($TenantName) { $Params.Add('Tenant',$TenantName) } $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty} $JSON.elements } Catch { Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)" If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ } } } } ################################################################################################################################################# ################################################################################################################################################# ## ## ## Endpoint Client Functions ## ## ## ################################################################################################################################################# ################################################################################################################################################# ################################################################################################################################################# # # # Controller Connection Functions # # # |