Search code examples
powershelloktaokta-api

Powershell Script for Okta API to add single group to Multiple Apps


I have a group called Group1 and I have approx 50-60 similar apps that contain the same name like "ABC-423", "ABC-4242" etc.

What i want is to add this single group(Group-1) to this different apps "ABC*" by using Okta API with Powershell (API - https://github.com/gabrielsroka/OktaAPI.psm1)

here is the code I wrote so far

#Purpose of Code : We want to Add Group named GRPS1 to Okta Apps that's name contains ABC
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# [1] Connect to Okta. Do this before making any other calls. - done
Connect-Okta "<redacted>" "https://yourorg.oktapreview.com"
$url = "https://yourorg.oktapreview.com" 
$appdata = @()
$groupid = "00gtx2yruqKg9diIJ0h7" #00gtx2yruqKg9diIJ0h7 => GRPS1
$group = 0
$i=0
$j=0
#Function to Get all Active OKTA Application List
function Get-AllActiveApps($url)
{ 
   # [2] Now we want to Store JSON data from $appdata to Powershell Object - done
   $appdata = @(Invoke-Method GET "/api/v1/apps?status eq 'Active'")   
   foreach($i in $appdata[0].label)
   {
      # [3.1] Use a For loop to get one by one application object checked with name contaning ABC
      if ($i -like '*ABC*') 
      {
         # [3.2] Assign Group to all apps that's name contains ABC
         $appnumber = $appdata[0][$j].id
         Add-OktaAppGroup($appnumber,$groupid,$group)
      }
      else 
      {
    
      }
      $j++
   }
}
Get-AllActiveApps($url)

The problem is at function Add-OktaAppGroup($appnumber,$groupid,$group) because the loop it is passing all application-ids as one single array and the function can only process one group id at a time

Can anyone help how to solve this?


Solution

  • Your Get-AllActiveApps function is pretty much useless. After taking out all the parts that don't have anything to do with the task of getting all active apps, we would be left with

    function Get-AllActiveApps
    { 
        Invoke-Method GET '/api/v1/apps?filter=status eq "Active"'
    }
    

    and that function already exists in OktaAPI.psm1, in a better form:

    function Get-OktaApps($filter, $limit = 20, $expand, $url = "/api/v1/apps?filter=$filter&limit=$limit&expand=$expand&q=$q", $q)
    {
         # ...
    }
    

    So let's use this instead, with the -filter parameter.

    The rest of your task (filtering some more, and doing something for each item) is PowerShell 101. You don't need any custom functions or loops for that, a pipeline is enough:

    Connect-Okta -baseUrl "https://yourorg.oktapreview.com" -token "<redacted>"
    
    # using a hash for group IDs allows easy reference in the rest of the code
    $groups = @{
        GRPS1 = "00gtx2yruqKg9diIJ0h7"
    }
    
    $activeApps = Get-OktaApps -filter 'status eq "ACTIVE"' -limit 200
    
    $activeApps.objects | Where-Object label -like '*ABC*' | Where-Object {
        $appGroups = Get-OktaAppGroups -appid $_.id -limit 200
        $appGroups.objects.id -notcontains $groups.GRPS1
    } | ForEach-Object {
        Add-OktaAppGroup -appid $_.id -groupid $groups.GRPS1
    }
    

    Notes

    • You don't need to set the [Net.ServicePointManager]::SecurityProtocol, Connect-Okta already does that.
    • App groups are not part of the API response when you get a list of apps, that's why the second Where-Object fetches the app groups for each app.
    • $appGroups.objects.id will be an array of the IDs of all returned groups. -notcontains $groups.GRPS1 produces $true or $false, depending. This will be the filter criterion for Where-Object, i.e. "all apps where the list of group IDs does not contain that particular ID".
    • Many Okta API responses are paged. 200 objects per page seems to be the upper limit, as per the API documentation. Pay attention to situations where there are more objects than that. Read the documentation to OktaAPI.psm1 to learn how to handle these cases, because the code above does not.
    • You should probably add some debugging output. Read about Write-Debug and the $DebugPreference global variable.