diff --git a/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 b/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 index 7ff4452bba45..bc0dfe9046bf 100644 --- a/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 @@ -5,9 +5,10 @@ function Add-CIPPDelegatedPermission { $ApplicationId, $Tenantfilter ) + Write-Host 'Adding Delegated Permissions' Set-Location (Get-Item $PSScriptRoot).FullName - - if ($RequiredResourceAccess -eq "CIPPDefaults") { + Write-Host "RequiredResourceAccess: $($RequiredResourceAccess | ConvertTo-Json -Depth 10)" + if ($RequiredResourceAccess -eq 'CIPPDefaults') { $RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess } $Translator = Get-Content '.\PermissionsTranslator.json' | ConvertFrom-Json @@ -26,17 +27,16 @@ function Add-CIPPDelegatedPermission { if (!$OldScope) { $Createbody = @{ clientId = $ourSVCPrincipal.id - consentType = "AllPrincipals" + consentType = 'AllPrincipals' resourceId = $svcPrincipalId.id scope = $NewScope } | ConvertTo-Json -Compress - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants" -tenantid $Tenantfilter -body $Createbody -type POST + $CreateRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/oauth2PermissionGrants' -tenantid $Tenantfilter -body $Createbody -type POST $Results.add("Successfully added permissions for $($svcPrincipalId.displayName)") | Out-Null - } - else { + } else { $compare = Compare-Object -ReferenceObject $OldScope.scope.Split(' ') -DifferenceObject $NewScope.Split(' ') if (!$compare) { - $Results.add("All delegated permissions exist for $($svcPrincipalId.displayName)") | Out-Null + $Results.add("All delegated permissions exist for $($svcPrincipalId.displayName)") | Out-Null continue } $Patchbody = @{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 index 4c10f456584e..f567ef62932f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 @@ -1,6 +1,7 @@ function Push-ExecAddMultiTenantApp($QueueItem, $TriggerMetadata) { try { - Write-Host $Queueitem + $Queueitem = $QueueItem | ConvertTo-Json -Depth 10 | ConvertFrom-Json + Write-Host "$($Queueitem | ConvertTo-Json -Depth 10)" $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Queueitem.Tenant if ($Queueitem.AppId -Notin $ServicePrincipalList.appId) { $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $queueitem.tenant -body "{ `"appId`": `"$($Queueitem.appId)`" }" @@ -8,8 +9,8 @@ function Push-ExecAddMultiTenantApp($QueueItem, $TriggerMetadata) { } else { Write-LogMessage -message "This app already exists in tenant $($Queueitem.Tenant). We're adding the required permissions." -tenant $Queueitem.Tenant -API 'Add Multitenant App' -sev Info } - Add-CIPPApplicationPermission -RequiredResourceAccess [pscustomobject]$queueitem.applicationResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant - Add-CIPPDelegatedPermission -RequiredResourceAccess [pscustomobject]$queueitem.DelegateResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + Add-CIPPApplicationPermission -RequiredResourceAccess ($queueitem.applicationResourceAccess) -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + Add-CIPPDelegatedPermission -RequiredResourceAccess ($queueitem.DelegateResourceAccess) -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant } catch { Write-LogMessage -message "Error adding application to tenant $($Queueitem.Tenant) - $($_.Exception.Message)" -tenant $Queueitem.Tenant -API 'Add Multitenant App' -sev Error } diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ExecOnboardTenantQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ExecOnboardTenantQueue.ps1 index 687af6d40b87..1c507e0ee57f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ExecOnboardTenantQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ExecOnboardTenantQueue.ps1 @@ -9,6 +9,7 @@ Function Push-ExecOnboardTenantQueue { $DateFormat = '%Y-%m-%d %H:%M:%S' $Id = $QueueItem.id #Write-Host ($QueueItem.Roles | ConvertTo-Json) + $Start = Get-Date $Logs = [System.Collections.Generic.List[object]]::new() $OnboardTable = Get-CIPPTable -TableName 'TenantOnboarding' $TenantOnboarding = Get-CIPPAzDataTableEntity @OnboardTable -Filter "RowKey eq '$Id'" @@ -17,6 +18,14 @@ Function Push-ExecOnboardTenantQueue { $OnboardingSteps = $TenantOnboarding.OnboardingSteps | ConvertFrom-Json $OnboardingSteps.Step1.Status = 'running' $OnboardingSteps.Step1.Message = 'Checking GDAP invite status' + $OnboardingSteps.Step2.Status = 'pending' + $OnboardingSteps.Step2.Message = 'Waiting for Step 1' + $OnboardingSteps.Step3.Status = 'pending' + $OnboardingSteps.Step3.Message = 'Waiting for Step 2' + $OnboardingSteps.Step4.Status = 'pending' + $OnboardingSteps.Step4.Message = 'Waiting for Step 3' + $OnboardingSteps.Step5.Status = 'pending' + $OnboardingSteps.Step5.Message = 'Waiting for Step 4' $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) $TenantOnboarding.Status = 'running' $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress -AsArray) @@ -50,7 +59,7 @@ Function Push-ExecOnboardTenantQueue { $Relationship = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$Id" $x++ Start-Sleep -Seconds 30 - } while ($Relationship.status -ne 'active' -and $x -lt 4) + } while ($Relationship.status -ne 'active' -and $x -lt 6) if ($Relationship.status -eq 'active') { $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'GDAP Invite Accepted' }) @@ -174,6 +183,10 @@ Function Push-ExecOnboardTenantQueue { $TenantOnboarding.Status = 'failed' $OnboardingSteps.Step3.Status = 'failed' $OnboardingSteps.Step3.Message = 'No matching roles found, check the relationship and try again.' + $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop + return } } @@ -192,6 +205,10 @@ Function Push-ExecOnboardTenantQueue { $TenantOnboarding.Status = 'failed' $OnboardingSteps.Step3.Status = 'failed' $OnboardingSteps.Step3.Message = 'Group mapping failed, check the log book for details.' + $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop + return } } elseif (!$GroupSuccess) { $TenantOnboarding.Status = 'failed' @@ -203,7 +220,7 @@ Function Push-ExecOnboardTenantQueue { do { $x++ $AccessAssignments = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$Id/accessAssignments" - Start-Sleep -Seconds 10 + Start-Sleep -Seconds 15 } while ($AccessAssignments.status -contains 'pending' -and $x -le 12) if ($AccessAssignments.status -notcontains 'pending') { @@ -212,6 +229,11 @@ Function Push-ExecOnboardTenantQueue { } else { $OnboardingSteps.Step3.Message = 'Group check: Access assignments are still pending, try again later' $OnboardingSteps.Step3.Status = 'failed' + $TenantOnboarding.Status = 'failed' + $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop + return } } if ($QueueItem.AddMissingGroups -eq $true) { @@ -239,22 +261,53 @@ Function Push-ExecOnboardTenantQueue { } if ($OnboardingSteps.Step3.Status -eq 'succeeded') { - $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Refreshing CPV permissions' }) + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Setting up CPV consent' }) $OnboardingSteps.Step4.Status = 'running' - $OnboardingSteps.Step4.Message = 'Refreshing CPV permissions' + $OnboardingSteps.Step4.Message = 'Setting up CPV consent' $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop - try { - Remove-CIPPCache -tenantsOnly $true - } catch {} + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Clearing tenant cache' }) + $y = 0 + do { + try { + Remove-CIPPCache -tenantsOnly $true + } catch {} + + $Tenant = Get-Tenants | Where-Object { $_.customerId -eq $Relationship.customer.tenantId } | Select-Object -First 1 + $y++ + Start-Sleep -Seconds 20 + } while (!$Tenant -and $y -le 4) - $Tenant = Get-Tenants | Where-Object { $_.customerId -eq $Relationship.customer.tenantId } | Select-Object -First 1 if ($Tenant) { - $y = 0 + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Tenant found in customer list' }) + try { + $CPVConsentParams = @{ + TenantFilter = $Tenant.defaultDomainName + } + $Consent = Set-CIPPCPVConsent @CPVConsentParams + if ($Consent -match 'Could not add our Service Principal to the client tenant') { + throw + } + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Added initial CPV consent permissions' }) + } catch { + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'CPV Consent Failed' }) + $TenantOnboarding.Status = 'failed' + $OnboardingSteps.Step4.Status = 'failed' + $OnboardingSteps.Step4.Message = 'CPV Consent failed, check the App Registration in your partner tenant for missing admin consent.' + $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop + return + } $Refreshing = $true $CPVSuccess = $false + $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Refreshing CPV permissions' }) + $OnboardingSteps.Step4.Message = 'Refreshing CPV permissions' + $TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress) + $TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress) + Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop do { try { Add-CIPPApplicationPermission -RequiredResourceAccess 'CippDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $Tenant.defaultDomainName @@ -262,10 +315,9 @@ Function Push-ExecOnboardTenantQueue { $CPVSuccess = $true $Refreshing = $false } catch { - $y++ Start-Sleep -Seconds 30 } - } while ($Refreshing -and $y -lt 4) + } while ($Refreshing -and (Get-Date) -lt $Start.AddMinutes(8)) if ($CPVSuccess) { $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'CPV permissions refreshed' }) diff --git a/Modules/CIPPCore/Public/Set-CIPPAuthenticationPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAuthenticationPolicy.ps1 index ecdb1bdfc904..b68de07e0301 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAuthenticationPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAuthenticationPolicy.ps1 @@ -9,7 +9,7 @@ function Set-CIPPAuthenticationPolicy { $TAPMaximumLifetime = 480, #minutes $TAPDefaultLifeTime = 60, #minutes $TAPDefaultLength = 8, #TAP password generated length in chars - [bool]$TAPisUsableOnce = $true, + $TAPisUsableOnce = $true, $APIName = 'Set Authentication Policy', $ExecutingUser ) @@ -62,11 +62,12 @@ function Set-CIPPAuthenticationPolicy { # Temporary Access Pass 'TemporaryAccessPass' { if ($State -eq 'enabled') { - $CurrentInfo.isUsableOnce = $TAPisUsableOnce + $CurrentInfo.isUsableOnce = [System.Convert]::ToBoolean($TAPisUsableOnce) $CurrentInfo.minimumLifetimeInMinutes = $TAPMinimumLifetime $CurrentInfo.maximumLifetimeInMinutes = $TAPMaximumLifetime $CurrentInfo.defaultLifetimeInMinutes = $TAPDefaultLifeTime $CurrentInfo.defaultLength = $TAPDefaultLength + $OptionalLogMessage = "with TAP isUsableOnce set to $TAPisUsableOnce" } } diff --git a/UpdatePermissions/run.ps1 b/UpdatePermissions/run.ps1 index 03faa53ab09f..e4e73f4be9ed 100644 --- a/UpdatePermissions/run.ps1 +++ b/UpdatePermissions/run.ps1 @@ -1,7 +1,7 @@ # Input bindings are passed in via param block. param($Timer) -$Tenants = get-tenants -IncludeAll +$Tenants = get-tenants -IncludeAll | Where-Object { $_.customerId -ne $env:TenantId } foreach ($Row in $Tenants) { Push-OutputBinding -Name Msg -Value $row } \ No newline at end of file