@@ -13,229 +13,31 @@ function Invoke-ListTenantAlignment {
1313 $APIName = $Request.Params.CIPPEndpoint
1414 $Headers = $Request.Headers
1515
16- # Get all standard templates
17- $TemplateTable = Get-CippTable - tablename ' templates'
18- $TemplateFilter = " PartitionKey eq 'StandardsTemplateV2'"
19- $Templates = (Get-CIPPAzDataTableEntity @TemplateTable - Filter $TemplateFilter ) | ForEach-Object {
20- $JSON = $_.JSON -replace ' "Action":' , ' "action":'
21- try {
22- $RowKey = $_.RowKey
23- $Data = $JSON | ConvertFrom-Json - Depth 100 - ErrorAction SilentlyContinue
24- } catch {
25- Write-Host " $ ( $RowKey ) standard could not be loaded: $ ( $_.Exception.Message ) "
26- return
27- }
28- if ($Data ) {
29- $Data | Add-Member - NotePropertyName ' GUID' - NotePropertyValue $_.GUID - Force
30- $Data
31- }
32- }
33-
34- # Get standards comparison data using the same pattern as ListStandardsCompare
35- $StandardsTable = Get-CIPPTable - TableName ' CippStandardsReports'
36- $Standards = Get-CIPPAzDataTableEntity @StandardsTable
37-
38- # Build tenant standards data structure like in ListStandardsCompare
39- $TenantStandards = @ {}
40- foreach ($Standard in $Standards ) {
41- $FieldName = $Standard.RowKey
42- $FieldValue = $Standard.Value
43- $Tenant = $Standard.PartitionKey
44-
45- # Process field value like in ListStandardsCompare
46- if ($FieldValue -is [System.Boolean ]) {
47- $FieldValue = [bool ]$FieldValue
48- } elseif ($FieldValue -like ' *{*' ) {
49- $FieldValue = ConvertFrom-Json - InputObject $FieldValue - ErrorAction SilentlyContinue
50- } else {
51- $FieldValue = [string ]$FieldValue
52- }
53-
54- if (-not $TenantStandards.ContainsKey ($Tenant )) {
55- $TenantStandards [$Tenant ] = @ {}
56- }
57- $TenantStandards [$Tenant ][$FieldName ] = @ {
58- Value = $FieldValue
59- LastRefresh = $Standard.TimeStamp.ToUniversalTime ().ToString(' yyyy-MM-ddTHH:mm:ssZ' )
60- }
61- }
62-
63- $Results = [System.Collections.Generic.List [object ]]::new()
64-
65- # Process each template against all tenants
66- foreach ($Template in $Templates ) {
67- $TemplateStandards = $Template.standards
68- if (-not $TemplateStandards ) {
69- continue
70- }
71-
72- # Check if template has tenant assignments (scope)
73- $TemplateAssignedTenants = @ ()
74- $AppliestoAllTenants = $false
75-
76- if ($Template.tenantFilter -and $Template.tenantFilter.Count -gt 0 ) {
77- # Extract tenant values from the tenantFilter array
78- $TenantValues = $Template.tenantFilter | ForEach-Object { $_.value }
79-
80- if ($TenantValues -contains ' AllTenants' ) {
81- $AppliestoAllTenants = $true
82- Write-Host " Template '$ ( $Template.templateName ) ' applies to all tenants (AllTenants)"
83- } else {
84- $TemplateAssignedTenants = $TenantValues
85- Write-Host " Template '$ ( $Template.templateName ) ' is assigned to specific tenants: $ ( $TemplateAssignedTenants -join ' , ' ) "
86- }
87- } else {
88- $AppliestoAllTenants = $true
89- Write-Host " Template '$ ( $Template.templateName ) ' applies to all tenants (no tenantFilter)"
90- }
91-
92- $AllStandards = [System.Collections.Generic.List [string ]]::new()
93- $ReportingEnabledStandards = [System.Collections.Generic.List [string ]]::new()
94- $ReportingDisabledStandards = [System.Collections.Generic.List [string ]]::new()
95-
96- foreach ($StandardKey in $TemplateStandards.PSObject.Properties.Name ) {
97- $StandardConfig = $TemplateStandards .$StandardKey
98- $StandardId = " standards.$StandardKey "
99-
100-
101- $Actions = @ ()
102- if ($StandardConfig.action ) {
103- $Actions = $StandardConfig.action
104- } elseif ($StandardConfig.Action ) {
105- $Actions = $StandardConfig.Action
106- } elseif ($StandardConfig.PSObject.Properties [' action' ]) {
107- $Actions = $StandardConfig.PSObject.Properties [' action' ].Value
108- }
109-
110- $ReportingEnabled = $false
111- if ($Actions -and $Actions.Count -gt 0 ) {
112- $ReportingEnabled = ($Actions | Where-Object { $_.value -and ($_.value.ToLower () -eq ' report' -or $_.value.ToLower () -eq ' remediate' ) }).Count -gt 0
113- }
114-
115- $AllStandards.Add ($StandardId )
116-
117- if ($ReportingEnabled ) {
118- $ReportingEnabledStandards.Add ($StandardId )
119- } else {
120- $ReportingDisabledStandards.Add ($StandardId )
121- }
122-
123- if ($StandardKey -eq ' IntuneTemplate' -and $StandardConfig -is [array ]) {
124- $AllStandards.Remove ($StandardId )
125- if ($ReportingEnabled ) {
126- $ReportingEnabledStandards.Remove ($StandardId )
127- } else {
128- $ReportingDisabledStandards.Remove ($StandardId )
129- }
130-
131- foreach ($IntuneTemplate in $StandardConfig ) {
132- if ($IntuneTemplate.TemplateList.value ) {
133- $IntuneStandardId = " standards.IntuneTemplate.$ ( $IntuneTemplate.TemplateList.value ) "
134-
135- $IntuneActions = if ($IntuneTemplate.action ) { $IntuneTemplate.action } else { @ () }
136- $IntuneReportingEnabled = ($IntuneActions | Where-Object { $_.value -and ($_.value.ToLower () -eq ' report' -or $_.value.ToLower () -eq ' remediate' ) }).Count -gt 0
137-
138- $AllStandards.Add ($IntuneStandardId )
139-
140- if ($IntuneReportingEnabled ) {
141- $ReportingEnabledStandards.Add ($IntuneStandardId )
142- } else {
143- $ReportingDisabledStandards.Add ($IntuneStandardId )
144- }
145- }
146- }
147- }
148- }
149-
150- foreach ($TenantName in $TenantStandards.Keys ) {
151- if (-not $AppliestoAllTenants -and $TenantName -notin $TemplateAssignedTenants ) {
152- Write-Host " Skipping tenant '$TenantName ' for template '$ ( $Template.templateName ) ' - not in assigned tenant list"
153- continue
154- }
155- $AllCount = $AllStandards.Count
156-
157- $CompliantStandards = 0
158- $NonCompliantStandards = 0
159- $ReportingDisabledStandardsCount = 0
160- $LatestDataCollection = $null
161- $ComparisonTable = @ ()
162-
163- foreach ($StandardKey in $AllStandards ) {
164- $IsReportingDisabled = $ReportingDisabledStandards -contains $StandardKey
165-
166- if ($TenantStandards [$TenantName ].ContainsKey($StandardKey )) {
167- $StandardObject = $TenantStandards [$TenantName ][$StandardKey ]
168- $Value = $StandardObject.Value
169-
170- if ($StandardObject.LastRefresh ) {
171- $RefreshTime = [DateTime ]::Parse($StandardObject.LastRefresh )
172- if (-not $LatestDataCollection -or $RefreshTime -gt $LatestDataCollection ) {
173- $LatestDataCollection = $RefreshTime
174- }
175- }
176-
177- $IsCompliant = ($Value -eq $true )
178-
179- if ($IsReportingDisabled ) {
180- $ReportingDisabledStandardsCount ++
181- $ComplianceStatus = ' Reporting Disabled'
182- } elseif ($IsCompliant ) {
183- $CompliantStandards ++
184- $ComplianceStatus = ' Compliant'
185- } else {
186- $NonCompliantStandards ++
187- $ComplianceStatus = ' Non-Compliant'
188- }
189-
190- $ComparisonTable += [PSCustomObject ]@ {
191- StandardName = $StandardKey
192- Compliant = $IsCompliant
193- StandardValue = ($Value | ConvertTo-Json - Compress)
194- ComplianceStatus = $ComplianceStatus
195- ReportingDisabled = $IsReportingDisabled
196- }
197- } else {
198- if ($IsReportingDisabled ) {
199- $ReportingDisabledStandardsCount ++
200- $ComplianceStatus = ' Reporting Disabled'
201- } else {
202- $NonCompliantStandards ++
203- $ComplianceStatus = ' Non-Compliant'
204- }
205-
206- $ComparisonTable += [PSCustomObject ]@ {
207- StandardName = $StandardKey
208- Compliant = $false
209- StandardValue = ' NOT FOUND'
210- ComplianceStatus = $ComplianceStatus
211- ReportingDisabled = $IsReportingDisabled
212- }
213- }
214- }
215-
216-
217- $AlignmentPercentage = if (($AllCount - $ReportingDisabledStandardsCount ) -gt 0 ) {
218- [Math ]::Round(($CompliantStandards / ($AllCount - $ReportingDisabledStandardsCount )) * 100 )
219- } else {
220- 0
221- }
222-
223- $TenantOnlyStandards = $TenantStandards [$TenantName ].Keys | Where-Object { $_ -notin $AllStandards }
224-
225- $Result = [PSCustomObject ]@ {
226- tenantFilter = $TenantName
227- standardName = $Template.templateName
228- standardId = $Template.GUID
229- alignmentScore = $AlignmentPercentage
230- latestDataCollection = if ($LatestDataCollection ) { $LatestDataCollection } else { $null }
231- }
232-
233- $Results.Add ($Result )
234- }
16+ try {
17+ # Use the new Get-CIPPTenantAlignment function to get alignment data
18+ $AlignmentData = Get-CIPPTenantAlignment
19+
20+ # Transform the data to match the expected API response format
21+ $Results = $AlignmentData | ForEach-Object {
22+ [PSCustomObject ]@ {
23+ tenantFilter = $_.TenantFilter
24+ standardName = $_.StandardName
25+ standardId = $_.StandardId
26+ alignmentScore = $_.AlignmentScore
27+ LicenseMissingPercentage = $_.LicenseMissingPercentage
28+ latestDataCollection = $_.LatestDataCollection
29+ }
30+ }
31+
32+ Push-OutputBinding - Name Response - Value ([HttpResponseContext ]@ {
33+ StatusCode = [HttpStatusCode ]::OK
34+ Body = @ ($Results )
35+ })
36+ } catch {
37+ Write-LogMessage - API $APIName - message " Failed to get tenant alignment data: $ ( $_.Exception.Message ) " - sev Error
38+ Push-OutputBinding - Name Response - Value ([HttpResponseContext ]@ {
39+ StatusCode = [HttpStatusCode ]::InternalServerError
40+ Body = @ { error = " Failed to get tenant alignment data: $ ( $_.Exception.Message ) " }
41+ })
23542 }
236-
237- Push-OutputBinding - Name Response - Value ([HttpResponseContext ]@ {
238- StatusCode = [HttpStatusCode ]::OK
239- Body = @ ($Results )
240- })
24143}
0 commit comments