Guest User

Untitled

a guest
Oct 14th, 2025
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 7.15 KB | Source Code | 0 0
  1. #Required by the New-ClearpassUri function
  2. Add-Type -AssemblyName 'System.Web'
  3.  
  4. <#
  5. * Clearpass API functions expect these variables to be defined and reference them from $script: scope
  6.  
  7. #Connection config for Clearpass API
  8. $ClearpassConfig = @{'Hostname' = '10.121.9.9'
  9. 'HostScheme' = 'https'
  10. 'HostPort' = '443'}
  11.  
  12. #Credentials for Clearpass API
  13. $ClearpassConfig.AuthBody = @{"grant_type" = "password"
  14. "username" = "api"
  15. "password" = "password"
  16. "client_id" = "customer"}
  17.  
  18. #>
  19. $script:ClearpassTokenCache = @{'Token' = $null
  20.     'Expires' = $null}
  21.  
  22. #region api functions clearpass
  23. function Get-ClearpassToken {
  24.     <#
  25.     .SYNOPSIS
  26.         Return a Clearpass token, either from cache variable $script:ClearpassTokenCache where not expired, or fetch a new one
  27.     .OUTPUTS
  28.         String - bearer token
  29.     #>
  30.  
  31.     if($null -eq $script:ClearpassTokenCache.Token -or $script:ClearpassTokenCache.expires -lt (Get-Date)){
  32.         $Response = Invoke-ClearpassApi -Path @('oauth') -Body $global:ClearpassConfig.AuthBody -Method 'POST' -OAuth
  33.         if($null -ne $Response.access_token){
  34.             $script:ClearpassTokenCache.Token = $Response.access_token
  35.             $script:ClearpassTokenCache.Expires = (Get-Date).AddSeconds($Response.expires_in - 60)
  36.         } else {
  37.             Throw "No access token in oauth response `"$Response`""
  38.         }
  39.     }
  40.     return $script:ClearpassTokenCache.Token
  41. }
  42. function New-ClearpassUri {
  43.     <#
  44.     .SYNOPSIS
  45.         Create the URI for a Clearpass API request
  46.     .DESCRIPTION
  47.         Internal function used to build a URIBuilder object.
  48.     .PARAMETER Path
  49.         Array of strings for each segment in the URL path
  50.     .PARAMETER Query
  51.         Hashtable of query parameters to include
  52.     #>
  53.    
  54.     [CmdletBinding()]
  55.     [OutputType([System.UriBuilder])]
  56.     param
  57.     (
  58.         [Parameter(Mandatory = $false)]
  59.         [string[]]$Path,
  60.         [Parameter(Mandatory = $false)]
  61.         [hashtable]$Query
  62.     )
  63.  
  64.     Write-Debug "Building URI"
  65.  
  66.     # Begin a URI builder with HTTP/HTTPS and the provided hostname
  67.     $UriBuilder = [System.UriBuilder]::new($global:ClearpassConfig.HostScheme, $global:ClearpassConfig.Hostname, $global:ClearpassConfig.HostPort)
  68.  
  69.     # Generate the path by trimming excess slashes and whitespace from the $Path[] and joining together
  70.     $UriBuilder.Path = "api/{0}" -f ($Path.ForEach({
  71.                 $_.trim('/').trim()
  72.             }) -join '/')
  73.  
  74.     Write-Debug " URIPath: $($UriBuilder.Path)"
  75.  
  76.     if ($Query) {
  77.         # Loop through the parameters and use the HttpUtility to create a Query string
  78.         [System.Collections.Specialized.NameValueCollection]$URIParams = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
  79.  
  80.         foreach ($param in $Query.GetEnumerator()) {
  81.             Write-Debug " Adding URI parameter $($param.Key):$($param.Value)"
  82.             $URIParams[$param.Key] = $param.Value
  83.         }
  84.         $UriBuilder.Query = $URIParams.ToString()
  85.     }
  86.  
  87.     # Return the entire UriBuilder object
  88.     $UriBuilder
  89. }
  90. function Invoke-ClearpassApi {
  91.     <#
  92.     .SYNOPSIS
  93.         Execute a Clearpass API request
  94.     .DESCRIPTION
  95.         Invoke an HTTP request to the API and return results
  96.         The Get-ClearpassChunkedResult function should be used for queries which may return multiple
  97.         results, it will make multiple requests and combine results in the _embedded.items property
  98.         of the API response if required (API does not return unlimited record counts)
  99.         A set request or query which will only return 0 or 1 results can call this function directly
  100.         as the JSON response is suitable for consumption
  101.     .PARAMETER Path
  102.         Array of strings for each segment in the URL path - passed to New-ApiUri
  103.     .PARAMETER Query
  104.         Hashtable of query parameters to include - passed to New-ApiUri
  105.     .PARAMETER Headers
  106.         Hashtable of HTTP Request headers
  107.     .PARAMETER Body
  108.         Object for HTTP Request body
  109.     .PARAMETER Method
  110.         HTTP Request method
  111.     .PARAMETER OAuth
  112.         Switch - if this is the oauth token request, obviously we won't have a token
  113.     #>
  114.     [CmdletBinding()]
  115.     param
  116.     (
  117.         [Parameter(Mandatory = $false)]
  118.         [string[]]$Path,
  119.         [Parameter(Mandatory = $false)]
  120.         [hashtable]$Query,
  121.         [Hashtable]$Headers = @{},
  122.         [pscustomobject]$Body = $null,
  123.         [ValidateSet('GET', 'PATCH', 'PUT', 'POST', 'DELETE', 'OPTIONS', IgnoreCase = $true)]
  124.         [string]$Method = 'GET',
  125.         [switch]$OAuth
  126.     )
  127.  
  128.     $Uri = New-ClearpassUri -Path $Path -Query $Query
  129.  
  130.     if(!$OAuth){
  131.         $Headers.Authorization = "Bearer {0}" -f (Get-ClearpassToken)
  132.     }
  133.  
  134.     #ClearPass API was picky about this
  135.     $Headers.Accept = '*/*'
  136.  
  137.     $Splat = @{
  138.         'Method'      = $Method
  139.         'Uri'         = $URI.Uri.AbsoluteUri # This property auto generates the scheme, hostname, path, and query
  140.         'Headers'     = $Headers
  141.         'TimeoutSec'  = 180
  142.         'ContentType' = 'application/json'
  143.     }
  144.  
  145.     #BasicParsing is required on Server Core, without it Invoke-RestMethod tries to run Internet Explorer
  146.     $Splat += @{'UseBasicParsing' = $true}
  147.  
  148.     if ($Body) {
  149.         Write-Debug "BODY: $($Body | ConvertTo-Json -Compress)"
  150.         $null = $Splat.Add('Body', ($Body | ConvertTo-Json -Compress))
  151.     }
  152.  
  153.     try {
  154.         $CurrentVerbose = $VerbosePreference
  155.         $VerbosePreference = 'silentlycontinue'
  156.         $Result = Invoke-RestMethod @Splat
  157.     } catch {
  158.         Throw "Clearpass API Request failed: $($Error[0].ToString())"
  159.     } finally {
  160.         $VerbosePreference = $CurrentVerbose
  161.     }
  162.  
  163.     return $Result
  164. }
  165. function Get-ClearpassChunkedResult {
  166.     <#
  167.     .SYNOPSIS
  168.         Combine results from multiple API queries as Clearpass doesn't support unlimited result count in one request
  169.     .DESCRIPTION
  170.         Makes multiple calls to Invoke-ClearpassApi while there are still more results in the set, and returns
  171.         all resutls in a combined array
  172.         Request Method, Body and Headers are for Invoke-ClearpassAPI are omitted from this function as it's an
  173.         implicit GET and Body/Headers aren't relevant
  174.     .PARAMETER Path
  175.         Array of strings for each segment in the URL path - passed to New-ApiUri
  176.     .PARAMETER SetSize
  177.         The number of results to get per query (default to 25)
  178.     #>    
  179.     [CmdletBinding()]
  180.     param
  181.     (
  182.         [Parameter(Mandatory = $false)]
  183.         [string[]]$Path,
  184.         [Parameter(Mandatory = $false)]
  185.         [hashtable]$Query,
  186.         $SetSize = 25
  187.        
  188.     )
  189.  
  190.     $Result = [System.Collections.ArrayList]@()
  191.  
  192.     $Query['offset'] = $null
  193.     $Query['limit'] = $SetSize
  194.     do {
  195.         if($null -eq $Query['offset']){
  196.             $Query['offset'] = 0            
  197.         } else {
  198.             $Query['offset']+= $SetSize
  199.         }
  200.         Write-Debug "Performing chunked query for path: $($Path -join '/'). Offset: $($Query['offset'])"
  201.         $RawResult = Invoke-ClearpassApi -Path $Path -Query $Query
  202.         $Result.AddRange(@($RawResult.'_embedded'.'items'))
  203.     } while($null -ne $RawResult.'_links'.'next')
  204.    
  205.     return $Result
  206. }
Advertisement
Add Comment
Please, Sign In to add comment