cancel
Showing results for 
Search instead for 
Did you mean: 

[PowerShell] Location Based Dynamic System Groups - New Systems

shawnsong
Rising Star II
Rising Star II

It all came down from my colleague Rodger asked me a possibility if we can automatically add a system to a system group according to it's physical location.

Well, the short answer we concluded is - YES! So, here is the how 🙂

A few callouts before we jump to it:

Scenario

* Encouraged to run this script on a schedule - ideally at least once a day.
* This script is suitable (but not tailored) to run as AWS Lambda functions, Azure functions (recommended), or on any server / VM / device which tasked to run jobs (less favourable).

Caveats

* Simply change the variable "backTracingDays" to any number of days suitable in your env.
* Set a large number of "backTracingDays" (like 10000) if you are running this for the first time, from your workstation ideally.
* Use a staggered approach by setting the "backTracingDays" if you have a large number of flee. - i.e. first do 10 days back, then 20 days back etc.
* Location info is fetched by "remoteIP" of the system and a query to http://ip-api.com/json/[IPAddress]

 

 

 

 

# a function to query the geo info from an IP supplied
function Get-IPGeolocation {
    Param
    (
      [string]$IPAddress
    )
   
    $request = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$IPAddress"
   
    [PSCustomObject]@{
      IP      = $request.query
      City    = $request.city
      Country = $request.country
      Isp     = $request.isp
    }
  }

# Setting the dates - depends on how often you run this
[int32]$backTracingDays = 1 # Recommended schedule
$anchorDate = (Get-Date -Hour 23 -Minute 59 -Second 59).AddDays(-$backTracingDays)

# Getting the system only created after the backtracingdays
$jcsystemInfo = Get-JCSystem | where {$_.created -gt $anchorDate}

# Adding the systems to these geo related groups
if ($null -ne $jcsystemInfo){
    foreach ($system in $jcsystemInfo){
        $geolocation = Get-IPGeolocation -IPAddress $system.remoteIP
    
        $targetGroup = $geolocation.Country.Replace(' ','') + "_" + $system.osFamily
        
        # Adding the system to the target group
        $testGroup = Get-JCGroup -Type System -Name $targetGroup -ErrorAction SilentlyContinue
        $testMember = Get-JCSystemGroupMember -GroupName $targetGroup | where system -eq $system.displayName
    
        if ($null -eq $testGroup){
            $newGroup = New-JCSystemGroup -GroupName $targetGroup
            Add-JCSystemGroupMember -GroupID $newGroup.id -SystemID $system._id 
            Write-Output "$($system.displayname) has been added to $($newgroup.name) system group! `n "
    
        }
        elseif ($null -ne $testGroup -and $null -eq $testMember) {
            Add-JCSystemGroupMember -GroupID $testGroup.id -SystemID $system._id
            Write-Output "$($system.displayname) has been added to $($testGroup.name) system group! `n "
        }
        else {
            Write-Output "$($system.displayname) already exists in $($testGroup.name) system group! `n "
        }
    }
}
else {
    Write-Output "Phew! No systems has been create for the past $backTracingDays days, take a day off!"
}

 

 

4 REPLIES 4

shawnsong
Rising Star II
Rising Star II

To add-on why are we doing this, imagine the benefit for having the system groups:

* You have a set of country specific software / app to deploy - i.e. a call-center client, engineering tools etc
* Country specific HR systems.
* Country / region specific security policies.
* And many many more.

BrightRodger
JumpCloud Employee
JumpCloud Employee

Thanks @shawnsong for writing this. This will really allow some simple and important automation. If you are an IT admin at a multinational company and have policies that are specific to each country, or os patching policies, even (as you stated above), specific software you would like to install based on country location this is a super clean and elegant way to handle it.

shawnsong
Rising Star II
Rising Star II

Thanks Rodger 😀 and appreciated for the offline proof reading too.

So to add on a bit:

1. The automated system group naming can be customised in line here:

$targetGroup = $geolocation.Country.Replace(' ','') + "_" + $system.osFamily

2. Suggest to use the similar / same naming convention on the policies (or policy group), which you can automate the binding in pwsh too, despite the frequency of this automation is significantly lower (probably just once).

3. For "backTracingDays" variable - It will track only the new devices created in the number of days you defined. This is to avoid moving the existing device around the groups in the context of travelling etc.

shawnsong
Rising Star II
Rising Star II

4. this is how it look like of the automated groupsimage (2).png