Public/Get-InforcerSecureScore.ps1
|
function Get-InforcerSecureScore { <# .SYNOPSIS Retrieves the current and historic secure score for an Inforcer tenant. Required API scope(s): Tenants.SecureScores.Read + Tenants.Read (only when -TenantId is a GUID or tenant name) (API key); Entra Dashboard + Tenants (only for a tenant name) permission (API client, unconfirmed). .DESCRIPTION Gets secure score data for a tenant from GET /tenants/{tenantId}/secureScores (beta or v1, by login type). Returns the current score, max score, licensed user count, enabled services, up to 90 days of daily score history, per-category scores, and actionable control profiles with remediation guidance. .PARAMETER TenantId The Inforcer tenant ID. Accepts numeric ID (API-key login only), Microsoft tenant GUID, or tenant name. Supports pipeline input. .PARAMETER OutputType Output type: 'PowerShellObject' (default) or 'JsonObject'. Piped tenants: each result carries TenantId and JsonObject returns one array for all tenants. .EXAMPLE Get-InforcerSecureScore -TenantId 'Contoso' Returns the secure score summary for the tenant Contoso. .EXAMPLE (Get-InforcerSecureScore -TenantId 'Contoso').Scores Returns the 90-day daily score history. .EXAMPLE (Get-InforcerSecureScore -TenantId 'Contoso').ControlProfiles | Sort-Object ScoreDifference -Descending | Select-Object -First 10 Lists the 10 controls with the largest gap between current and max score. .EXAMPLE $s = Get-InforcerSecureScore -TenantId 'Contoso' $s.ControlProfiles | Where-Object ScoreDifference -gt 0 | Group-Object ControlCategory | Select-Object Name, Count, @{n='TotalGain';e={($_.Group | Measure-Object ScoreDifference -Sum).Sum}} Groups open recommendations by category with total potential score gain per category. .EXAMPLE $s = Get-InforcerSecureScore -TenantId 'Contoso' ($s.ControlCategoryScores | Where-Object ControlCategory -eq 'Identity').HistoricScores | Format-Table CreatedDateTime, CurrentScore, MaxScore, CurrentScorePercentage -AutoSize Shows the daily Identity category history for the tenant. .EXAMPLE Get-InforcerTenant -TenantId 'Contoso' | Get-InforcerSecureScore Retrieves secure scores for the piped tenant. .EXAMPLE Get-InforcerSecureScore -TenantId 'Contoso' -OutputType JsonObject Returns the response as a JSON string. .OUTPUTS PSObject or String (when -OutputType JsonObject) .LINK https://github.com/royklo/InforcerCommunity/blob/main/docs/CMDLET-REFERENCE.md#get-inforcersecurescore .LINK Connect-Inforcer #> [CmdletBinding()] [OutputType([PSObject], [string])] param( [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [Alias('ClientTenantId', 'MsTenantId')] [object]$TenantId, [Parameter(Mandatory = $false)] [ValidateSet('PowerShellObject', 'JsonObject')] [string]$OutputType = 'PowerShellObject' ) begin { $pipedJson = [System.Collections.Generic.List[object]]::new() } process { if (-not (Test-InforcerSession)) { Write-Error -Message "Not connected to Inforcer. Use Connect-Inforcer first." -ErrorId 'NotConnected' -Category ConnectionError return } try { $resolvedTenantId = Resolve-InforcerTenantId -TenantId $TenantId } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidTenantId' -Category InvalidArgument return } $endpoint = "/tenants/$resolvedTenantId/secureScores" Write-Verbose "Retrieving secure score for tenant $resolvedTenantId..." # -PreserveStructure prevents Invoke-InforcerApiRequest from unwrapping the first array # property of .data. The secure-score payload is a single object whose interesting # content sits in its `scores`, `controlProfiles`, and `controlCategoryScores` arrays — # without -PreserveStructure the caller would receive one of those inner arrays instead # of the top-level tenantSecureScoreDetails object. $response = Invoke-InforcerApiRequest -Endpoint $endpoint -Method GET -OutputType PowerShellObject -PreserveStructure -ObjectType SecureScore if ($null -eq $response) { return } $piped = $PSCmdlet.MyInvocation.ExpectingInput if ($piped -and $response -is [PSObject] -and -not $response.PSObject.Properties['TenantId']) { $response.PSObject.Properties.Add([System.Management.Automation.PSNoteProperty]::new('TenantId', $resolvedTenantId)) } if ($OutputType -eq 'JsonObject') { if ($piped) { $pipedJson.Add($response); return } return ($response | ConvertTo-Json -Depth 100) } if ($response -is [PSObject]) { $null = Add-InforcerPropertyAliases -InputObject $response -ObjectType SecureScore $response.PSObject.TypeNames.Insert(0, 'InforcerCommunity.SecureScore') foreach ($cp in @($response.controlProfiles)) { if ($cp -is [PSObject]) { $cp.PSObject.TypeNames.Insert(0, 'InforcerCommunity.SecureScoreControlProfile') } } } $response } end { if ($PSCmdlet.MyInvocation.ExpectingInput -and $OutputType -eq 'JsonObject' -and (Test-InforcerSession)) { ConvertTo-Json -InputObject @($pipedJson) -Depth 100 } } } |