Get-OktaURIRecursive.psm1
$FunctionScriptName = "Get-OktaURIRecursive" Write-Verbose "Import-Start| [$($FunctionScriptName)]" #* Dependencies # N/A function Get-OktaURIRecursive { <# .SYNOPSIS Get Okta API data - recursive .Description Get recursive Okta API data Uses nextLink property .NOTES AUTHOR: Ken Dobrunz // Ken.Dobrunz@skaylink.com | Direkt Gruppe LASTEDIT: 06.05.2024 - Version: 2.3 #> [cmdletbinding()] Param( [Parameter(Mandatory = $true)]$uri, [Parameter()][Alias('filter')]$QueryFilter, [Parameter()]$QueryLimit = 1000, [Parameter()]$APIkey, [Parameter()][Alias('Header_OkktaResponse')]$Header_OktaResponse, [Parameter()]$RateLimitMinimumRemaining = 5, [Parameter()]$MaxPaginationCount = 1000, [Parameter()]$TimeoutSec = 60, [Parameter()][switch]$ReturnPaginationObjectsOnly ) Begin { $ProgressPreference = 'SilentlyContinue' $OktaHeader = @{ Accept = "application/json" "Content-Type" = "application/json" "Authorization" = "SSWS " + $APIkey } # Set OktaResponse if ($Header_OktaResponse) { $OktaHeader.'okta-response' = $Header_OktaResponse } # Add Query filter if($uri -match "\?" -and $QueryFilter){ $uri = $uri + "&" + $QueryFilter }elseif($QueryFilter){ $uri = $uri + "?" + $QueryFilter } # Add limit #? Only add if not in uri if($uri -match "\?" -and $QueryLimit -and $uri -notlike "*limit=*"){ $uri = $uri + "&limit=" + $QueryLimit }elseif($QueryLimit -and $uri -notlike "*limit=*"){ $uri = $uri + "?limit=" + $QueryLimit } } process { $functionlist = @(); $PaginationCount = 0 while ($null -ne $uri) { # Get response from API Try { # Get response from OKTA API $response = $null $response = (Invoke-WebRequest -Method GET -Uri $uri -Headers $OktaHeader -TimeoutSec $TimeoutSec) # Rate Limit / Pagination Write-Debug "Rate Limit: [Remaining: $($response.Headers.'x-rate-limit-remaining') / Limit: $($response.Headers.'x-rate-limit-limit')] - QRY Limit: $($RateLimitMinimumRemaining)" if ([int]($response.Headers.'x-rate-limit-remaining')[0] -le $RateLimitMinimumRemaining) { # Wait until "x-rate-limit-reset" $RateLimitWaitSeconds = ($response.Headers.'x-rate-limit-reset')[0] - (([DateTimeOffset](($response.Headers.'date')[0])).ToUnixTimeSeconds()) Write-Warning "Waiting for Rate Limit [Remaining: $($response.Headers.'x-rate-limit-remaining') / Limit: $($response.Headers.'x-rate-limit-limit')] - Waiting [$($RateLimitWaitSeconds)] seconds" Start-Sleep -Seconds $RateLimitWaitSeconds } else { # Pagination - Skipping current turn to ensure clean data $functionlist = $functionlist + ($response.content | ConvertFrom-Json) if ($null -ne ($response.RelationLink.next)) { $uri = $response.RelationLink.next } else { $uri = $null } } } catch { # Check for error & Rate limit if ($_.Exception.StatusCode -eq "TooManyRequests") { # Wait until "x-rate-limit-reset" $ErrorHeaderResetTime = ($_.Exception.Response.Headers).GetValues('x-rate-limit-reset') $ErrorHeaderDateTime = ($_.Exception.Response.Headers).GetValues('date') $RateLimitWaitSeconds = ($ErrorHeaderResetTime)[0] - (([DateTimeOffset](($ErrorHeaderDateTime)[0])).ToUnixTimeSeconds()) Write-Warning "Too Many requests - Waiting [$($RateLimitWaitSeconds)] seconds" Start-Sleep -Seconds $RateLimitWaitSeconds } else { $TryError = $_.Exception Write-Error "ERROR: [$($TryError.StatusCode.value__)] $($TryError.StatusCode) @ [$($uri)]" Write-Debug "$($_.Exception.Message)" $uri = $null } } # Stop pagination $PaginationCount++ if ($PaginationCount -ge $MaxPaginationCount) { $uri = $null Write-Warning "Paginationlimit of [$MaxPaginationCount] reached - Ignoring additional responses" if ($ReturnPaginationObjectsOnly -eq $true) { return $functionlist } else { return [ordered]@{ Message = "Paginationlimit of [$MaxPaginationCount] reached - Ignoring additional responses" MaxPaginationCount = $MaxPaginationCount ObjectCount = (($functionlist.count) + 0) Objects = $functionlist } } } } return $functionlist } } #v2.3 Export-ModuleMember -Function * Write-Verbose "Import-END| [$($FunctionScriptName)]" |