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: 09.01.2024 - Version: 2.0
        #>

    [cmdletbinding()]
    Param(
        [Parameter(Mandatory = $true)]$uri,
        [Parameter()]$APIkey,
        [Parameter()]$Header_OkktaResponse,
        [Parameter()]$RateLimitWaitTime = 25,
        [Parameter()]$RateLimitMinimumRemaining = 5
    )
    Begin {
        $ProgressPreference = 'SilentlyContinue'
        $OktaHeader = @{
            Accept          = "application/json"
            "Content-Type"  = "application/json"
            "Authorization" = "SSWS " + $APIkey
        }
        if ($Header_OkktaResponse) {
            $OktaHeader.'okta-response' = $Header_OkktaResponse
        }
    
    }
    process {
        $functionlist = @()
        while ($null -ne $uri) {
            # Get response from API
            Try {
                # Get response from OKTA API
                $response = (Invoke-WebRequest -Method GET -Uri $uri -Headers $OktaHeader -TimeoutSec 60)
                
                # 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 for neq rate limit
                    Write-Warning "Waiting for Rate Limit [Remaining: $($response.Headers.'x-rate-limit-remaining') / Limit: $($response.Headers.'x-rate-limit-limit')] - Waiting [$($RateLimitWaitTime)] seconds"
                    Start-Sleep -Seconds $RateLimitWaitTime
                } 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") {
                    Write-Verbose "Too Many requests - Waiting [$($RateLimitWaitTime)] seconds"
                    Start-Sleep -Seconds $RateLimitWaitTime
                } else {
                    Write-Error "$($_.Exception.Message)"
                }
            }
            
            $response = $null
        }
        return $functionlist
    }
} #v2.0

Export-ModuleMember -Function *
Write-Verbose "Import-END| [$($FunctionScriptName)]"