Public/Get-InforcerBaseline.ps1
|
<# .SYNOPSIS Retrieves baseline information from the Inforcer API. Required API scope(s): Baselines.Read + Tenants.Read (only when -TenantId is a GUID or tenant name) (API key); Baselines + Tenants (only for a tenant name) permission (API client, unconfirmed). .DESCRIPTION Retrieves baseline groups and members. Optionally filter by -TenantId (owner or member). API-key login: the owner is identified by BaselineClientTenantId and members by ClientTenantId. Client-credentials login: those numeric ids do not exist; the owner is BaselineMsTenantId and members carry MsTenantId. Piped tenants (Get-InforcerTenant | Get-InforcerBaseline): the baselines are fetched once, each baseline is returned once per piped tenant it belongs to with that tenant in TenantId, and -OutputType JsonObject returns one JSON array. .PARAMETER Format Raw (default). .PARAMETER TenantId Optional. Filter baselines where this tenant is owner or member. Accepts the Microsoft Tenant ID (GUID), the tenant name, or (API-key login only) the numeric Client Tenant ID. .PARAMETER OutputType PowerShellObject (default) or JsonObject. .EXAMPLE Get-InforcerBaseline .EXAMPLE Get-InforcerBaseline -TenantId 'Contoso' Baselines owned by, or including, the tenant named Contoso (both logins). .EXAMPLE Get-InforcerBaseline -TenantId '00000000-0000-0000-0000-000000000001' Baselines owned by, or including, the tenant with this Microsoft Tenant ID (both logins). .EXAMPLE Get-InforcerBaseline -OutputType JsonObject Returns JSON string with full depth (100). .OUTPUTS PSObject or String .LINK https://github.com/royklo/InforcerCommunity/blob/main/docs/CMDLET-REFERENCE.md#get-inforcerbaseline .LINK Connect-Inforcer #> function Get-InforcerBaseline { [CmdletBinding()] [OutputType([PSObject], [string])] param( [Parameter(Mandatory = $false)] [ValidateSet('Raw')] [string]$Format = 'Raw', [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [Alias('ClientTenantId', 'MsTenantId')] [object]$TenantId, [Parameter(Mandatory = $false)] [ValidateSet('PowerShellObject', 'JsonObject')] [string]$OutputType = 'PowerShellObject' ) begin { $requestedTenantIds = [System.Collections.Generic.List[object]]::new() } process { $requestedTenantIds.Add($TenantId) } end { $piped = $PSCmdlet.MyInvocation.ExpectingInput if ($piped -and $requestedTenantIds.Count -eq 0) { return } if (-not (Test-InforcerSession)) { Write-Error -Message 'Not connected yet. Please run Connect-Inforcer first.' -ErrorId 'NotConnected' -Category ConnectionError return } Write-Verbose 'Retrieving baseline information...' $isV1 = $script:InforcerSession.ApiVersion -eq 'v1' # One fetch per call, also when tenants are piped. The list is shared with the session cache: copy before decorating. $listErr = $null $baselines = @(Get-InforcerBaselineList -Refresh -ErrorVariable listErr) if ($listErr) { return } $hasTenant = { param($p, $tid) if ($tid -is [string]) { if ("$($p.PSObject.Properties['baselineMsTenantId'].Value)" -eq $tid) { return $true } foreach ($m in @($p.PSObject.Properties['members'].Value)) { if ($m -is [PSObject] -and "$($m.PSObject.Properties['msTenantId'].Value)" -eq $tid) { return $true } } return $false } $ownerProp = $p.PSObject.Properties['baselineClientTenantId'] if ($ownerProp -and [int]$ownerProp.Value -eq $tid) { return $true } $membersProp = $p.PSObject.Properties['members'] if ($membersProp -and $membersProp.Value -is [object[]]) { foreach ($m in $membersProp.Value) { if ($m -is [PSObject]) { $cid = $m.PSObject.Properties['clientTenantId'].Value if ($null -ne $cid -and [int]$cid -eq $tid) { return $true } } } } $false } $copyOf = { param($b) $copy = [ordered]@{} foreach ($prop in $b.PSObject.Properties) { $copy[$prop.Name] = $prop.Value } [PSCustomObject]$copy } $decorate = { param($b) $null = Add-InforcerPropertyAliases -InputObject $b -ObjectType Baseline $b.PSObject.TypeNames.Insert(0, 'InforcerCommunity.Baseline') $b } if (-not $piped) { $resolvedTenantId = $null if ($null -ne $requestedTenantIds[0]) { try { $resolvedTenantId = Resolve-InforcerTenantId -TenantId $requestedTenantIds[0] -ErrorAction Stop } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidTenantId' -Category InvalidArgument return } Write-Verbose "Filtering baselines to tenant ID $resolvedTenantId..." } if ($OutputType -eq 'JsonObject') { if ($isV1) { # v1 list contract: always a JSON array, also for one match or none. $selected = @(foreach ($b in $baselines) { if ($null -eq $resolvedTenantId -or ($b -is [PSObject] -and (& $hasTenant $b $resolvedTenantId))) { $b } }) return ConvertTo-Json -InputObject $selected -Depth 100 } $json = $baselines | ConvertTo-Json -Depth 100 if ($null -eq $json) { return } if ($null -eq $resolvedTenantId) { return $json } return Filter-InforcerResponse -InputObject $json -FilterScript { param($p) & $hasTenant $p $resolvedTenantId } -OutputType JsonObject } if ($baselines.Count -eq 0) { return } $result = @(foreach ($b in $baselines) { if ($b -is [PSObject]) { & $decorate (& $copyOf $b) } else { $b } }) if ($null -ne $resolvedTenantId) { $result = Filter-InforcerResponse -InputObject $result -FilterScript { param($p) & $hasTenant $p $resolvedTenantId } -OutputType PowerShellObject } return $result } # Piped tenants: one row per (tenant, baseline), carrying the tenant in TenantId. $rows = [System.Collections.Generic.List[object]]::new() $seen = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($requested in $requestedTenantIds) { if ($null -eq $requested) { continue } $resolvedTenantId = $null if ($null -ne $requested) { try { $resolvedTenantId = Resolve-InforcerTenantId -TenantId $requested -ErrorAction Stop } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidTenantId' -Category InvalidArgument continue } } foreach ($b in $baselines) { if ($b -isnot [PSObject]) { continue } if ($null -ne $resolvedTenantId -and -not (& $hasTenant $b $resolvedTenantId)) { continue } if (-not $seen.Add("$resolvedTenantId|$($b.PSObject.Properties['id'].Value)")) { continue } $row = & $copyOf $b if ($null -ne $resolvedTenantId -and -not $row.PSObject.Properties['TenantId']) { $row.PSObject.Properties.Add([System.Management.Automation.PSNoteProperty]::new('TenantId', $resolvedTenantId)) } $rows.Add($row) } } if ($OutputType -eq 'JsonObject') { return ConvertTo-Json -InputObject @($rows) -Depth 100 } foreach ($row in $rows) { & $decorate $row } } } |