Skip to content

Commit 0152412

Browse files
authored
Merge pull request #83 from KelvinTegelaar/master
[pull] master from KelvinTegelaar:master
2 parents 4bad972 + bd676d3 commit 0152412

68 files changed

Lines changed: 688 additions & 257994 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Config/intuneCollection.json

Lines changed: 1 addition & 257816 deletions
Large diffs are not rendered by default.

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogSearchCreation.ps1

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@ function Push-AuditLogSearchCreation {
1010
$Tenant = $Item.Tenant
1111
$StartTime = $Item.StartTime
1212
$EndTime = $Item.EndTime
13-
$ServiceFilters = @($Item.ServiceFilters)
14-
1513
try {
1614
$LogSearch = @{
1715
StartTime = $StartTime
1816
EndTime = $EndTime
19-
ServiceFilters = $ServiceFilters
2017
TenantFilter = $Tenant.defaultDomainName
2118
ProcessLogs = $true
2219
RecordTypeFilters = @(
@@ -30,6 +27,8 @@ function Push-AuditLogSearchCreation {
3027
$NewSearch = New-CippAuditLogSearch @LogSearch
3128
if ($NewSearch.id) {
3229
Write-Information "Created audit log search $($Tenant.defaultDomainName) - $($NewSearch.displayName)"
30+
} elseif ($NewSearch.cippStatus -eq 'TransientError') {
31+
Write-Information "Audit log search creation hit transient error for tenant $($Tenant.defaultDomainName) ($($NewSearch.status))"
3332
} elseif ($NewSearch.status -eq 'AuditingDisabledTenant') {
3433
Write-Information "Skipping audit log search $($Tenant.defaultDomainName) because unified auditing is disabled for this tenant"
3534
Write-LogMessage -API 'Audit Logs' -Message "Skipped audit log search creation for tenant $($Tenant.defaultDomainName) because unified auditing is disabled" -Sev Warning -tenant $Tenant.defaultDomainName

Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function Get-CippAuditLogSearches {
2020
$PendingQueries = Get-CIPPAzDataTableEntity @AuditLogSearchesTable -Filter "PartitionKey eq 'Search' and Tenant eq '$TenantFilter' and (CippStatus eq 'Pending' or (CippStatus eq 'Processing' and Timestamp le datetime'$15MinutesAgo')) and Timestamp ge datetime'$1DayAgo'" | Sort-Object Timestamp
2121
} else {
2222
$7DaysAgo = (Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
23-
$PendingQueries = Get-CIPPAzDataTableEntity @AuditLogSearchesTable -Filter "Tenant eq '$TenantFilter' and Timestamp ge datetime'$7DaysAgo'"
23+
$PendingQueries = Get-CIPPAzDataTableEntity @AuditLogSearchesTable -Filter "PartitionKey eq 'Search' and Tenant eq '$TenantFilter' and Timestamp ge datetime'$7DaysAgo'"
2424
}
2525

2626
$BulkRequests = foreach ($PendingQuery in $PendingQueries) {

Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ function New-CippAuditLogSearch {
1616
The record types to filter on.
1717
.PARAMETER KeywordFilter
1818
The keyword to filter on.
19-
.PARAMETER ServiceFilter
20-
The service to filter on.
2119
.PARAMETER OperationsFilters
2220
The operations to filter on.
2321
.PARAMETER UserPrincipalNameFilters
@@ -109,8 +107,6 @@ function New-CippAuditLogSearch {
109107
[Parameter()]
110108
[string]$KeywordFilters,
111109
[Parameter()]
112-
[string[]]$ServiceFilters,
113-
[Parameter()]
114110
[string[]]$OperationsFilters,
115111
[Parameter()]
116112
[string[]]$UserPrincipalNameFilters,
@@ -130,16 +126,13 @@ function New-CippAuditLogSearch {
130126
filterEndDateTime = $EndTime.AddHours(1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss')
131127
}
132128
if ($OperationsFilters) {
133-
$SearchParams.operationsFilters = $OperationsFilters
129+
$SearchParams.operationFilters = @($OperationsFilters)
134130
}
135131
if ($RecordTypeFilters) {
136132
$SearchParams.recordTypeFilters = @($RecordTypeFilters)
137133
}
138134
if ($KeywordFilters) {
139-
$SearchParams.keywordFilters = $KeywordFilters
140-
}
141-
if ($ServiceFilters) {
142-
$SearchParams.serviceFilters = $ServiceFilters
135+
$SearchParams.keywordFilter = $KeywordFilters
143136
}
144137
if ($UserPrincipalNameFilters) {
145138
$SearchParams.userPrincipalNameFilters = @($UserPrincipalNameFilters)
@@ -151,7 +144,7 @@ function New-CippAuditLogSearch {
151144
$SearchParams.objectIdFilters = @($ObjectIdFilters)
152145
}
153146
if ($AdministrativeUnitFilters) {
154-
$SearchParams.administrativeUnitFilters = @($AdministrativeUnitFilters)
147+
$SearchParams.administrativeUnitIdFilters = @($AdministrativeUnitFilters)
155148
}
156149

157150
if ($PSCmdlet.ShouldProcess('Create a new audit log search for tenant ' + $TenantFilter)) {
@@ -193,26 +186,26 @@ function New-CippAuditLogSearch {
193186
# Handle HTML error pages (e.g. Azure Front Door 502/504 gateway timeouts)
194187
if ($TrimmedAuditLogErrorMessage -match '<!DOCTYPE|<html' -and $TrimmedAuditLogErrorMessage -match '<title>([^<]+)</title>') {
195188
$HtmlTitle = $Matches[1].Trim()
196-
Write-LogMessage -API 'Audit Logs' -tenant $TenantFilter -message "Audit log search creation failed with gateway error for tenant $TenantFilter ($HtmlTitle) - will retry next cycle" -sev Warning
189+
Write-LogMessage -API 'Audit Logs' -tenant $TenantFilter -message "Audit log search creation failed with gateway error for tenant $TenantFilter ($HtmlTitle)" -sev Warning
197190
return [PSCustomObject]@{
198191
id = $null
199192
displayName = [string]$DisplayName
200193
status = [string]'GatewayError'
201194
cippStatus = [string]'TransientError'
202-
message = [string]"Microsoft returned gateway error ($HtmlTitle) - search will be retried next cycle."
195+
message = [string]"Microsoft returned gateway error ($HtmlTitle)."
203196
}
204197
}
205198

206199
# Handle Microsoft-side timeouts / transient errors (e.g. UnknownError with empty message)
207200
$ErrorCode = $AuditLogError.error.code ?? $AuditLogError.code
208201
if ($ErrorCode -in @('UnknownError', 'ServiceUnavailable', 'RequestTimeout', 'GatewayTimeout', 'TooManyRequests')) {
209-
Write-LogMessage -API 'Audit Logs' -tenant $TenantFilter -message "Audit log search creation failed with transient error for tenant $TenantFilter ($ErrorCode) - will retry next cycle" -sev Warning
202+
Write-LogMessage -API 'Audit Logs' -tenant $TenantFilter -message "Audit log search creation failed with transient error for tenant $TenantFilter ($ErrorCode)" -sev Warning
210203
return [PSCustomObject]@{
211204
id = $null
212205
displayName = [string]$DisplayName
213206
status = [string]$ErrorCode
214207
cippStatus = [string]'TransientError'
215-
message = [string]"Microsoft returned $ErrorCode - search will be retried next cycle."
208+
message = [string]"Microsoft returned $ErrorCode."
216209
}
217210
}
218211

Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,13 @@ function New-CIPPAPIConfig {
192192
if ($ResetSecret.IsPresent -and $APIApp) {
193193
if ($PSCmdlet.ShouldProcess($APIApp.displayName, 'Reset API Secret')) {
194194
$Step = 'Resetting Application Password'
195-
Write-Information 'Removing all old passwords'
195+
196+
try {
197+
$PolicyUpdate = Update-AppManagementPolicy -ApplicationId $APIApp.appId
198+
Write-Information "Policy check for secret reset: $($PolicyUpdate.PolicyAction)"
199+
} catch {
200+
Write-Information "Failed to update app management policy during secret reset: $($_.Exception.Message)"
201+
}
196202

197203
$AppManagementPolicy = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/policies/defaultAppManagementPolicy' -AsApp $true -NoAuthCheck $true
198204
$PasswordExpirationPolicy = $AppManagementPolicy.applicationRestrictions.passwordcredentials |
@@ -207,39 +213,50 @@ function New-CIPPAPIConfig {
207213
$NewPasswordCredential.endDateTime = $ExpirationDate
208214
}
209215

210-
$Requests = @(
211-
@{
212-
id = 'removeOldPasswords'
213-
method = 'PATCH'
214-
url = "applications/$($APIApp.id)/"
215-
headers = @{
216-
'Content-Type' = 'application/json'
217-
}
218-
body = @{
219-
passwordCredentials = @()
220-
}
221-
},
222-
@{
223-
id = 'addNewPassword'
224-
method = 'POST'
225-
url = "applications/$($APIApp.id)/addPassword"
226-
headers = @{
227-
'Content-Type' = 'application/json'
216+
Write-Information 'Removing all old passwords'
217+
for ($Attempt = 1; $Attempt -le 6; $Attempt++) {
218+
$Requests = @(
219+
@{
220+
id = 'removeOldPasswords'
221+
method = 'PATCH'
222+
url = "applications/$($APIApp.id)/"
223+
headers = @{
224+
'Content-Type' = 'application/json'
225+
}
226+
body = @{
227+
passwordCredentials = @()
228+
}
229+
},
230+
@{
231+
id = 'addNewPassword'
232+
method = 'POST'
233+
url = "applications/$($APIApp.id)/addPassword"
234+
headers = @{
235+
'Content-Type' = 'application/json'
236+
}
237+
body = @{
238+
passwordCredential = $NewPasswordCredential
239+
}
240+
dependsOn = @('removeOldPasswords')
228241
}
229-
body = @{
230-
passwordCredential = $NewPasswordCredential
242+
)
243+
$BatchResponse = New-GraphBulkRequest -tenantid $env:TenantID -NoAuthCheck $true -asapp $true -Requests $Requests
244+
$AddPasswordResponse = $BatchResponse | Where-Object { $_.id -eq 'addNewPassword' }
245+
if ($AddPasswordResponse.status -ge 400) {
246+
$ErrorBody = $AddPasswordResponse.body
247+
$ErrorMsg = $ErrorBody.error.message ?? ($ErrorBody | ConvertTo-Json -Compress -Depth 5)
248+
$IsCredentialPolicyBlocked = $ErrorMsg -match 'Credential type not allowed as per assigned policy'
249+
if ($IsCredentialPolicyBlocked -and $Attempt -lt 6) {
250+
$DelaySeconds = [Math]::Min(10, 1 * $Attempt)
251+
Write-Information "Credential policy still blocks addPassword (attempt $Attempt of 6). Waiting for policy propagation and retrying in $DelaySeconds second(s)."
252+
Start-Sleep -Seconds $DelaySeconds
253+
continue
231254
}
232-
dependsOn = @('removeOldPasswords')
255+
throw "Failed to add new password during secret reset: $ErrorMsg"
233256
}
234-
)
235-
$BatchResponse = New-GraphBulkRequest -tenantid $env:TenantID -NoAuthCheck $true -asapp $true -Requests $Requests
236-
$AddPasswordResponse = $BatchResponse | Where-Object { $_.id -eq 'addNewPassword' }
237-
if ($AddPasswordResponse.status -ge 400) {
238-
$ErrorBody = $AddPasswordResponse.body
239-
$ErrorMsg = $ErrorBody.error.message ?? ($ErrorBody | ConvertTo-Json -Compress -Depth 5)
240-
throw "Failed to add new password during secret reset: $ErrorMsg"
257+
$APIPassword = $AddPasswordResponse.body
258+
break
241259
}
242-
$APIPassword = $AddPasswordResponse.body
243260
Write-LogMessage -headers $Headers -API $APINAME -tenant 'None '-message "Reset CIPP-API Password for '$($APIApp.displayName)'." -Sev 'info'
244261
}
245262
}

Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogSearchCreation.ps1

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,25 @@ function Start-AuditLogSearchCreation {
6868
}
6969

7070
$TenantInConfig = $false
71-
$MatchingConfigs = [System.Collections.Generic.List[object]]::new()
7271
foreach ($ConfigEntry in $ConfigEntries) {
7372
if ($ConfigEntry.excludedTenants.value -contains $Tenant.defaultDomainName) {
7473
continue
7574
}
7675
if ($ConfigEntry.ExpandedTenants -contains $Tenant.defaultDomainName -or $ConfigEntry.ExpandedTenants -contains 'AllTenants') {
7776
$TenantInConfig = $true
78-
$MatchingConfigs.Add($ConfigEntry)
77+
break
7978
}
8079
}
8180

8281
if (!$TenantInConfig) {
8382
continue
8483
}
8584

86-
if ($MatchingConfigs) {
87-
[PSCustomObject]@{
88-
FunctionName = 'AuditLogSearchCreation'
89-
Tenant = $Tenant | Select-Object defaultDomainName, customerId, displayName
90-
StartTime = $StartTime
91-
EndTime = $EndTime
92-
ServiceFilters = @($MatchingConfigs | Select-Object -Property type | Sort-Object -Property type -Unique | ForEach-Object { $_.type.split('.')[1] })
93-
}
85+
[PSCustomObject]@{
86+
FunctionName = 'AuditLogSearchCreation'
87+
Tenant = $Tenant | Select-Object defaultDomainName, customerId, displayName
88+
StartTime = $StartTime
89+
EndTime = $EndTime
9490
}
9591
}
9692

Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-CIPPOrchestrator.ps1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ function Start-CIPPOrchestrator {
3434
[switch]$CallerIsQueueTrigger
3535
)
3636

37-
# ─── CIPPNG runtime: push batch directly to OrchestratorService ───
37+
# ─── CRAFT runtime: push batch directly to OrchestratorService ───
3838
if ($env:CIPPNG -eq 'true' -and $InputObject) {
3939
$OrchestratorName = $InputObject.OrchestratorName ?? 'UnnamedOrchestrator'
4040

4141
# QueueFunction pattern: call the function first to generate batch items
4242
if (-not $InputObject.Batch -and $InputObject.QueueFunction) {
4343
$QueueFuncName = "Push-$($InputObject.QueueFunction.FunctionName)"
44-
Write-Information "CIPP-NG: Calling QueueFunction '$QueueFuncName' to build batch for '$OrchestratorName'"
44+
Write-Information "CRAFT: Calling QueueFunction '$QueueFuncName' to build batch for '$OrchestratorName'"
4545
$QueueItem = [PSCustomObject]@{}
4646
if ($InputObject.QueueFunction.Parameters) {
4747
$QueueItem = [PSCustomObject]$InputObject.QueueFunction.Parameters
4848
}
4949
$BatchResult = & $QueueFuncName -Item $QueueItem
5050
$QueueBatch = @($BatchResult | Where-Object { $null -ne $_ })
5151
if ($QueueBatch.Count -eq 0) {
52-
Write-Information "CIPP-NG: QueueFunction '$QueueFuncName' returned 0 tasks for '$OrchestratorName' - skipping"
53-
return "CIPPNG-$OrchestratorName-NoTasks"
52+
Write-Information "CRAFT: QueueFunction '$QueueFuncName' returned 0 tasks for '$OrchestratorName' - skipping"
53+
return "CRAFT-$OrchestratorName-NoTasks"
5454
}
5555
$InputObject | Add-Member -MemberType NoteProperty -Name 'Batch' -Value $QueueBatch -Force
5656
}
@@ -66,15 +66,15 @@ function Start-CIPPOrchestrator {
6666
}
6767
}
6868

69-
Write-Information "CIPP-NG: Queuing orchestrator '$OrchestratorName' ($($InputObject.Batch.Count) tasks$(if ($PostExecFunctionName) { ", PostExec: $PostExecFunctionName" }))"
70-
[CIPPASP.Services.OrchestratorBridge]::QueueOrchestration(
69+
Write-Information "CRAFT: Queuing orchestrator '$OrchestratorName' ($($InputObject.Batch.Count) tasks$(if ($PostExecFunctionName) { ", PostExec: $PostExecFunctionName" }))"
70+
[CRAFT.Services.OrchestratorBridge]::QueueOrchestration(
7171
$OrchestratorName,
7272
$BatchJson,
7373
4,
7474
$PostExecFunctionName,
7575
$PostExecParametersJson
7676
)
77-
return "CIPPNG-$OrchestratorName"
77+
return "CRAFT-$OrchestratorName"
7878
}
7979

8080
$OrchestratorTable = Get-CippTable -TableName 'CippOrchestratorInput'

Modules/CIPPCore/Public/Get-CIPPDbItem.ps1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ function Get-CIPPDbItem {
3434
)
3535

3636
try {
37+
# Enforce tenant lock when running inside custom script execution
38+
if ($script:CIPPLockedTenant) {
39+
$TenantFilter = $script:CIPPLockedTenant
40+
}
41+
3742
$Table = Get-CippTable -tablename 'CippReportingDB'
3843

3944
if ($TenantFilter -ne 'allTenants') {

Modules/CIPPCore/Public/Get-CIPPLicenseOverview.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,13 @@ function Get-CIPPLicenseOverview {
119119
$SubInfo = $SkuIDs | Where-Object { $_.id -eq $Subscription }
120120
$diff = $SubInfo.nextLifecycleDateTime - $SubInfo.createdDateTime
121121
$Term = 'Term unknown or non-NCE license'
122-
if ($diff.Days -ge 32 -and $diff.Days -le 1089) {
122+
if ($SubInfo.isTrial) {
123+
$Term = 'Trial'
124+
} elseif ($diff.Days -ge 36 -and $diff.Days -le 1089) {
123125
$Term = 'Yearly'
124126
} elseif ($diff.Days -ge 1090 -and $diff.Days -le 1100) {
125127
$Term = '3 Year'
126-
} elseif ($diff.Days -ge 25 -and $diff.Days -le 31) {
128+
} elseif ($diff.Days -ge 25 -and $diff.Days -le 35) {
127129
$Term = 'Monthly'
128130
}
129131
$TimeUntilRenew = ($subinfo.nextLifecycleDateTime - (Get-Date)).days

Modules/CIPPCore/Public/Get-CIPPMDEOnboardingReport.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ function Get-CIPPMDEOnboardingReport {
1919
$TenantList = Get-Tenants -IncludeErrors
2020
$Tenants = $Tenants | Where-Object { $TenantList.defaultDomainName -contains $_ }
2121

22+
if (-not $Tenants) {
23+
throw 'No MDE onboarding data found in reporting database for any tenant. Sync the report data first.'
24+
}
25+
2226
$AllResults = [System.Collections.Generic.List[PSCustomObject]]::new()
2327
foreach ($Tenant in $Tenants) {
2428
try {

0 commit comments

Comments
 (0)