diff --git a/Activity_AddOrUpdateTableRows/function.json b/Activity_AddOrUpdateTableRows/function.json
deleted file mode 100644
index f87c62c534f8..000000000000
--- a/Activity_AddOrUpdateTableRows/function.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "bindings": [
- {
- "name": "TableParams",
- "type": "activityTrigger",
- "direction": "in"
- }
- ]
-}
diff --git a/Activity_AddOrUpdateTableRows/run.ps1 b/Activity_AddOrUpdateTableRows/run.ps1
deleted file mode 100644
index adc07df73e23..000000000000
--- a/Activity_AddOrUpdateTableRows/run.ps1
+++ /dev/null
@@ -1,12 +0,0 @@
-param($TableParams)
-$TableName = ($TableParams.Context['TableName'])
-$Table = Get-CippTable -tablename $TableName
-
-foreach ($param in $TableParams.Entity) {
- try {
- #Sending each item indivually, if it fails, log an error.
- Add-CIPPAzDataTableEntity @Table -Entity $param -Force
- } catch {
- Write-LogMessage -API 'Activity_AddOrUpdateTableRows' -message "Unable to write to '$($TableParams.TableName)' Using RowKey $($param.RowKey)" -LogData (Get-CippException -Exception $_) -sev error
- }
-}
diff --git a/Activity_GetAllTableRows/function.json b/Activity_GetAllTableRows/function.json
deleted file mode 100644
index ce320a44c1a3..000000000000
--- a/Activity_GetAllTableRows/function.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "bindings": [
- {
- "name": "name",
- "type": "activityTrigger",
- "direction": "in"
- }
- ]
-}
diff --git a/Activity_GetAllTableRows/run.ps1 b/Activity_GetAllTableRows/run.ps1
deleted file mode 100644
index db63ea61a8cb..000000000000
--- a/Activity_GetAllTableRows/run.ps1
+++ /dev/null
@@ -1,6 +0,0 @@
-param($name)
-
-$Table = Get-CippTable -tablename $name
-$Rows = Get-CIPPAzDataTableEntity @Table
-
-Write-Output $Rows
\ No newline at end of file
diff --git a/AddChocoApp_OrchestrationStarter/function.json b/AddChocoApp_OrchestrationStarter/function.json
deleted file mode 100644
index 14c44f4f0217..000000000000
--- a/AddChocoApp_OrchestrationStarter/function.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "bindings": [
- {
- "authLevel": "anonymous",
- "name": "Request",
- "type": "httpTrigger",
- "direction": "in",
- "methods": [
- "post",
- "get"
- ]
- },
- {
- "type": "http",
- "direction": "out",
- "name": "Response"
- },
- {
- "name": "starter",
- "type": "durableClient",
- "direction": "in"
- }
- ]
-}
diff --git a/AddChocoApp_OrchestrationStarter/run.ps1 b/AddChocoApp_OrchestrationStarter/run.ps1
deleted file mode 100644
index 1053de0bd089..000000000000
--- a/AddChocoApp_OrchestrationStarter/run.ps1
+++ /dev/null
@@ -1,21 +0,0 @@
-using namespace System.Net
-
-param($Request, $TriggerMetadata)
-if ($CurrentlyRunning) {
- $Results = [pscustomobject]@{"Results" = "Already running. Please wait for the current instance to finish" }
- Write-LogMessage -API "ChocoApps" -message "Attempted to start upload but an instance was already running." -sev Info
-}
-else {
- $InstanceId = Start-NewOrchestration -FunctionName 'Applications_Orchestrator'
- Write-Host "Started orchestration with ID = '$InstanceId'"
- $Orchestrator = New-OrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId
- Write-LogMessage -API "ChocoApps" -message "Started uploading applications to tenants" -sev Info
- $Results = [pscustomobject]@{"Results" = "Started application queue" }
-}
-Write-Host ($Orchestrator | ConvertTo-Json)
-
-
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $results
- })
\ No newline at end of file
diff --git a/AddChocoApp_OrchestrationStarterTimer/run.ps1 b/AddChocoApp_OrchestrationStarterTimer/run.ps1
index db6463ff1c29..85d820ceb522 100644
--- a/AddChocoApp_OrchestrationStarterTimer/run.ps1
+++ b/AddChocoApp_OrchestrationStarterTimer/run.ps1
@@ -1,19 +1,7 @@
param($Timer)
try {
- if ($CurrentlyRunning) {
- $Results = [pscustomobject]@{'Results' = 'Already running. Please wait for the current instance to finish' }
- Write-LogMessage -API 'ChocoApps' -message 'Attempted to start upload but an instance was already running.' -sev Info
- }
- else {
- $InstanceId = Start-NewOrchestration -FunctionName 'Applications_Orchestrator'
- Write-Host "Started orchestration with ID = '$InstanceId'"
- $Orchestrator = New-OrchestrationCheckStatusResponse -Request $Timer -InstanceId $InstanceId
- Write-LogMessage -API 'ChocoApps' -message 'Started uploading applications to tenants' -sev Info
- $Results = [pscustomobject]@{'Results' = 'Started running analysis' }
- }
- Write-Host ($Orchestrator | ConvertTo-Json)
-}
-catch {
+ Start-ApplicationOrchestrator
+} catch {
Write-Host "AddChocoApp_OrchestratorStarterTimer Exception: $($_.Exception.Message)"
}
diff --git a/Applications_GetQueue/function.json b/Applications_GetQueue/function.json
deleted file mode 100644
index b31f1ad21352..000000000000
--- a/Applications_GetQueue/function.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "bindings": [
- {
- "name": "name",
- "type": "activityTrigger",
- "direction": "in"
- }
- ]
-}
\ No newline at end of file
diff --git a/Applications_GetQueue/run.ps1 b/Applications_GetQueue/run.ps1
deleted file mode 100644
index 44940eed384b..000000000000
--- a/Applications_GetQueue/run.ps1
+++ /dev/null
@@ -1,6 +0,0 @@
-param($name)
-
-$Table = Get-CippTable -tablename 'apps'
-
-$Object = (Get-CIPPAzDataTableEntity @Table).RowKey
-$object
\ No newline at end of file
diff --git a/Applications_Orchestrator/function.json b/Applications_Orchestrator/function.json
deleted file mode 100644
index 7326b39c184d..000000000000
--- a/Applications_Orchestrator/function.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "bindings": [
- {
- "name": "Context",
- "type": "orchestrationTrigger",
- "direction": "in"
- }
- ]
-}
\ No newline at end of file
diff --git a/Applications_Orchestrator/run.ps1 b/Applications_Orchestrator/run.ps1
deleted file mode 100644
index ebf60eb55628..000000000000
--- a/Applications_Orchestrator/run.ps1
+++ /dev/null
@@ -1,25 +0,0 @@
-param($Context)
-
-$DurableRetryOptions = @{
- FirstRetryInterval = (New-TimeSpan -Seconds 5)
- MaxNumberOfAttempts = 3
- BackoffCoefficient = 2
-}
-$RetryOptions = New-DurableRetryOptions @DurableRetryOptions
-
-try {
- $Batch = (Invoke-ActivityFunction -FunctionName 'Applications_GetQueue' -Input 'LetsGo')
- Write-Host $Batch
- $ParallelTasks = foreach ($Item in $Batch) {
- Invoke-DurableActivity -FunctionName 'Applications_Upload' -Input $item -NoWait -RetryOptions $RetryOptions
- }
-
- $Outputs = Wait-ActivityFunction -Task $ParallelTasks
- Write-Host $Outputs
-}
-catch {
- Write-Host "Applications_Orchestrator exception: $($_.Exception.Message)"
-}
-finally {
- Write-LogMessage -API 'ChocoApp' -Message 'Choco Application Queue: Deployment finished.' -sev Info
-}
\ No newline at end of file
diff --git a/Applications_Upload/function.json b/Applications_Upload/function.json
deleted file mode 100644
index b31f1ad21352..000000000000
--- a/Applications_Upload/function.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "bindings": [
- {
- "name": "name",
- "type": "activityTrigger",
- "direction": "in"
- }
- ]
-}
\ No newline at end of file
diff --git a/Applications_Upload/run.ps1 b/Applications_Upload/run.ps1
deleted file mode 100644
index 9245bf78f2f5..000000000000
--- a/Applications_Upload/run.ps1
+++ /dev/null
@@ -1,121 +0,0 @@
-param($name)
-$Table = Get-CippTable -tablename 'apps'
-$Filter = "PartitionKey eq 'apps' and RowKey eq '$name'"
-Set-Location (Get-Item $PSScriptRoot).Parent.FullName
-$ChocoApp = (Get-CIPPAzDataTableEntity @Table -filter $Filter).JSON | ConvertFrom-Json
-$intuneBody = $ChocoApp.IntuneBody
-$tenants = if ($chocoapp.Tenant -eq 'AllTenants') {
- (Get-tenants).defaultDomainName
-} else {
- $chocoapp.Tenant
-}
-if ($chocoApp.type -eq 'MSPApp') {
- [xml]$Intunexml = Get-Content "AddMSPApp\$($ChocoApp.MSPAppName).app.xml"
- $intunewinFilesize = (Get-Item "AddMSPApp\$($ChocoApp.MSPAppName).intunewin")
- $Infile = "AddMSPApp\$($ChocoApp.MSPAppName).intunewin"
-} else {
- [xml]$Intunexml = Get-Content 'AddChocoApp\choco.app.xml'
- $intunewinFilesize = (Get-Item 'AddChocoApp\IntunePackage.intunewin')
- $Infile = "AddChocoApp\$($intunexml.ApplicationInfo.FileName)"
-}
-$assignTo = $ChocoApp.AssignTo
-$AssignToIntent = $ChocoApp.InstallationIntent
-$Baseuri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps'
-$ContentBody = ConvertTo-Json @{
- name = $intunexml.ApplicationInfo.FileName
- size = [int64]$intunexml.ApplicationInfo.UnencryptedContentSize
- sizeEncrypted = [int64]($intunewinFilesize).length
-}
-$ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter
-$RemoveCacheFile = if ($chocoapp.Tenant -ne 'AllTenants') {
- Remove-AzDataTableEntity @Table -Entity $clearRow
-} else {
- $Table.Force = $true
- Add-CIPPAzDataTableEntity @Table -Entity @{
- JSON = "$($ChocoApp | ConvertTo-Json)"
- RowKey = "$($ClearRow.RowKey)"
- PartitionKey = 'apps'
- status = 'Deployed'
- }
-}
-$EncBody = @{
- fileEncryptionInfo = @{
- encryptionKey = $intunexml.ApplicationInfo.EncryptionInfo.EncryptionKey
- macKey = $intunexml.ApplicationInfo.EncryptionInfo.MacKey
- initializationVector = $intunexml.ApplicationInfo.EncryptionInfo.InitializationVector
- mac = $intunexml.ApplicationInfo.EncryptionInfo.Mac
- profileIdentifier = $intunexml.ApplicationInfo.EncryptionInfo.ProfileIdentifier
- fileDigest = $intunexml.ApplicationInfo.EncryptionInfo.FileDigest
- fileDigestAlgorithm = $intunexml.ApplicationInfo.EncryptionInfo.FileDigestAlgorithm
- }
-} | ConvertTo-Json
-
-foreach ($tenant in $tenants) {
- Try {
-
- $ApplicationList = (New-graphGetRequest -Uri $baseuri -tenantid $Tenant) | Where-Object { $_.DisplayName -eq $ChocoApp.ApplicationName }
- if ($ApplicationList.displayname.count -ge 1) {
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) exists. Skipping this application" -Sev 'Info'
- continue
- }
- if ($chocoApp.type -eq 'WinGet') {
- Write-Host 'Winget!'
- Write-Host ($intuneBody | ConvertTo-Json -Compress)
- $NewApp = New-GraphPostRequest -Uri $baseuri -Body ($intuneBody | ConvertTo-Json -Compress) -Type POST -tenantid $tenant
- Start-Sleep -Milliseconds 200
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) uploaded as WinGet app." -Sev 'Info'
- if ($AssignTo -ne 'On') {
- $intent = if ($AssignToIntent) { 'Uninstall' } else { 'Required' }
- Set-CIPPAssignedApplication -ApplicationId $NewApp.Id -Intent $intent -TenantFilter $tenant -groupName "$AssignTo" -AppType 'WinGet'
- }
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) Successfully created" -Sev 'Info'
- exit 0
- } else {
- $NewApp = New-GraphPostRequest -Uri $baseuri -Body ($intuneBody | ConvertTo-Json) -Type POST -tenantid $tenant
-
- }
- $ContentReq = New-GraphPostRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/" -Body $ContentBody -Type POST -tenantid $tenant
- do {
- $AzFileUri = New-graphGetRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)" -tenantid $tenant
- if ($AZfileuri.uploadState -like '*fail*') { break }
- Start-Sleep -Milliseconds 300
- } while ($AzFileUri.AzureStorageUri -eq $null)
- Write-Host "Uploading file to $($AzFileUri.azureStorageUri)"
- Write-Host "Complete AZ file uri data: $($AzFileUri | ConvertTo-Json -Depth 10)"
- $chunkSizeInBytes = 4mb
- [byte[]]$bytes = [System.IO.File]::ReadAllBytes($($intunewinFilesize.fullname))
- $chunks = [Math]::Ceiling($bytes.Length / $chunkSizeInBytes)
- $id = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($chunks.ToString('0000')))
- #For anyone that reads this, The maximum chunk size is 100MB for blob storage, so we can upload it as one part and just give it the single ID. Easy :)
- $Upload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=block&blockid=$id" -Method Put -Headers @{'x-ms-blob-type' = 'BlockBlob' } -InFile $inFile -ContentType 'application/octet-stream'
- Write-Host "Upload data: $($Upload | ConvertTo-Json -Depth 10)"
- $ConfirmUpload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=blocklist" -Method Put -Body "$id"
- Write-Host "Confirm Upload data: $($ConfirmUpload | ConvertTo-Json -Depth 10)"
- $CommitReq = New-graphPostRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)/commit" -Body $EncBody -Type POST -tenantid $tenant
- Write-Host "Commit Request: $($CommitReq | ConvertTo-Json -Depth 10)"
-
- do {
- $CommitStateReq = New-graphGetRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)" -tenantid $tenant
- Write-Host "Commit State Request: $($CommitStateReq | ConvertTo-Json -Depth 10)"
- if ($CommitStateReq.uploadState -like '*fail*') {
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) Commit failed. Please check if app uploaded succesful" -Sev 'Warning'
- break
- }
- Start-Sleep -Milliseconds 300
- } while ($CommitStateReq.uploadState -eq 'commitFilePending')
- $CommitFinalizeReq = New-graphPostRequest -Uri "$($BaseURI)/$($NewApp.id)" -tenantid $tenant -Body '{"@odata.type":"#microsoft.graph.win32lobapp","committedContentVersion":"1"}' -type PATCH
- Write-Host "Commit Finalize Request: $($CommitFinalizeReq | ConvertTo-Json -Depth 10)"
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "Added Application $($chocoApp.ApplicationName)" -Sev 'Info'
- if ($AssignTo -ne 'On') {
- $intent = if ($AssignToIntent) { 'Uninstall' } else { 'Required' }
- Set-CIPPAssignedApplication -ApplicationId $NewApp.Id -Intent $intent -TenantFilter $tenant -groupName "$AssignTo" -AppType 'Win32Lob'
-
- }
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message 'Successfully added Application' -Sev 'Info'
- } catch {
- "Failed to add Application for $($Tenant): $($_.Exception.Message)"
- Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "Failed adding Application $($ChocoApp.ApplicationName). Error: $($_.Exception.Message)" -LogData (Get-CippException -Exception $_) -Sev 'Error'
- continue
- }
-
-}
diff --git a/BestPracticeAnalyser_OrchestrationStarter/function.json b/BestPracticeAnalyser_OrchestrationStarter/function.json
deleted file mode 100644
index 14c44f4f0217..000000000000
--- a/BestPracticeAnalyser_OrchestrationStarter/function.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "bindings": [
- {
- "authLevel": "anonymous",
- "name": "Request",
- "type": "httpTrigger",
- "direction": "in",
- "methods": [
- "post",
- "get"
- ]
- },
- {
- "type": "http",
- "direction": "out",
- "name": "Response"
- },
- {
- "name": "starter",
- "type": "durableClient",
- "direction": "in"
- }
- ]
-}
diff --git a/BestPracticeAnalyser_OrchestrationStarter/run.ps1 b/BestPracticeAnalyser_OrchestrationStarter/run.ps1
deleted file mode 100644
index 3135509f9b3e..000000000000
--- a/BestPracticeAnalyser_OrchestrationStarter/run.ps1
+++ /dev/null
@@ -1,40 +0,0 @@
-using namespace System.Net
-param($Request, $TriggerMetadata)
-
-if ($Request.Query.TenantFilter) {
- $TenantList = @($Request.Query.TenantFilter)
- $Name = "Best Practice Analyser ($($Request.Query.TenantFilter))"
-} else {
- $TenantList = Get-Tenants
- $Name = 'Best Practice Analyser (All Tenants)'
-}
-
-$BPATemplateTable = Get-CippTable -tablename 'templates'
-$Filter = "PartitionKey eq 'BPATemplate'"
-$Templates = ((Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json).Name
-
-$BPAReports = foreach ($Tenant in $TenantList) {
- foreach ($Template in $Templates) {
- [PSCustomObject]@{
- FunctionName = 'BPACollectData'
- Tenant = $Tenant.defaultDomainName
- Template = $Template
- QueueName = '{0} - {1}' -f $Template, $Tenant.defaultDomainName
- }
- }
-}
-
-$Queue = New-CippQueueEntry -Name $Name -TotalTasks ($BPAReports | Measure-Object).Count
-$BPAReports = $BPAReports | Select-Object *, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }
-$InputObject = [PSCustomObject]@{
- Batch = @($BPAReports)
- OrchestratorName = 'BPAOrchestrator'
- SkipLog = $true
-}
-Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
-
-$Results = [pscustomobject]@{'Results' = 'BPA started' }
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
\ No newline at end of file
diff --git a/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1 b/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
index 0b9faa0a7c8b..5b9e12f54258 100644
--- a/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
+++ b/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
@@ -1,33 +1,3 @@
param($Timer)
-if ($env:DEV_SKIP_BPA_TIMER) {
- Write-Host 'Skipping BPA timer'
- exit 0
-}
-
-$TenantList = Get-Tenants
-
-$BPATemplateTable = Get-CippTable -tablename 'templates'
-$Filter = "PartitionKey eq 'BPATemplate'"
-$Templates = ((Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json).Name
-
-
-$BPAReports = foreach ($Tenant in $TenantList) {
- foreach ($Template in $Templates) {
- [PSCustomObject]@{
- FunctionName = 'BPACollectData'
- Tenant = $Tenant.defaultDomainName
- Template = $Template
- QueueName = '{0} - {1}' -f $Template, $Tenant.defaultDomainName
- }
- }
-}
-
-$Queue = New-CippQueueEntry -Name 'Best Practice Analyser' -TotalTasks ($BPAReports | Measure-Object).Count
-$BPAReports = $BPAReports | Select-Object *, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }
-$InputObject = [PSCustomObject]@{
- Batch = @($BPAReports)
- OrchestratorName = 'BPAOrchestrator'
- SkipLog = $true
-}
-Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+Start-BPAOrchestrator
diff --git a/DomainAnalyser_OrchestrationStarter/function.json b/DomainAnalyser_OrchestrationStarter/function.json
deleted file mode 100644
index 14c44f4f0217..000000000000
--- a/DomainAnalyser_OrchestrationStarter/function.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "bindings": [
- {
- "authLevel": "anonymous",
- "name": "Request",
- "type": "httpTrigger",
- "direction": "in",
- "methods": [
- "post",
- "get"
- ]
- },
- {
- "type": "http",
- "direction": "out",
- "name": "Response"
- },
- {
- "name": "starter",
- "type": "durableClient",
- "direction": "in"
- }
- ]
-}
diff --git a/DomainAnalyser_OrchestrationStarter/run.ps1 b/DomainAnalyser_OrchestrationStarter/run.ps1
deleted file mode 100644
index 9c16b32afdba..000000000000
--- a/DomainAnalyser_OrchestrationStarter/run.ps1
+++ /dev/null
@@ -1,25 +0,0 @@
-using namespace System.Net
-
-param($Request, $TriggerMetadata)
-
-$Results = [pscustomobject]@{'Results' = 'Domain Analyser started' }
-$TenantList = Get-Tenants -IncludeAll
-$Queue = New-CippQueueEntry -Name 'Domain Analyser' -TotalTasks ($TenantList | Measure-Object).Count
-$InputObject = [PSCustomObject]@{
- QueueFunction = [PSCustomObject]@{
- FunctionName = 'GetTenants'
- DurableName = 'DomainAnalyserTenant'
- QueueId = $Queue.RowKey
- TenantParams = @{
- IncludeAll = $true
- }
- }
- OrchestratorName = 'DomainAnalyser_Tenants'
- SkipLog = $true
-}
-Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
-
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $results
- })
\ No newline at end of file
diff --git a/Domain_OrchestrationStarterTimer/run.ps1 b/Domain_OrchestrationStarterTimer/run.ps1
index 8ac7721ca590..259b225d9d75 100644
--- a/Domain_OrchestrationStarterTimer/run.ps1
+++ b/Domain_OrchestrationStarterTimer/run.ps1
@@ -5,32 +5,4 @@ if ($env:DEV_SKIP_DOMAIN_TIMER) {
exit 0
}
-try {
- if ($CurrentlyRunning) {
- $Results = [pscustomobject]@{'Results' = 'Already running. Please wait for the current instance to finish' }
- Write-LogMessage -API 'DomainAnalyser' -message 'Attempted to start analysis but an instance was already running.' -sev Info
- } else {
- #$InstanceId = Start-NewOrchestration -FunctionName 'DomainAnalyser_Orchestration'
- Write-Host "Started orchestration with ID = '$InstanceId'"
- #Orchestrator = New-OrchestrationCheckStatusResponse -Request $Timer -InstanceId $InstanceId
- Write-LogMessage -API 'DomainAnalyser' -message 'Starting Domain Analyser' -sev Info
- $Results = [pscustomobject]@{'Results' = 'Starting Domain Analyser' }
-
- $TenantList = Get-Tenants -IncludeAll
- $Queue = New-CippQueueEntry -Name 'Domain Analyser' -TotalTasks ($TenantList | Measure-Object).Count
- $InputObject = [PSCustomObject]@{
- QueueFunction = [PSCustomObject]@{
- FunctionName = 'GetTenants'
- DurableName = 'DomainAnalyserTenant'
- QueueId = $Queue.RowKey
- TenantParams = @{
- IncludeAll = $true
- }
- }
- OrchestratorName = 'DomainAnalyser_Tenants'
- SkipLog = $true
- }
- Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
- }
- Write-Host ($Orchestrator | ConvertTo-Json)
-} catch { Write-Host "Domain_OrchestratorStarterTimer Exception $($_.Exception.Message)" }
\ No newline at end of file
+Start-DomainOrchestrator
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-GetApplicationQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-GetApplicationQueue.ps1
new file mode 100644
index 000000000000..91665837d1e0
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-GetApplicationQueue.ps1
@@ -0,0 +1,5 @@
+function Push-GetApplicationQueue {
+ param()
+ $Table = Get-CippTable -tablename 'apps'
+ Get-CIPPAzDataTableEntity @Table | Select-Object @{Name = 'Name'; Expression = { $_.RowKey } }, @{Name = 'FunctionName'; Expression = { 'UploadApplication' } }
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-UploadApplication.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-UploadApplication.ps1
new file mode 100644
index 000000000000..f33ef37a8e84
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Applications/Push-UploadApplication.ps1
@@ -0,0 +1,135 @@
+function Push-UploadApplication {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding()]
+ param($Item)
+
+ try {
+ $Table = Get-CippTable -tablename 'apps'
+ $Filter = "PartitionKey eq 'apps' and RowKey eq '$($Item.Name)'"
+
+ $ModuleRoot = (Get-Module CIPPCore).ModuleBase
+ $CippRoot = (Get-Item $ModuleRoot).Parent.Parent
+ Set-Location $CippRoot
+
+ $ChocoApp = (Get-CIPPAzDataTableEntity @Table -filter $Filter).JSON | ConvertFrom-Json
+ $intuneBody = $ChocoApp.IntuneBody
+ $tenants = if ($chocoapp.Tenant -eq 'AllTenants') {
+ (Get-tenants).defaultDomainName
+ } else {
+ $chocoapp.Tenant
+ }
+ if ($chocoApp.type -eq 'MSPApp') {
+ [xml]$Intunexml = Get-Content "AddMSPApp\$($ChocoApp.MSPAppName).app.xml"
+ $intunewinFilesize = (Get-Item "AddMSPApp\$($ChocoApp.MSPAppName).intunewin")
+ $Infile = "AddMSPApp\$($ChocoApp.MSPAppName).intunewin"
+ } else {
+ [xml]$Intunexml = Get-Content 'AddChocoApp\choco.app.xml'
+ $intunewinFilesize = (Get-Item 'AddChocoApp\IntunePackage.intunewin')
+ $Infile = "AddChocoApp\$($intunexml.ApplicationInfo.FileName)"
+ }
+ $assignTo = $ChocoApp.AssignTo
+ $AssignToIntent = $ChocoApp.InstallationIntent
+ $Baseuri = 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps'
+ $ContentBody = ConvertTo-Json @{
+ name = $intunexml.ApplicationInfo.FileName
+ size = [int64]$intunexml.ApplicationInfo.UnencryptedContentSize
+ sizeEncrypted = [int64]($intunewinFilesize).length
+ }
+ $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter
+ $RemoveCacheFile = if ($chocoapp.Tenant -ne 'AllTenants') {
+ Remove-AzDataTableEntity @Table -Entity $clearRow
+ } else {
+ $Table.Force = $true
+ Add-CIPPAzDataTableEntity @Table -Entity @{
+ JSON = "$($ChocoApp | ConvertTo-Json)"
+ RowKey = "$($ClearRow.RowKey)"
+ PartitionKey = 'apps'
+ status = 'Deployed'
+ }
+ }
+ $EncBody = @{
+ fileEncryptionInfo = @{
+ encryptionKey = $intunexml.ApplicationInfo.EncryptionInfo.EncryptionKey
+ macKey = $intunexml.ApplicationInfo.EncryptionInfo.MacKey
+ initializationVector = $intunexml.ApplicationInfo.EncryptionInfo.InitializationVector
+ mac = $intunexml.ApplicationInfo.EncryptionInfo.Mac
+ profileIdentifier = $intunexml.ApplicationInfo.EncryptionInfo.ProfileIdentifier
+ fileDigest = $intunexml.ApplicationInfo.EncryptionInfo.FileDigest
+ fileDigestAlgorithm = $intunexml.ApplicationInfo.EncryptionInfo.FileDigestAlgorithm
+ }
+ } | ConvertTo-Json
+
+ foreach ($tenant in $tenants) {
+ Try {
+ $ApplicationList = (New-graphGetRequest -Uri $baseuri -tenantid $Tenant) | Where-Object { $_.DisplayName -eq $ChocoApp.ApplicationName }
+ if ($ApplicationList.displayname.count -ge 1) {
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) exists. Skipping this application" -Sev 'Info'
+ continue
+ }
+ if ($chocoApp.type -eq 'WinGet') {
+ Write-Host 'Winget!'
+ Write-Host ($intuneBody | ConvertTo-Json -Compress)
+ $NewApp = New-GraphPostRequest -Uri $baseuri -Body ($intuneBody | ConvertTo-Json -Compress) -Type POST -tenantid $tenant
+ Start-Sleep -Milliseconds 200
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) uploaded as WinGet app." -Sev 'Info'
+ if ($AssignTo -ne 'On') {
+ $intent = if ($AssignToIntent) { 'Uninstall' } else { 'Required' }
+ Set-CIPPAssignedApplication -ApplicationId $NewApp.Id -Intent $intent -TenantFilter $tenant -groupName "$AssignTo" -AppType 'WinGet'
+ }
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) Successfully created" -Sev 'Info'
+ exit 0
+ } else {
+ $NewApp = New-GraphPostRequest -Uri $baseuri -Body ($intuneBody | ConvertTo-Json) -Type POST -tenantid $tenant
+
+ }
+ $ContentReq = New-GraphPostRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/" -Body $ContentBody -Type POST -tenantid $tenant
+ do {
+ $AzFileUri = New-graphGetRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)" -tenantid $tenant
+ if ($AZfileuri.uploadState -like '*fail*') { break }
+ Start-Sleep -Milliseconds 300
+ } while ($AzFileUri.AzureStorageUri -eq $null)
+ Write-Host "Uploading file to $($AzFileUri.azureStorageUri)"
+ Write-Host "Complete AZ file uri data: $($AzFileUri | ConvertTo-Json -Depth 10)"
+ $chunkSizeInBytes = 4mb
+ [byte[]]$bytes = [System.IO.File]::ReadAllBytes($($intunewinFilesize.fullname))
+ $chunks = [Math]::Ceiling($bytes.Length / $chunkSizeInBytes)
+ $id = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($chunks.ToString('0000')))
+ #For anyone that reads this, The maximum chunk size is 100MB for blob storage, so we can upload it as one part and just give it the single ID. Easy :)
+ $Upload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=block&blockid=$id" -Method Put -Headers @{'x-ms-blob-type' = 'BlockBlob' } -InFile $inFile -ContentType 'application/octet-stream'
+ Write-Host "Upload data: $($Upload | ConvertTo-Json -Depth 10)"
+ $ConfirmUpload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=blocklist" -Method Put -Body "$id"
+ Write-Host "Confirm Upload data: $($ConfirmUpload | ConvertTo-Json -Depth 10)"
+ $CommitReq = New-graphPostRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)/commit" -Body $EncBody -Type POST -tenantid $tenant
+ Write-Host "Commit Request: $($CommitReq | ConvertTo-Json -Depth 10)"
+
+ do {
+ $CommitStateReq = New-graphGetRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)" -tenantid $tenant
+ Write-Host "Commit State Request: $($CommitStateReq | ConvertTo-Json -Depth 10)"
+ if ($CommitStateReq.uploadState -like '*fail*') {
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "$($ChocoApp.ApplicationName) Commit failed. Please check if app uploaded succesful" -Sev 'Warning'
+ break
+ }
+ Start-Sleep -Milliseconds 300
+ } while ($CommitStateReq.uploadState -eq 'commitFilePending')
+ $CommitFinalizeReq = New-graphPostRequest -Uri "$($BaseURI)/$($NewApp.id)" -tenantid $tenant -Body '{"@odata.type":"#microsoft.graph.win32lobapp","committedContentVersion":"1"}' -type PATCH
+ Write-Host "Commit Finalize Request: $($CommitFinalizeReq | ConvertTo-Json -Depth 10)"
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "Added Application $($chocoApp.ApplicationName)" -Sev 'Info'
+ if ($AssignTo -ne 'On') {
+ $intent = if ($AssignToIntent) { 'Uninstall' } else { 'Required' }
+ Set-CIPPAssignedApplication -ApplicationId $NewApp.Id -Intent $intent -TenantFilter $tenant -groupName "$AssignTo" -AppType 'Win32Lob'
+
+ }
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message 'Successfully added Application' -Sev 'Info'
+ } catch {
+ "Failed to add Application for $($Tenant): $($_.Exception.Message)"
+ Write-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "Failed adding Application $($ChocoApp.ApplicationName). Error: $($_.Exception.Message)" -LogData (Get-CippException -Exception $_) -Sev 'Error'
+ continue
+ }
+ }
+ } catch {
+ Write-Host "Error pushing application: $($_.Exception.Message)"
+ }
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAppUpload.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAppUpload.ps1
new file mode 100644
index 000000000000..366da173390e
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAppUpload.ps1
@@ -0,0 +1,23 @@
+function Invoke-ExecAppUpload {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ try {
+ Start-ApplicationOrchestrator
+ } catch {
+ Write-Host "orchestrator error: $($_.Exception.Message)"
+ }
+
+ $Results = [pscustomobject]@{'Results' = 'Started application queue' }
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $results
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1
new file mode 100644
index 000000000000..fb2b4f4e7c48
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1
@@ -0,0 +1,18 @@
+function Invoke-ExecBPA {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Tenant.BestPracticeAnalyser.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ Start-BPAOrchestrator -TenantFilter $Request.Query.TenantFilter
+
+ $Results = [pscustomobject]@{'Results' = 'BPA started' }
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecDomainAnalyser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecDomainAnalyser.ps1
new file mode 100644
index 000000000000..50de572b0729
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecDomainAnalyser.ps1
@@ -0,0 +1,17 @@
+function Invoke-ExecDomainAnalyser {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Tenant.DomainAnalyser.Read
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ Start-DomainOrchestrator
+
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $results
+ })
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
index 41f16aba1e48..ae08abddcd8a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
@@ -13,40 +13,50 @@ Function Invoke-ListmailboxPermissions {
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
-
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
-
# Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
+ $TenantFilter = $Request.Query.tenantFilter
+ $UserID = $Request.Query.userId
- Write-Host "Tenant Filter: $TenantFilter"
try {
- $Bytes = [System.Text.Encoding]::UTF8.GetBytes($Request.Query.UserID)
- $base64IdentityParam = [Convert]::ToBase64String($Bytes)
- $PermsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($Request.Query.UserID)')/MailboxPermission" -Tenantid $tenantfilter -scope ExchangeOnline
- $PermsRequest2 = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Recipient('$base64IdentityParam')?`$expand=RecipientPermission&isEncoded=true" -Tenantid $tenantfilter -scope ExchangeOnline
- $PermRequest3 = New-ExoRequest -Anchor $Request.Query.UserID -tenantid $Tenantfilter -cmdlet 'Get-Mailbox' -cmdParams @{Identity = $($Request.Query.UserID); }
-
- $GraphRequest = foreach ($Perm in $PermsRequest, $PermsRequest2.RecipientPermission, $PermRequest3) {
+ $Requests = @(
+ @{
+ CmdletInput = @{
+ CmdletName = 'Get-Mailbox'
+ Parameters = @{ Identity = $UserID }
+ }
+ }
+ @{
+ CmdletInput = @{
+ CmdletName = 'Get-MailboxPermission'
+ Parameters = @{ Identity = $UserID }
+ }
+ }
+ @{
+ CmdletInput = @{
+ CmdletName = 'Get-RecipientPermission'
+ Parameters = @{ Identity = $UserID }
+ }
+ }
+ )
- if ($perm.Trustee) {
- $perm | Where-Object Trustee | ForEach-Object { [PSCustomObject]@{
+ $Results = New-ExoBulkRequest -tenantid $TenantFilter -cmdletArray $Requests
+ $GraphRequest = foreach ($Perm in $Results) {
+ if ($Perm.Trustee) {
+ $Perm | Where-Object Trustee | ForEach-Object { [PSCustomObject]@{
User = $_.Trustee
Permissions = $_.accessRights
}
}
-
}
- if ($perm.PermissionList) {
- $perm | Where-Object User | ForEach-Object { [PSCustomObject]@{
+ if ($Perm.AccessRights) {
+ $Perm | Where-Object User | ForEach-Object { [PSCustomObject]@{
User = $_.User
- Permissions = $_.PermissionList.accessRights -join ', '
+ Permissions = $_.AccessRights -join ', '
}
}
}
- if ($perm.GrantSendonBehalfTo -ne $null) {
- $perm.GrantSendonBehalfTo | ForEach-Object { [PSCustomObject]@{
+ if ($Perm.GrantSendonBehalfTo -ne $null) {
+ $Perm.GrantSendonBehalfTo | ForEach-Object { [PSCustomObject]@{
User = $_
Permissions = 'SendOnBehalf'
}
@@ -64,7 +74,4 @@ Function Invoke-ListmailboxPermissions {
StatusCode = $StatusCode
Body = @($GraphRequest)
})
-
-
-
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ApplicationOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ApplicationOrchestrator.ps1
new file mode 100644
index 000000000000..c564d6a70d60
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ApplicationOrchestrator.ps1
@@ -0,0 +1,22 @@
+function Start-ApplicationOrchestrator {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ Param()
+
+ Write-LogMessage -API 'IntuneApps' -message 'Started uploading applications to tenants' -sev Info
+
+ $InputObject = [PSCustomObject]@{
+ OrchestratorName = 'ApplicationOrchestrator'
+ SkipLog = $true
+ QueueFunction = @{
+ FunctionName = 'GetApplicationQueue'
+ }
+ }
+
+ if ($PSCmdlet.ShouldProcess('Upload Applications')) {
+ return Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+ }
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-BPAOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-BPAOrchestrator.ps1
new file mode 100644
index 000000000000..fbe51460a0dc
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-BPAOrchestrator.ps1
@@ -0,0 +1,69 @@
+function Start-BPAOrchestrator {
+ <#
+ .SYNOPSIS
+ Start the Best Practice Analyser
+ .DESCRIPTION
+ This function starts the Best Practice Analyser
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ param(
+ $TenantFilter = 'AllTenants'
+ )
+
+ try {
+ if ($TenantFilter -ne 'AllTenants') {
+ Write-Verbose "TenantFilter: $TenantFilter"
+ if ($TenantFilter -notmatch '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
+ $TenantFilter = @($TenantFilter)
+ } else {
+ Write-Verbose 'Got GUID: Looking up tenant'
+ $TenantFilter = Get-Tenants -TenantFilter $TenantFilter | Select-Object -ExpandProperty defaultDomainName
+ }
+ $TenantList = @($TenantFilter)
+ $Name = "Best Practice Analyser ($TenantFilter)"
+ } else {
+ $TenantList = (Get-Tenants).defaultDomainName
+ $Name = 'Best Practice Analyser'
+ }
+
+ Write-Verbose 'Getting BPA templates'
+ $BPATemplateTable = Get-CippTable -tablename 'templates'
+ $Filter = "PartitionKey eq 'BPATemplate'"
+ $Templates = ((Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json).Name
+
+ Write-Verbose 'Creating orchestrator batch'
+ $BPAReports = foreach ($Tenant in $TenantList) {
+ foreach ($Template in $Templates) {
+ [PSCustomObject]@{
+ FunctionName = 'BPACollectData'
+ Tenant = $Tenant
+ Template = $Template
+ QueueName = '{0} - {1}' -f $Template, $Tenant
+ }
+ }
+ }
+
+ if (($BPAReports | Measure-Object).Count -eq 0) {
+ Write-Information 'No BPA reports to run'
+ return 0
+ }
+
+ if ($PSCmdlet.ShouldProcess($Name, 'Starting Orchestrator')) {
+ Write-LogMessage -API 'BestPracticeAnalyser' -message 'Starting Best Practice Analyser' -sev Info
+ $Queue = New-CippQueueEntry -Name $Name -TotalTasks ($BPAReports | Measure-Object).Count
+ $BPAReports = $BPAReports | Select-Object *, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }
+ $InputObject = [PSCustomObject]@{
+ Batch = @($BPAReports)
+ OrchestratorName = 'BPAOrchestrator'
+ SkipLog = $true
+ }
+ return Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+ }
+ } catch {
+ $ErrorMessage = Get-CippException -Exception $_
+ Write-LogMessage -API 'BestPracticeAnalyser' -message "Could not start Best Practice Analyser: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage
+ return $false
+ }
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-DomainOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-DomainOrchestrator.ps1
new file mode 100644
index 000000000000..60c1d20600b7
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-DomainOrchestrator.ps1
@@ -0,0 +1,41 @@
+function Start-DomainOrchestrator {
+ <#
+ .SYNOPSIS
+ Start the Domain Orchestrator
+ .DESCRIPTION
+ This function starts the Domain Orchestrator
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ param()
+ try {
+ $TenantList = Get-Tenants -IncludeAll
+ if (($TenantList | Measure-Object).Count -eq 0) {
+ Write-Information 'No tenants found'
+ return 0
+ }
+
+ $Queue = New-CippQueueEntry -Name 'Domain Analyser' -TotalTasks ($TenantList | Measure-Object).Count
+ $InputObject = [PSCustomObject]@{
+ QueueFunction = [PSCustomObject]@{
+ FunctionName = 'GetTenants'
+ DurableName = 'DomainAnalyserTenant'
+ QueueId = $Queue.RowKey
+ TenantParams = @{
+ IncludeAll = $true
+ }
+ }
+ OrchestratorName = 'DomainAnalyser_Tenants'
+ SkipLog = $true
+ }
+ if ($PSCmdlet.ShouldProcess('Domain Analyser', 'Starting Orchestrator')) {
+ Write-LogMessage -API 'DomainAnalyser' -message 'Starting Domain Analyser' -sev Info
+ return Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+ }
+ } catch {
+ $ErrorMessage = Get-CippException -Exception $_
+ Write-LogMessage -API 'DomainAnalyser' -message "Could not start Domain Analyser: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage
+ return $false
+ }
+}