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 + } +}