Skip to content

Commit 5a13af0

Browse files
2 parents ee4a2cf + 8bbefe1 commit 5a13af0

7 files changed

Lines changed: 97 additions & 55 deletions

File tree

Config/CIPPTimers.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"Id": "5ff6c500-e420-4a3b-8532-ace2e4da4f7d",
6060
"Command": "Start-ApplicationOrchestrator",
6161
"Description": "Orchestrator to process application uploads",
62-
"Cron": "0 0 */12 * * *",
62+
"Cron": "0 30 */12 * * *",
6363
"Priority": 2,
6464
"RunOnProcessor": true
6565
},
@@ -84,7 +84,7 @@
8484
"Id": "4d80205c-674d-4fc1-abeb-a1ec37e0d796",
8585
"Command": "Start-DriftStandardsOrchestrator",
8686
"Description": "Orchestrator to process drift standards",
87-
"Cron": "0 0 */12 * * *",
87+
"Cron": "0 15 */12 * * *",
8888
"Priority": 5,
8989
"RunOnProcessor": true,
9090
"PreferredProcessor": "standards"
@@ -101,15 +101,15 @@
101101
"Id": "ed7b5241-1cb9-499b-8f5b-1013ba5764b4",
102102
"Command": "Set-CIPPGDAPInviteGroups",
103103
"Description": "Orchestrator to map the groups for GDAP invites",
104-
"Cron": "0 0 */3 * * *",
104+
"Cron": "0 45 */3 * * *",
105105
"Priority": 5,
106106
"RunOnProcessor": true
107107
},
108108
{
109109
"Id": "0967c860-3a57-4860-8f33-e5136eae7b4e",
110110
"Command": "Start-TenantDynamicGroupOrchestrator",
111111
"Description": "Orchestrator to update dynamic tenant groups",
112-
"Cron": "0 0 */4 * * *",
112+
"Cron": "0 30 */4 * * *",
113113
"Priority": 6,
114114
"RunOnProcessor": true
115115
},
@@ -180,7 +180,7 @@
180180
"Id": "54c39540-fe91-4795-8613-ac4295751a51",
181181
"Command": "Start-ExtensionOrchestrator",
182182
"Description": "Orchestrator to process extensions",
183-
"Cron": "0 0 */2 * * *",
183+
"Cron": "0 45 */2 * * *",
184184
"Priority": 12,
185185
"RunOnProcessor": true
186186
},

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,20 @@ function New-CIPPAPIConfig {
193193
if ($PSCmdlet.ShouldProcess($APIApp.displayName, 'Reset API Secret')) {
194194
$Step = 'Resetting Application Password'
195195
Write-Information 'Removing all old passwords'
196+
197+
$AppManagementPolicy = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/policies/defaultAppManagementPolicy' -AsApp $true -NoAuthCheck $true
198+
$PasswordExpirationPolicy = $AppManagementPolicy.applicationRestrictions.passwordcredentials |
199+
Where-Object { $_.restrictionType -eq 'passwordLifetime' }
200+
201+
$NewPasswordCredential = @{
202+
displayName = 'Generated by API Setup'
203+
}
204+
if (-not ($PasswordExpirationPolicy.state -eq 'disabled' -or $null -eq $PasswordExpirationPolicy.state)) {
205+
$TimeToExpiration = [System.Xml.XmlConvert]::ToTimeSpan($PasswordExpirationPolicy.maxLifetime)
206+
$ExpirationDate = (Get-Date).AddDays($TimeToExpiration.Days).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
207+
$NewPasswordCredential.endDateTime = $ExpirationDate
208+
}
209+
196210
$Requests = @(
197211
@{
198212
id = 'removeOldPasswords'
@@ -213,15 +227,19 @@ function New-CIPPAPIConfig {
213227
'Content-Type' = 'application/json'
214228
}
215229
body = @{
216-
passwordCredential = @{
217-
displayName = 'Generated by API Setup'
218-
}
230+
passwordCredential = $NewPasswordCredential
219231
}
220232
dependsOn = @('removeOldPasswords')
221233
}
222234
)
223235
$BatchResponse = New-GraphBulkRequest -tenantid $env:TenantID -NoAuthCheck $true -asapp $true -Requests $Requests
224-
$APIPassword = $BatchResponse | Where-Object { $_.id -eq 'addNewPassword' } | Select-Object -ExpandProperty body
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"
241+
}
242+
$APIPassword = $AddPasswordResponse.body
225243
Write-LogMessage -headers $Headers -API $APINAME -tenant 'None '-message "Reset CIPP-API Password for '$($APIApp.displayName)'." -Sev 'info'
226244
}
227245
}

Modules/CIPPCore/Public/Functions/Get-CIPPTenantAlignment.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,27 @@ function Get-CIPPTenantAlignment {
400400
if ($item.ReportingDisabled) { $ReportingDisabledStandardsCount++ }
401401
}
402402

403+
# For drift templates, include all policy deviation entries from tenantDrift table in alignment score
404+
# Accepted/CustomerSpecific count as compliant, all others (New, Denied, etc.) count as non-compliant
405+
$CurrentDeviationsCount = $null
406+
if ($IsDriftTemplate) {
407+
$PolicyDeviationCompliant = 0
408+
$PolicyDeviationNonCompliant = 0
409+
foreach ($DriftKey in $TenantDriftStatuses.Keys) {
410+
if ($DriftKey -like 'IntuneTemplates.*' -or $DriftKey -like 'ConditionalAccessTemplates.*') {
411+
if ($TenantDriftStatuses[$DriftKey] -in @('Accepted', 'CustomerSpecific')) {
412+
$PolicyDeviationCompliant++
413+
} else {
414+
$PolicyDeviationNonCompliant++
415+
}
416+
}
417+
}
418+
$AllCount += $PolicyDeviationCompliant + $PolicyDeviationNonCompliant
419+
$CompliantStandards += $PolicyDeviationCompliant
420+
$NonCompliantStandards += $PolicyDeviationNonCompliant
421+
$CurrentDeviationsCount = $PolicyDeviationNonCompliant
422+
}
423+
403424
$AlignmentPercentage = if (($AllCount - $ReportingDisabledStandardsCount) -gt 0) {
404425
[Math]::Round(($CompliantStandards / ($AllCount - $ReportingDisabledStandardsCount)) * 100)
405426
} else {
@@ -429,6 +450,7 @@ function Get-CIPPTenantAlignment {
429450
LicenseMissingStandards = $LicenseMissingStandards
430451
TotalStandards = $AllCount
431452
ReportingDisabledCount = $ReportingDisabledStandardsCount
453+
CurrentDeviationsCount = $CurrentDeviationsCount
432454
LatestDataCollection = if ($LatestDataCollection) { $LatestDataCollection } else { $null }
433455
ComparisonDetails = $ComparisonResults
434456
}

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,11 @@ function Invoke-PublicWebhooks {
77
#>
88
param($Request, $TriggerMetadata)
99
$Headers = $Request.Headers
10-
11-
$WebhookTable = Get-CIPPTable -TableName webhookTable
12-
$WebhookIncoming = Get-CIPPTable -TableName WebhookIncoming
13-
$Webhooks = Get-CIPPAzDataTableEntity @WebhookTable
1410
Write-Host 'Received request'
1511
$url = ($Headers.'x-ms-original-url').split('/API') | Select-Object -First 1
1612
$CIPPURL = [string]$url
1713
Write-Host $url
18-
if ($Webhooks.Resource -eq 'M365AuditLogs') {
19-
Write-Host "Found M365AuditLogs - This is an old entry, we'll deny so Microsoft stops sending it."
20-
$body = 'This webhook is not authorized, its an old entry.'
21-
$StatusCode = [HttpStatusCode]::Forbidden
22-
}
14+
2315
if ($Request.Query.ValidationToken) {
2416
Write-Host 'Validation token received - query ValidationToken'
2517
$body = $Request.Query.ValidationToken
@@ -32,45 +24,54 @@ function Invoke-PublicWebhooks {
3224
Write-Host 'Validation token received - query validationCode'
3325
$body = $Request.Query.validationCode
3426
$StatusCode = [HttpStatusCode]::OK
35-
} elseif ($Request.Query.CIPPID -in $Webhooks.RowKey) {
36-
Write-Host 'Found matching CIPPID'
37-
$url = ($Headers.'x-ms-original-url').split('/API') | Select-Object -First 1
38-
$Webhookinfo = $Webhooks | Where-Object -Property RowKey -EQ $Request.Query.CIPPID
27+
} elseif ($Request.Query.CIPPID) {
28+
$WebhookTable = Get-CIPPTable -TableName webhookTable
29+
$Webhookinfo = Get-CIPPAzDataTableEntity @WebhookTable -Filter "RowKey eq '$($Request.Query.CIPPID)'" -First 1
30+
if (-not $Webhookinfo) {
31+
Write-Host "No matching CIPPID found: $($Request.Query.CIPPID)"
32+
$Body = 'This webhook is not authorized.'
33+
$StatusCode = [HttpStatusCode]::Forbidden
34+
} elseif ($Webhookinfo.Resource -eq 'M365AuditLogs') {
35+
Write-Host "Found M365AuditLogs - This is an old entry, we'll deny so Microsoft stops sending it."
36+
$Body = 'This webhook is not authorized, its an old entry.'
37+
$StatusCode = [HttpStatusCode]::Forbidden
38+
} else {
39+
Write-Host 'Found matching CIPPID'
40+
$WebhookIncoming = Get-CIPPTable -TableName WebhookIncoming
3941

40-
if ($Request.Query.Type -eq 'GraphSubscription') {
41-
# Graph Subscriptions
42-
[pscustomobject]$ReceivedItem = $Request.Body.value
43-
$Entity = [PSCustomObject]@{
44-
PartitionKey = 'Webhook'
45-
RowKey = [string](New-Guid).Guid
46-
Type = $Request.Query.Type
47-
Data = [string]($ReceivedItem | ConvertTo-Json -Depth 10)
48-
CIPPID = $Request.Query.CIPPID
49-
WebhookInfo = [string]($WebhookInfo | ConvertTo-Json -Depth 10)
50-
FunctionName = 'PublicWebhookProcess'
51-
}
52-
Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity
53-
## Push webhook data to queue
54-
#Invoke-CippGraphWebhookProcessing -Data $ReceivedItem -CIPPID $request.Query.CIPPID -WebhookInfo $Webhookinfo
42+
if ($Request.Query.Type -eq 'GraphSubscription') {
43+
# Graph Subscriptions
44+
[pscustomobject]$ReceivedItem = $Request.Body.value
45+
$Entity = [PSCustomObject]@{
46+
PartitionKey = 'Webhook'
47+
RowKey = [string](New-Guid).Guid
48+
Type = $Request.Query.Type
49+
Data = [string]($ReceivedItem | ConvertTo-Json -Depth 10)
50+
CIPPID = $Request.Query.CIPPID
51+
WebhookInfo = [string]($WebhookInfo | ConvertTo-Json -Depth 10)
52+
FunctionName = 'PublicWebhookProcess'
53+
}
54+
Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity
5555

56-
} elseif ($Request.Query.Type -eq 'PartnerCenter') {
57-
[pscustomobject]$ReceivedItem = $Request.Body
58-
$Entity = [PSCustomObject]@{
59-
PartitionKey = 'Webhook'
60-
RowKey = [string](New-Guid).Guid
61-
Type = $Request.Query.Type
62-
Data = [string]($ReceivedItem | ConvertTo-Json -Depth 10)
63-
CIPPID = $Request.Query.CIPPID
64-
WebhookInfo = [string]($WebhookInfo | ConvertTo-Json -Depth 10)
65-
FunctionName = 'PublicWebhookProcess'
56+
} elseif ($Request.Query.Type -eq 'PartnerCenter') {
57+
[pscustomobject]$ReceivedItem = $Request.Body
58+
$Entity = [PSCustomObject]@{
59+
PartitionKey = 'Webhook'
60+
RowKey = [string](New-Guid).Guid
61+
Type = $Request.Query.Type
62+
Data = [string]($ReceivedItem | ConvertTo-Json -Depth 10)
63+
CIPPID = $Request.Query.CIPPID
64+
WebhookInfo = [string]($WebhookInfo | ConvertTo-Json -Depth 10)
65+
FunctionName = 'PublicWebhookProcess'
66+
}
67+
Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity
68+
} else {
69+
$Body = 'This webhook is not authorized.'
70+
$StatusCode = [HttpStatusCode]::Forbidden
6671
}
67-
Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity
68-
} else {
69-
$Body = 'This webhook is not authorized.'
70-
$StatusCode = [HttpStatusCode]::Forbidden
72+
$Body = 'Webhook Received'
73+
$StatusCode = [HttpStatusCode]::OK
7174
}
72-
$Body = 'Webhook Received'
73-
$StatusCode = [HttpStatusCode]::OK
7475

7576
} else {
7677
$Body = 'This webhook is not authorized.'

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListTenantAlignment.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ function Invoke-ListTenantAlignment {
9292
alignmentScore = $_.AlignmentScore
9393
LicenseMissingPercentage = $_.LicenseMissingPercentage
9494
combinedAlignmentScore = $_.CombinedScore
95+
currentDeviationsCount = $_.CurrentDeviationsCount
9596
latestDataCollection = $_.LatestDataCollection
9697
}
9798
}

Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneExtensionScheduler.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function Invoke-NinjaOneExtensionScheduler {
7676
$_ | Add-Member -NotePropertyName lastStartTime -NotePropertyValue $Null -Force
7777
}
7878
}
79-
$CatchupTenants = $TenantsToProcess | Where-Object { (((($_.lastEndTime -eq $Null) -or ($_.lastStartTime -gt $_.lastEndTime)) -and ($_.lastStartTime -lt (Get-Date).AddMinutes(-30)))) -or ($_.lastStartTime -lt $LastRunTime) }
79+
$CatchupTenants = $TenantsToProcess | Where-Object { ((($_.lastEndTime -eq $Null) -or ($_.lastStartTime -gt $_.lastEndTime)) -and ($_.lastStartTime -lt (Get-Date).AddHours(-3))) -or (($_.lastStartTime -lt $LastRunTime) -and ($Null -eq $_.lastEndTime -or $_.lastEndTime -lt $LastRunTime)) }
8080
$Batch = foreach ($Tenant in $CatchupTenants) {
8181
[PSCustomObject]@{
8282
NinjaAction = 'SyncTenant'

version_latest.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
10.4.1
1+
10.4.2

0 commit comments

Comments
 (0)