Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
843ebfb
Fix mailcontact when values un-set
Zacgoose Jun 16, 2026
d2e54ee
SSO app password policy modification
Zacgoose Jun 16, 2026
d2655de
github template id sync fixes
Zacgoose Jun 16, 2026
8e21ee1
Fixes for when duplicate intune standards are applied to the same tenant
Zacgoose Jun 16, 2026
444a746
emit message when mailbox conversion might hit 50gb limit
Zacgoose Jun 16, 2026
e2b092b
update json from frontend
Zacgoose Jun 17, 2026
4939515
repair GDAP role mapping actions
Zacgoose Jun 17, 2026
2c63d31
Schema backed standards repair action, repaired standards are prefixe…
Zacgoose Jun 17, 2026
504c21a
fix: patch command for updating redirect uri
JohnDuprey Jun 17, 2026
1164290
remove incorrectly added permissions
KelvinTegelaar Jun 17, 2026
231e834
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
KelvinTegelaar Jun 17, 2026
a2c8a4a
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
JohnDuprey Jun 18, 2026
fa8a589
chore: add logging for onboarding
JohnDuprey Jun 18, 2026
942ff39
chore: consolidate graph log message
JohnDuprey Jun 18, 2026
920e3a1
user auth and sync logic
Zacgoose Jun 18, 2026
5e63541
Update standards.json
Zacgoose Jun 18, 2026
151ef46
SPO version cleanup job check
Zacgoose Jun 18, 2026
1a8b716
fixes for missing state on templates
Zacgoose Jun 18, 2026
5392acf
Sensitivity label fixes
Zacgoose Jun 18, 2026
ee92936
more drift logging and type casting
Zacgoose Jun 18, 2026
66ff8f5
ca template deployment logging for packages
Zacgoose Jun 18, 2026
4160b51
chore: add feature flag for copilot pages
JohnDuprey Jun 18, 2026
e4bd4be
chore: bump version to 10.5.3
JohnDuprey Jun 18, 2026
edc7acb
Trail claim better info on error
Zacgoose Jun 19, 2026
83c7735
enable copilot after hotfix
Zacgoose Jun 19, 2026
10f2478
intune device app collection
Zacgoose Jun 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions Config/AdditionalPermissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,5 @@
"type": "Scope"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "CopilotPolicySettings.ReadWrite",
"type": "Scope"
},
{
"id": "CopilotSettings-LimitedMode.ReadWrite",
"type": "Scope"
},
{
"id": "CopilotPackages.Read.All",
"type": "Scope"
},
{
"id": "CopilotPackages.ReadWrite.All",
"type": "Scope"
}
]
}
]
25 changes: 25 additions & 0 deletions Config/FeatureFlags.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@
],
"Hidden": true
},
{
"Id": "CopilotAI",
"Name": "Copilot & AI",
"Description": "Under Development: Microsoft 365 Copilot and AI management pages including settings, usage reports, Agent365 packages, and Shadow AI analysis.",
"Enabled": true,
"AllowUserToggle": false,
"Timers": [],
"Endpoints": [
"ListCopilotSettings",
"ExecCopilotSettings",
"ListCopilotUsage",
"ListAgent365Packages",
"ListAgent365PackageDetail",
"ListShadowAI"
],
"Pages": [
"/copilot/settings",
"/copilot/shadow-ai",
"/copilot/agent365/packages",
"/copilot/reports/copilot-adoption",
"/copilot/reports/copilot-usage",
"/copilot/reports/copilot-trend"
],
"Hidden": false
},
{
"Id": "MCPServer",
"Name": "MCP Server",
Expand Down
4,494 changes: 3,144 additions & 1,350 deletions Config/standards.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function Push-ExecOnboardTenantQueue {
param($Item)
try {
$Id = $Item.id
Write-Information "Onboarding: Starting for relationship $Id"
$Start = Get-Date
$Logs = [System.Collections.Generic.List[object]]::new()
$OnboardTable = Get-CIPPTable -TableName 'TenantOnboarding'
Expand Down Expand Up @@ -61,6 +62,7 @@ function Push-ExecOnboardTenantQueue {
$x++
Start-Sleep -Seconds 30
} while ($Relationship.status -ne 'active' -and $x -lt 6)
Write-Information "Onboarding: Step1 poll completed - status=$($Relationship.status) attempts=$x"

if ($Relationship.status -eq 'active') {
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'GDAP Invite Accepted' })
Expand Down Expand Up @@ -118,9 +120,34 @@ function Push-ExecOnboardTenantQueue {
$OnboardingSteps.Step2.Status = 'succeeded'
$OnboardingSteps.Step2.Message = 'Your GDAP relationship has the required roles'
}

# Validate (and correct) that the mapped security groups still exist in the partner tenant before
# Step 3 tries to POST the access assignments - a missing group surfaces as a raw Graph
# "access container does not exist" error otherwise.
if ($OnboardingSteps.Step2.Status -ne 'failed' -and ($Item.Roles | Measure-Object).Count -gt 0) {
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'Validating GDAP security group mappings against the partner tenant' })
$GroupCheck = Test-CIPPGDAPGroupMappings -RoleMappings $Item.Roles -CreateMissing:([bool]$Item.AddMissingGroups) -WriteBack
foreach ($GroupResult in $GroupCheck.Results) {
if ($GroupResult.Status -in @('Stale', 'Created', 'Missing')) {
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = $GroupResult.Message })
}
}
# Use the corrected mappings for the remainder of the onboarding (group mapping, SAM membership, retries)
$Item.Roles = @($GroupCheck.RoleMappings)

if (-not $GroupCheck.Valid) {
$MissingGroupNames = ($GroupCheck.MissingGroups.Name | Sort-Object -Unique) -join ', '
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = "Missing GDAP security groups in the partner tenant: $MissingGroupNames" })
$TenantOnboarding.Status = 'failed'
$OnboardingSteps.Step2.Status = 'failed'
$OnboardingSteps.Step2.Message = "The following GDAP security groups are missing in the partner tenant, recreate the GDAP roles and retry: $MissingGroupNames"
}
}

$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
Write-Information "Onboarding: Step2 completed - status=$($OnboardingSteps.Step2.Status) missingRoles=$($MissingRoles -join ',')"
}

if ($OnboardingSteps.Step2.Status -eq 'succeeded') {
Expand Down Expand Up @@ -304,43 +331,57 @@ function Push-ExecOnboardTenantQueue {
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
Write-Information "Onboarding: Step3 completed - status=$($OnboardingSteps.Step3.Status)"
}

if ($OnboardingSteps.Step3.Status -eq 'succeeded') {
# Check if the relationship was recently activated — Microsoft propagation may not have settled yet
if ($Relationship.activatedDateTime) {
$MinutesSinceActivation = $null
try {
$ActivatedTimeUtc = ([DateTimeOffset]$Relationship.activatedDateTime).UtcDateTime
$MinutesSinceActivation = ([datetime]::UtcNow - $ActivatedTimeUtc).TotalMinutes
if ($MinutesSinceActivation -lt 15) {
$RetryAtUtc = [Cronos.CronExpression]::Parse('* * * * *').GetNextOccurrence([DateTime]::UtcNow.AddMinutes(15), [TimeZoneInfo]::Utc)
$RetryEpoch = ([DateTimeOffset]$RetryAtUtc).ToUnixTimeSeconds()
$RetryDelayMinutes = ($RetryAtUtc - [DateTime]::UtcNow).TotalMinutes
$MinutesSinceActivationDisplay = ('{0:N1}' -f $MinutesSinceActivation)
$RetryDelayMinutesDisplay = ('{0:N1}' -f $RetryDelayMinutes)
$RetryLogMessage = "GDAP relationship was activated $MinutesSinceActivationDisplay minutes ago. Rescheduling onboarding in $RetryDelayMinutesDisplay minutes to allow Microsoft propagation to settle."
$Logs.Add([PSCustomObject]@{
Date = (Get-Date).ToUniversalTime()
Log = $RetryLogMessage
})
$RetryParams = [PSCustomObject]@{
Item = [PSCustomObject]@{
id = $Item.id
Roles = $Item.Roles
AutoMapRoles = $Item.AutoMapRoles
IgnoreMissingRoles = $Item.IgnoreMissingRoles
StandardsExcludeAllTenants = $Item.StandardsExcludeAllTenants
}
}
$RetryTask = [PSCustomObject]@{
Name = "GDAP Onboarding retry: $($Relationship.customer.displayName)"
Command = [PSCustomObject]@{ value = 'Push-ExecOnboardTenantQueue' }
Parameters = $RetryParams
TenantFilter = $env:TenantID
Recurrence = ''
ScheduledTime = $RetryEpoch
} catch {
Write-Warning "Failed to parse activatedDateTime for relationship ${Id}: $($_.Exception.Message)"
}
Write-Information "Onboarding: activatedDateTime=$($Relationship.activatedDateTime) minutesSinceActivation=$MinutesSinceActivation"
if ($null -ne $MinutesSinceActivation -and $MinutesSinceActivation -lt 15) {
$RetryAtUtc = [Cronos.CronExpression]::Parse('* * * * *').GetNextOccurrence([DateTime]::UtcNow.AddMinutes(15), [TimeZoneInfo]::Utc)
$RetryEpoch = ([DateTimeOffset]$RetryAtUtc).ToUnixTimeSeconds()
$RetryDelayMinutes = ($RetryAtUtc - [DateTime]::UtcNow).TotalMinutes
$MinutesSinceActivationDisplay = ('{0:N1}' -f $MinutesSinceActivation)
$RetryDelayMinutesDisplay = ('{0:N1}' -f $RetryDelayMinutes)
$RetryParams = [PSCustomObject]@{
Item = [PSCustomObject]@{
id = $Item.id
Roles = $Item.Roles
AutoMapRoles = $Item.AutoMapRoles
IgnoreMissingRoles = $Item.IgnoreMissingRoles
AddMissingGroups = $Item.AddMissingGroups
StandardsExcludeAllTenants = $Item.StandardsExcludeAllTenants
}
$null = Add-CIPPScheduledTask -Task $RetryTask -DesiredStartTime ([string]$RetryEpoch)
}
$RetryTask = [PSCustomObject]@{
Name = "GDAP Onboarding retry: $($Relationship.customer.displayName)"
Command = [PSCustomObject]@{ value = 'Push-ExecOnboardTenantQueue' }
Parameters = $RetryParams
TenantFilter = $env:TenantID
Recurrence = ''
ScheduledTime = $RetryEpoch
}
try {
$ScheduleResult = Add-CIPPScheduledTask -Task $RetryTask -DesiredStartTime ([string]$RetryEpoch)
} catch {
$ScheduleResult = "Error - $($_.Exception.Message)"
}
Write-Information "Onboarding: Add-CIPPScheduledTask result=$ScheduleResult"
if ($ScheduleResult -match '^Error') {
$FailMessage = "Failed to schedule onboarding retry for $($Relationship.customer.displayName): $ScheduleResult"
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = $FailMessage })
Write-LogMessage -API 'Onboarding' -message $FailMessage -Sev 'Error'
} else {
$RetryLogMessage = "GDAP relationship was activated $MinutesSinceActivationDisplay minutes ago. Rescheduling onboarding in $RetryDelayMinutesDisplay minutes to allow Microsoft propagation to settle."
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = $RetryLogMessage })
$RetryMessage = "Rescheduled: GDAP relationship was activated $MinutesSinceActivationDisplay minutes ago. Retrying in $RetryDelayMinutesDisplay minutes to allow Microsoft propagation to settle."
$OnboardingSteps.Step4.Status = 'pending'
$OnboardingSteps.Step4.Message = $RetryMessage
Expand All @@ -351,8 +392,6 @@ function Push-ExecOnboardTenantQueue {
Write-LogMessage -API 'Onboarding' -message $RetryMessage -Sev 'Info'
return
}
} catch {
Write-Warning "Failed to check activatedDateTime for relationship ${Id}: $($_.Exception.Message)"
}
}

Expand Down Expand Up @@ -421,6 +460,7 @@ function Push-ExecOnboardTenantQueue {
}
} while ($Refreshing -and (Get-Date) -lt $Start.AddMinutes(8))

Write-Information "Onboarding: CPV refresh loop completed - success=$CPVSuccess lastError=$LastCPVError"
if ($CPVSuccess) {
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'CPV permissions refreshed' })
$OnboardingSteps.Step4.Status = 'succeeded'
Expand Down Expand Up @@ -534,6 +574,7 @@ function Push-ExecOnboardTenantQueue {
$ApiException = $_
}

Write-Information "Onboarding: Step5 API test completed - userCount=$UserCount apiError=$ApiError"
if ($UserCount -gt 0) {
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'API test successful' })
$Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'Onboarding complete' })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ function Push-IntuneReportExportSubmit {
'UserId', 'UserName', 'EmailAddress'
)
}
'AppInstallStatusAggregate' {
@(
'ApplicationId', 'DisplayName', 'Publisher', 'Platform', 'AppVersion', 'AppPlatform',
'InstalledDeviceCount', 'FailedDeviceCount', 'FailedUserCount',
'PendingInstallDeviceCount', 'NotInstalledDeviceCount', 'FailedDevicePercentage'
)
}
default { throw "Unknown Intune report '$ReportName'" }
}

Expand Down
Loading