diff --git a/Activity_AddOrUpdateTableRows/run.ps1 b/Activity_AddOrUpdateTableRows/run.ps1
index 6bb7e218b987..adc07df73e23 100644
--- a/Activity_AddOrUpdateTableRows/run.ps1
+++ b/Activity_AddOrUpdateTableRows/run.ps1
@@ -3,11 +3,10 @@ $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) table: $($_.Exception.Message)" -sev error
- }
+ 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/Applications_Orchestrator/run.ps1 b/Applications_Orchestrator/run.ps1
index 9c8457ff91fc..ebf60eb55628 100644
--- a/Applications_Orchestrator/run.ps1
+++ b/Applications_Orchestrator/run.ps1
@@ -17,7 +17,7 @@ try {
$Outputs = Wait-ActivityFunction -Task $ParallelTasks
Write-Host $Outputs
}
-catch {
+catch {
Write-Host "Applications_Orchestrator exception: $($_.Exception.Message)"
}
finally {
diff --git a/Applications_Upload/run.ps1 b/Applications_Upload/run.ps1
index a92637a42882..b1aacdc41318 100644
--- a/Applications_Upload/run.ps1
+++ b/Applications_Upload/run.ps1
@@ -1,14 +1,14 @@
param($name)
$Table = Get-CippTable -tablename 'apps'
-$Filter = "PartitionKey eq 'apps' and RowKey eq '$name'"
+$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') {
+$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")
@@ -25,7 +25,7 @@ $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
@@ -54,11 +54,11 @@ foreach ($tenant in $tenants) {
Try {
$ApplicationList = (New-graphGetRequest -Uri $baseuri -tenantid $Tenant) | Where-Object { $_.DisplayName -eq $ChocoApp.ApplicationName }
- if ($ApplicationList.displayname.count -ge 1) {
+ 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') {
+ 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
@@ -79,8 +79,8 @@ foreach ($tenant in $tenants) {
$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)
-
+ } while ($AzFileUri.AzureStorageUri -eq $null)
+
$chunkSizeInBytes = 4mb
[byte[]]$bytes = [System.IO.File]::ReadAllBytes($($intunewinFilesize.fullname))
$chunks = [Math]::Ceiling($bytes.Length / $chunkSizeInBytes)
@@ -89,15 +89,15 @@ foreach ($tenant in $tenants) {
$Upload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=block&blockid=$id" -Method Put -Headers @{'x-ms-blob-type' = 'BlockBlob' } -InFile $inFile -ContentType 'application/octet-stream'
$ConfirmUpload = Invoke-RestMethod -Uri "$($AzFileUri.azureStorageUri)&comp=blocklist" -Method Put -Body "$id"
$CommitReq = New-graphPostRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)/commit" -Body $EncBody -Type POST -tenantid $tenant
-
+
do {
$CommitStateReq = New-graphGetRequest -Uri "$($BaseURI)/$($NewApp.id)/microsoft.graph.win32lobapp/contentVersions/1/files/$($ContentReq.id)" -tenantid $tenant
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
+ break
}
Start-Sleep -Milliseconds 300
- } while ($CommitStateReq.uploadState -eq 'commitFilePending')
+ } 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-LogMessage -api 'AppUpload' -tenant $($Tenant) -message "Added Application $($chocoApp.ApplicationName)" -Sev 'Info'
if ($AssignTo -ne 'On') {
@@ -108,7 +108,7 @@ foreach ($tenant in $tenants) {
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)" -Sev 'Error'
+ 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_All/run.ps1 b/BestPracticeAnalyser_All/run.ps1
index ddd92560ccda..6e90102a161a 100644
--- a/BestPracticeAnalyser_All/run.ps1
+++ b/BestPracticeAnalyser_All/run.ps1
@@ -107,7 +107,7 @@ $AddRow = foreach ($Template in $templates) {
try {
Add-CIPPAzDataTableEntity @Table -Entity $Result -Force
} catch {
- Write-LogMessage -API 'BPA' -tenant $tenant -message "Error getting saving data for $($template.Name) - $($TenantName.customerId). Error: $($_.Exception.Message)" -sev Error
+ Write-LogMessage -API 'BPA' -tenant $tenant -message "Error getting saving data for $($template.Name) - $($TenantName.customerId). Error: $($_.Exception.Message)" -LogData (Get-CippException -Exception $_) -sev Error
}
}
diff --git a/DomainAnalyser_All/run.ps1 b/DomainAnalyser_All/run.ps1
index c9f0b989c04e..981afa4b7bbc 100644
--- a/DomainAnalyser_All/run.ps1
+++ b/DomainAnalyser_All/run.ps1
@@ -36,6 +36,7 @@ try {
$Result = [PSCustomObject]@{
Tenant = $Tenant.Tenant
+ TenantID = $Tenant.TenantGUID
GUID = $($Domain.Replace('.', ''))
LastRefresh = $(Get-Date (Get-Date).ToUniversalTime() -UFormat '+%Y-%m-%dT%H:%M:%S.000Z')
Domain = $Domain
@@ -116,8 +117,8 @@ try {
$ScoreExplanation.Add('No SPF Record Found') | Out-Null
}
} catch {
- $Message = 'SPF Exception: {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -sev Error
+ $Message = 'SPF Error'
+ Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
throw $Message
}
@@ -179,8 +180,8 @@ try {
}
}
} catch {
- $Message = 'DMARC Exception: {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -sev Error
+ $Message = 'DMARC Error'
+ Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
throw $Message
}
@@ -197,8 +198,8 @@ try {
$ScoreExplanation.Add('DNSSEC Not Configured or Enabled') | Out-Null
}
} catch {
- $Message = 'DNSSEC Exception: {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -sev Error
+ $Message = 'DNSSEC Error'
+ Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
throw $Message
}
@@ -226,8 +227,8 @@ try {
$ScoreExplanation.Add('DKIM Not Configured') | Out-Null
}
} catch {
- $Message = 'DKIM Exception: {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -sev Error
+ $Message = 'DKIM Exception'
+ Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
throw $Message
}
# Final Score
diff --git a/DomainAnalyser_GetTenantDomains/run.ps1 b/DomainAnalyser_GetTenantDomains/run.ps1
index 4e0fd71f2be8..6c4b8b0d8110 100644
--- a/DomainAnalyser_GetTenantDomains/run.ps1
+++ b/DomainAnalyser_GetTenantDomains/run.ps1
@@ -9,10 +9,13 @@ $TenantDomains = $Tenants | ForEach-Object -Parallel {
$Tenant = $_
# Get Domains to Lookup
try {
- $Domains = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains' -tenantid $Tenant.defaultDomainName | Where-Object { ($_.id -notlike '*.microsoftonline.com' -and $_.id -NotLike '*.exclaimer.cloud' -and $_.id -NotLike '*.codetwo.online' -and $_.id -NotLike '*.call2teams.com' -and $_.isVerified) }
+ $Domains = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains' -tenantid $Tenant.defaultDomainName | Where-Object { ($_.id -notlike '*.microsoftonline.com' -and $_.id -NotLike '*.exclaimer.cloud' -and $_.id -Notlike '*.excl.cloud' -and $_.id -NotLike '*.codetwo.online' -and $_.id -NotLike '*.call2teams.com' -and $_.isVerified) }
+
foreach ($d in $domains) {
[PSCustomObject]@{
Tenant = $Tenant.defaultDomainName
+ TenantGUID = $Tenant.customerId
+ InitialDomainName = $Tenant.initialDomainName
Domain = $d.id
AuthenticationType = $d.authenticationType
IsAdminManaged = $d.isAdminManaged
@@ -24,7 +27,7 @@ $TenantDomains = $Tenants | ForEach-Object -Parallel {
}
}
} catch {
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.defaultDomainName -message "DNS Analyser GraphGetRequest Exception: $($_.Exception.Message)" -sev Error
+ Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.defaultDomainName -message 'DNS Analyser GraphGetRequest' -LogData (Get-CippException -Exception $_) -sev Error
}
} | Sort-Object -Unique -Property Domain
@@ -57,11 +60,12 @@ if ($TenantCount -gt 0) {
$Filter = "PartitionKey eq 'TenantDomains' and RowKey eq '{0}'" -f $Tenant.Domain
$Domain = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter
- if (!$Domain) {
+ if (!$Domain -or $null -eq $Domain.TenantGUID) {
$DomainObject = [pscustomobject]@{
DomainAnalyser = ''
TenantDetails = $TenantDetails
TenantId = $Tenant.Tenant
+ TenantGUID = $Tenant.TenantGUID
DkimSelectors = ''
MailProviders = ''
RowKey = $Tenant.Domain
@@ -87,6 +91,6 @@ if ($TenantCount -gt 0) {
# Batch insert all tenant domains
try {
Add-CIPPAzDataTableEntity @DomainTable -Entity $TenantDomainObjects -Force
- } catch { Write-LogMessage -API 'DomainAnalyser' -message "Domain Analyser GetTenantDomains Error $($_.Exception.Message)" -sev info }
- } catch { Write-LogMessage -API 'DomainAnalyser' -message "GetTenantDomains loop exception: $($_.Exception.Message) line $($_.InvocationInfo.ScriptLineNumber)" -sev 'Error' }
+ } catch { Write-LogMessage -API 'DomainAnalyser' -message 'Domain Analyser GetTenantDomains error' -sev info -LogData (Get-CippException -Exception $_) }
+ } catch { Write-LogMessage -API 'DomainAnalyser' -message 'GetTenantDomains loop error' -sev 'Error' -LogData (Get-CippException -Exception $_) }
}
diff --git a/DomainAnalyser_Orchestration/run.ps1 b/DomainAnalyser_Orchestration/run.ps1
index 34848e03284d..e8d51585ffa7 100644
--- a/DomainAnalyser_Orchestration/run.ps1
+++ b/DomainAnalyser_Orchestration/run.ps1
@@ -33,7 +33,7 @@ try {
Write-Host "Orchestrator exception UpdateDomains $($_.Exception.Message)"
}
} catch {
- Write-LogMessage -API 'DomainAnalyser' -message "Domain Analyser Orchestrator Error $($_.Exception.Message)" -sev info
+ Write-LogMessage -API 'DomainAnalyser' -message 'Domain Analyser Orchestrator Error' -sev info -LogData (Get-CippException -Exception $_)
#Write-Host $_.Exception | ConvertTo-Json
} finally {
Write-LogMessage -API 'DomainAnalyser' -message 'Domain Analyser has Finished' -sev Info
diff --git a/ExecSchedulerBillingRun/run.ps1 b/ExecSchedulerBillingRun/run.ps1
index ff93986817b2..3ea7e6621fac 100644
--- a/ExecSchedulerBillingRun/run.ps1
+++ b/ExecSchedulerBillingRun/run.ps1
@@ -3,20 +3,19 @@ param($QueueItem)
# Get the current universal time in the default string format.
try {
- Write-LogMessage -API "Scheduler_Billing" -tenant "none" -message "Starting billing processing." -sev Info
+ Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message 'Starting billing processing.' -sev Info
$Table = Get-CIPPTable -TableName Extensionsconfig
$Configuration = (Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json -Depth 10
foreach ($ConfigItem in $Configuration.psobject.properties.name) {
switch ($ConfigItem) {
- "Gradient" {
+ 'Gradient' {
If ($Configuration.Gradient.enabled -and $Configuration.Gradient.BillingEnabled) {
New-GradientServiceSyncRun
}
}
}
}
-}
-catch {
- Write-LogMessage -API "Scheduler_Billing" -tenant "none" -message "Could not start billing processing $($_.Exception.Message)" -sev Error
+} catch {
+ Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message 'Could not start billing processing' -sev Error -LogData (Get-CippException -Exception $_)
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1
index 6f03e28b64e2..befa8155df6c 100644
--- a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1
+++ b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1
@@ -9,7 +9,7 @@ function Add-CIPPAzDataTableEntity {
foreach ($SingleEnt in $Entity) {
try {
- Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt
+ Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt -ErrorAction Stop
} catch [System.Exception] {
if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge') {
try {
@@ -52,6 +52,8 @@ function Add-CIPPAzDataTableEntity {
throw "Error processing entity: $($_.Exception.Message)."
}
} else {
+ Write-Host "THE ERROR IS $($_.Exception.ErrorCode)"
+
throw $_
}
}
diff --git a/Modules/CIPPCore/Public/Add-CIPPGroupMember.ps1 b/Modules/CIPPCore/Public/Add-CIPPGroupMember.ps1
index a4c66a07cb7b..b29972bcce3a 100644
--- a/Modules/CIPPCore/Public/Add-CIPPGroupMember.ps1
+++ b/Modules/CIPPCore/Public/Add-CIPPGroupMember.ps1
@@ -1,18 +1,18 @@
function Add-CIPPGroupMember(
[string]$ExecutingUser,
- [string]$GroupType,
+ [string]$GroupType,
[string]$GroupId,
- [string]$Member,
+ [string]$Member,
[string]$TenantFilter,
[string]$APIName = 'Add Group Member'
) {
try {
if ($member -like '*#EXT#*') { $member = [System.Web.HttpUtility]::UrlEncode($member) }
- $MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $TenantFilter).id
+ $MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $TenantFilter).id
$addmemberbody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }"
if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') {
$Params = @{ Identity = $GroupId; Member = $member; BypassSecurityGroupManagerCheck = $true }
- New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
+ New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
} else {
New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $TenantFilter -type patch -body $addmemberbody -Verbose
}
@@ -21,9 +21,9 @@ function Add-CIPPGroupMember(
return $message
return
} catch {
- $message = "Failed to add user $($Member) to $($GroupId): $($_.Exception.Message)"
- Write-LogMessage -user $ExecutingUser -API $APIName -tenant $TenantFilter -message $message -Sev 'error'
- return $message
+ $message = "Failed to add user $($Member) to $($GroupId)"
+ Write-LogMessage -user $ExecutingUser -API $APIName -tenant $TenantFilter -message $message -Sev 'error' -LogData (Get-CippException -Exception $_)
+ return $message
}
}
diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
index 04c5d358d599..8cd5b159d458 100644
--- a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
+++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
@@ -18,8 +18,7 @@ function Add-CIPPScheduledTask {
$ht[$p.Key] = $p.Value
}
$Parameters[$Key] = [PSCustomObject]$ht
- }
- else {
+ } else {
$Parameters[$Key] = $Param
}
}
@@ -30,10 +29,15 @@ function Add-CIPPScheduledTask {
}
$AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress)
if ($Parameters -eq 'null') { $Parameters = '' }
+ if (!$Task.RowKey) {
+ $RowKey = (New-Guid).Guid
+ } else {
+ $RowKey = $Task.RowKey
+ }
$entity = @{
PartitionKey = [string]'ScheduledTask'
TaskState = [string]'Planned'
- RowKey = [string]"$(New-Guid)"
+ RowKey = [string]$RowKey
Tenant = [string]$task.TenantFilter
Name = [string]$task.Name
Command = [string]$task.Command.value
@@ -46,10 +50,9 @@ function Add-CIPPScheduledTask {
Results = 'Planned'
}
try {
- Add-CIPPAzDataTableEntity @Table -Entity $entity
- }
- catch {
+ Add-CIPPAzDataTableEntity @Table -Entity $entity -Force
+ } catch {
return "Could not add task: $($_.Exception.Message)"
}
- return "Successfully added task"
+ return 'Successfully added task'
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertMFAAlertUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertMFAAlertUsers.ps1
index e6401a7b117f..6af3ca798606 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertMFAAlertUsers.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertMFAAlertUsers.ps1
@@ -6,7 +6,7 @@ function Push-CIPPAlertMFAAlertUsers {
)
try {
- $users = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?$filter=isMfaRegistered eq false and userType eq ''member''&$select=userPrincipalName,lastUpdatedDateTime,isMfaRegistered' -tenantid $($Item.tenant)
+ $users = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/reports/authenticationMethods/userRegistrationDetails?$top=999&filter=isMfaRegistered eq false and userType eq ''member''&$select=userPrincipalName,lastUpdatedDateTime,isMfaRegistered' -tenantid $($Item.tenant)
if ($users.UserPrincipalName) {
Write-AlertMessage -tenant $Item.tenant -message "The following $($users.Count) users do not have MFA registered: $($users.UserPrincipalName -join ', ')"
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertNewAppApproval.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertNewAppApproval.ps1
index 438fd62739d6..f5317b9769a5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertNewAppApproval.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPAlertNewAppApproval.ps1
@@ -6,7 +6,7 @@ function Push-CIPPAlertNewAppApproval {
[pscustomobject]$Item
)
try {
- $Approvals = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests' -tenantid $item.tenant
+ $Approvals = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests' -tenantid $item.tenant | Where-Object -Property requestStatus -EQ 'inProgress'
if ($Approvals.count -gt 1) {
Write-AlertMessage -tenant $($Item.tenant) -message "There is are $($Approvals.count) App Approvals waiting."
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
index cc23c195820c..221068716478 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
@@ -215,39 +215,40 @@ Function Push-ExecOnboardTenantQueue {
$OnboardingSteps.Step3.Status = 'failed'
$OnboardingSteps.Step3.Message = 'Failed to map security groups, no pending invite available'
}
+ }
- do {
- $AccessAssignments = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$Id/accessAssignments"
- Start-Sleep -Seconds 15
- } while ($AccessAssignments.status -contains 'pending' -and (Get-Date) -lt $Start.AddMinutes(8))
+ do {
+ $AccessAssignments = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$Id/accessAssignments"
+ Start-Sleep -Seconds 15
+ } while ($AccessAssignments.status -contains 'pending' -and (Get-Date) -lt $Start.AddMinutes(8))
- if ($AccessAssignments.status -notcontains 'pending') {
- $OnboardingSteps.Step3.Message = 'Group check: Access assignments are mapped and active'
- $OnboardingSteps.Step3.Status = 'succeeded'
- if ($Item.AddMissingGroups -eq $true) {
- $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Checking for missing groups for SAM user' })
- $SamUserId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me?`$select=id").id
- $CurrentMemberships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me/transitiveMemberOf?`$select=id,displayName"
- foreach ($Role in $Item.Roles) {
- if ($CurrentMemberships.id -notcontains $Role.GroupId) {
- $PostBody = @{
- '@odata.id' = 'https://graph.microsoft.com/v1.0/directoryObjects/{0}' -f $SamUserId
- } | ConvertTo-Json -Compress
- try {
- New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($Role.GroupId)/members/`$ref" -body $PostBody -AsApp $true -NoAuthCheck $true
- $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = "Added SAM user to $($Role.GroupName)" })
- } catch {
- $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = "Failed to add SAM user to $($Role.GroupName) - $($_.Exception.Message)" })
- }
+ if ($AccessAssignments.status -notcontains 'pending') {
+ $OnboardingSteps.Step3.Message = 'Group check: Access assignments are mapped and active'
+ $OnboardingSteps.Step3.Status = 'succeeded'
+ if ($Item.AddMissingGroups -eq $true) {
+ $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Checking for missing groups for SAM user' })
+ $SamUserId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me?`$select=id").id
+ $CurrentMemberships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me/transitiveMemberOf?`$select=id,displayName"
+ foreach ($Role in $Item.Roles) {
+ if ($CurrentMemberships.id -notcontains $Role.GroupId) {
+ $PostBody = @{
+ '@odata.id' = 'https://graph.microsoft.com/v1.0/directoryObjects/{0}' -f $SamUserId
+ } | ConvertTo-Json -Compress
+ try {
+ New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($Role.GroupId)/members/`$ref" -body $PostBody -AsApp $true -NoAuthCheck $true
+ $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = "Added SAM user to $($Role.GroupName)" })
+ } catch {
+ $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = "Failed to add SAM user to $($Role.GroupName) - $($_.Exception.Message)" })
}
}
- $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'SAM user group check completed' })
}
- } else {
- $OnboardingSteps.Step3.Message = 'Group check: Access assignments are still pending, try again later'
- $OnboardingSteps.Step3.Status = 'failed'
- $TenantOnboarding.Status = 'failed'
+ $Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'SAM user group check completed' })
}
+ } else {
+ $OnboardingSteps.Step3.Message = 'Group check: Access assignments are still pending, try again later'
+ $OnboardingSteps.Step3.Status = 'failed'
+ $TenantOnboarding.Status = 'failed'
+ Write-LogMessage -API 'Onboarding' -message "Tenant onboarding failed at group mapping step for $($Relationship.customer.displayName)" -Sev 'Error'
}
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
@@ -298,6 +299,7 @@ Function Push-ExecOnboardTenantQueue {
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
+ Write-LogMessage -API 'Onboarding' -message "Tenant onboarding failed at CPV step for $($Relationship.customer.displayName)" -Sev 'Error'
return
}
$Refreshing = $true
@@ -357,6 +359,7 @@ Function Push-ExecOnboardTenantQueue {
} catch {
$UserCount = 0
$ApiError = $_.Exception.Message
+ $ApiException = $_
}
if ($UserCount -gt 0) {
@@ -368,6 +371,7 @@ Function Push-ExecOnboardTenantQueue {
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
+ Write-LogMessage -API 'Onboarding' -message "Tenant onboarding succeeded for $($Relationship.customer.displayName)" -Sev 'Info'
} else {
$Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'API Test failed: {0}' -f $ApiError })
$OnboardingSteps.Step5.Status = 'failed'
@@ -376,6 +380,7 @@ Function Push-ExecOnboardTenantQueue {
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
+ Write-LogMessage -API 'Onboarding' -message "Tenant onboarding API test failed for $($Relationship.customer.displayName)" -Sev 'Error' -LogData (Get-CippException -Exception $ApiException)
}
}
} catch {
@@ -385,5 +390,6 @@ Function Push-ExecOnboardTenantQueue {
$TenantOnboarding.OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
$TenantOnboarding.Logs = [string](ConvertTo-Json -InputObject @($Logs) -Compress)
Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
+ Write-LogMessage -API 'Onboarding' -message "Tenant onboarding failed for $Id" -Sev 'Error' -LogData (Get-CippException -Exception $_)
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
index 4d321a825f4e..fa4872195b0e 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
@@ -6,12 +6,14 @@ function Push-PublicWebhookProcess {
Invoke-CippGraphWebhookProcessing -Data ($Item.Data | ConvertFrom-Json) -CIPPID $Item.CIPPID -WebhookInfo ($Item.Webhookinfo | ConvertFrom-Json)
} elseif ($Item.Type -eq 'AuditLog') {
Invoke-CippWebhookProcessing -TenantFilter $Item.TenantFilter -Data ($Item.Data | ConvertFrom-Json) -CIPPPURL $Item.CIPPURL
+ } elseif ($Item.Type -eq 'PartnerCenter') {
+ Invoke-CippPartnerWebhookProcessing -Data ($Item.Data | ConvertFrom-Json)
}
} catch {
Write-Host "Webhook Exception: $($_.Exception.Message)"
} finally {
$WebhookIncoming = Get-CIPPTable -TableName WebhookIncoming
$Entity = $Item | Select-Object -Property RowKey, PartitionKey
- Remove-AzDataTableEntity @WebhookIncoming -Entity $Entity
+ Remove-AzDataTableEntity @WebhookIncoming -Entity $Entity
}
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1
new file mode 100644
index 000000000000..d529d55b1f0f
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1
@@ -0,0 +1,46 @@
+function Invoke-ExecPartnerWebhook {
+ Param($Request, $TriggerMetadata)
+
+ switch ($Request.Query.Action) {
+ 'ListEventTypes' {
+ $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration/events'
+ $Results = New-GraphGetRequest -uri $Uri -tenantid $env:TenantID -NoAuthCheck $true -scope 'https://api.partnercenter.microsoft.com/.default'
+ }
+ 'ListSubscription' {
+ $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration'
+ $Results = New-GraphGetRequest -uri $Uri -tenantid $env:TenantID -NoAuthCheck $true -scope 'https://api.partnercenter.microsoft.com/.default'
+ }
+ 'CreateSubscription' {
+ $BaseURL = ([System.Uri]$request.headers.'x-ms-original-url').Host
+ $Webhook = @{
+ TenantFilter = $env:TenantId
+ PartnerCenter = $true
+ BaseURL = $BaseURL
+ EventType = $Request.body.EventType
+ ExecutingUser = $Request.headers.'x-ms-client-principal'
+ }
+ $Results = New-CIPPGraphSubscription @Webhook
+ }
+ 'SendTest' {
+ $Results = New-GraphPOSTRequest -uri 'https://api.partnercenter.microsoft.com/webhooks/v1/registration/validationEvents' -tenantid $env:TenantID -NoAuthCheck $true -scope 'https://api.partnercenter.microsoft.com/.default'
+ }
+ 'ValidateTest' {
+ $Results = New-GraphGetRequest -uri "https://api.partnercenter.microsoft.com/webhooks/v1/registration/validationEvents/$($Request.Query.CorrelationId)" -tenantid $env:TenantID -NoAuthCheck $true -scope 'https://api.partnercenter.microsoft.com/.default'
+ }
+ default {
+ $Results = 'Invalid Action'
+ }
+ }
+
+ $Body = [PSCustomObject]@{
+ Results = $Results
+ Metadata = [PSCustomObject]@{
+ Action = $Request.Query.Action
+ }
+ }
+
+ Push-OutputBinding -Name Response -Value @{
+ StatusCode = [System.Net.HttpStatusCode]::OK
+ Body = $Body
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ExecScheduledCommand.ps1
deleted file mode 100644
index ce73476b5c97..000000000000
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ExecScheduledCommand.ps1
+++ /dev/null
@@ -1,93 +0,0 @@
- using namespace System.Net
-
- Function Invoke-ExecScheduledCommand {
- <#
- .FUNCTIONALITY
- Entrypoint
- #>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
-
- $commandParameters = $QueueItem.Parameters
-
-$tenant = $QueueItem.Parameters['TenantFilter']
-Write-Host 'started task'
-try {
- try {
- $results = & $QueueItem.command @commandParameters
- }
- catch {
- $results = "Task Failed: $($_.Exception.Message)"
-
- }
-
- Write-Host 'ran the command'
- if ($results -is [String]) {
- $results = @{ Results = $results }
- }
- if ($results -is [array]) {
- $results = $results | Where-Object { $_ -is [string] }
- $results = $results | ForEach-Object { @{ Results = $_ } }
- }
-
- $results = $results | Select-Object * -ExcludeProperty RowKey, PartitionKey
-
- $StoredResults = $results | ConvertTo-Json -Compress -Depth 20 | Out-String
- if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') {
- $StoredResults = @{ Results = 'The results for this query are too long to store in this table, or the query was meant for All Tenants. Please use the options to send the results to another target to be able to view the results. ' } | ConvertTo-Json -Compress
- }
-}
-catch {
- $errorMessage = $_.Exception.Message
- if ($task.Recurrence -gt 0) { $State = 'Failed - Planned' } else { $State = 'Failed' }
- Update-AzDataTableEntity @Table -Entity @{
- PartitionKey = $task.PartitionKey
- RowKey = $task.RowKey
- Results = "$errorMessage"
- TaskState = $State
- }
- Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): $errorMessage" -sev Error
-}
-
-
-$TableDesign = ''
-$HTML = ($results | Select-Object * -ExcludeProperty RowKey, PartitionKey | ConvertTo-Html -Fragment) -replace '
', "$TableDesign" | Out-String
-$title = "Scheduled Task $($task.Name) - $($task.ExpectedRunTime)"
-Write-Host $title
-switch -wildcard ($task.PostExecution) {
- '*psa*' { Send-CIPPAlert -Type 'psa' -Title $title -HTMLContent $HTML }
- '*email*' { Send-CIPPAlert -Type 'email' -Title $title -HTMLContent $HTML }
- '*webhook*' {
- $Webhook = [PSCustomObject]@{
- 'Tenant' = $tenant
- 'TaskInfo' = $QueueItem.TaskInfo
- 'Results' = $Results
- }
- Send-CIPPAlert -Type 'webhook' -Title $title -JSONContent $($Webhook | ConvertTo-Json -Depth 20)
- }
-}
-
-Write-Host 'ran the command'
-
-if ($task.Recurrence -le '0' -or $task.Recurrence -eq $null) {
- Update-AzDataTableEntity @Table -Entity @{
- PartitionKey = $task.PartitionKey
- RowKey = $task.RowKey
- Results = "$StoredResults"
- TaskState = 'Completed'
- }
-}
-else {
- $nextRun = (Get-Date).AddDays($task.Recurrence)
- $nextRunUnixTime = [int64]($nextRun - (Get-Date '1/1/1970')).TotalSeconds
- Update-AzDataTableEntity @Table -Entity @{
- PartitionKey = $task.PartitionKey
- RowKey = $task.RowKey
- Results = "$StoredResults"
- TaskState = 'Planned'
- ScheduledTime = "$nextRunUnixTime"
- }
-}
-Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Successfully executed task: $($task.name)" -sev Info
-
- }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1
index 067da939c2ca..41768a704af5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1
@@ -88,7 +88,7 @@ Function Invoke-ExecDnsConfig {
}
'GetConfig' {
$body = [pscustomobject]$Config
- Write-LogMessage -API $APINAME -tenant 'Global' -user $request.headers.'x-ms-client-principal' -message 'Retrieved DNS configuration' -Sev 'Info'
+ Write-LogMessage -API $APINAME -tenant 'Global' -user $request.headers.'x-ms-client-principal' -message 'Retrieved DNS configuration' -Sev 'Debug'
}
'RemoveDomain' {
$Filter = "RowKey eq '{0}'" -f $Request.Query.Domain
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1
index ca63f9f20afa..ca3e85feed9a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1
@@ -17,13 +17,13 @@ Function Invoke-ExecExcludeTenant {
$TenantsTable = Get-CippTable -tablename Tenants
if ($Request.Query.List) {
- $ExcludedFilter = "PartitionKey eq 'Tenants' and Excluded eq true"
- $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter $ExcludedFilter
- Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message 'got excluded tenants list' -Sev 'Info'
+ $ExcludedFilter = "PartitionKey eq 'Tenants' and Excluded eq true"
+ $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter $ExcludedFilter
+ Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message 'got excluded tenants list' -Sev 'Debug'
$body = @($ExcludedTenants)
} elseif ($Request.query.ListAll) {
- $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -filter "PartitionKey eq 'Tenants'"
- Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message 'got excluded tenants list' -Sev 'Info'
+ $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -filter "PartitionKey eq 'Tenants'"
+ Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message 'got excluded tenants list' -Sev 'Debug'
$body = @($ExcludedTenants)
}
try {
@@ -31,7 +31,7 @@ Function Invoke-ExecExcludeTenant {
$name = $Request.Query.TenantFilter
if ($Request.Query.AddExclusion) {
$Tenants = Get-Tenants -IncludeAll | Where-Object { $Request.body.value -contains $_.customerId }
-
+
$Excluded = foreach ($Tenant in $Tenants) {
$Tenant.Excluded = $true
$Tenant.ExcludeUser = $username
@@ -41,17 +41,17 @@ Function Invoke-ExecExcludeTenant {
Write-Host ($Excluded | ConvertTo-Json)
Update-AzDataTableEntity @TenantsTable -Entity ([pscustomobject]$Excluded)
#Remove-CIPPCache
- Write-LogMessage -API $APINAME -tenant $($name) -user $request.headers.'x-ms-client-principal' -message "Added exclusion for customer(s): $($Excluded.defaultDomainName -join ',')" -Sev 'Info'
+ Write-LogMessage -API $APINAME -tenant $($name) -user $request.headers.'x-ms-client-principal' -message "Added exclusion for customer(s): $($Excluded.defaultDomainName -join ',')" -Sev 'Info'
$body = [pscustomobject]@{'Results' = "Success. Added exclusions for customer(s): $($Excluded.defaultDomainName -join ',')" }
}
if ($Request.Query.RemoveExclusion) {
$Filter = "PartitionKey eq 'Tenants' and defaultDomainName eq '{0}'" -f $name
- $Tenant = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter
+ $Tenant = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter
$Tenant.Excluded = $false
$Tenant.ExcludeUser = ''
$Tenant.ExcludeDate = ''
- Update-AzDataTableEntity @TenantsTable -Entity $Tenant
+ Update-AzDataTableEntity @TenantsTable -Entity $Tenant
#Remove-CIPPCache
Write-LogMessage -API $APINAME -tenant $($name) -user $request.headers.'x-ms-client-principal' -message "Removed exclusion for customer $($name)" -Sev 'Info'
$body = [pscustomobject]@{'Results' = "Success. We've removed $name from the excluded tenants." }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSites.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSites.ps1
index 51f31ef28b70..48f3f8badb80 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSites.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSites.ps1
@@ -59,7 +59,7 @@ Function Invoke-ListSites {
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
- Body = @($GraphRequest)
+ Body = @($GraphRequest | Sort-Object -Property UPN)
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1
index 5c83df245e5f..c5969ad1d8ae 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1
@@ -18,7 +18,7 @@ Function Invoke-ListTeams {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
if ($request.query.type -eq 'List') {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups?`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&`$select=id,displayname,description,visibility,mailNickname" -tenantid $TenantFilter
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups?`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')&`$select=id,displayname,description,visibility,mailNickname" -tenantid $TenantFilter | Sort-Object -Property displayName
}
$TeamID = $request.query.ID
Write-Host $TeamID
@@ -37,7 +37,7 @@ Function Invoke-ListTeams {
Members = @($Members)
Owners = @($owners)
InstalledApps = @($AppsList)
- }
+ }
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1
index 730cbba9d457..9f843768ab9b 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1
@@ -54,6 +54,18 @@ function Invoke-PublicWebhooks {
## Push webhook data to queue
#Invoke-CippGraphWebhookProcessing -Data $ReceivedItem -CIPPID $request.Query.CIPPID -WebhookInfo $Webhookinfo
+ } elseif ($Request.Query.Type -eq 'PartnerCenter') {
+ [pscustomobject]$ReceivedItem = $Request.Body
+ $Entity = [PSCustomObject]@{
+ PartitionKey = 'Webhook'
+ RowKey = [string](New-Guid).Guid
+ Type = $Request.Query.Type
+ Data = [string]($ReceivedItem | ConvertTo-Json -Depth 10)
+ CIPPID = $Request.Query.CIPPID
+ WebhookInfo = [string]($WebhookInfo | ConvertTo-Json -Depth 10)
+ FunctionName = 'PublicWebhookProcess'
+ }
+ Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity
} else {
# Auditlog Subscriptions
try {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1
index ab6635459e4b..547828a337f4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1
@@ -16,11 +16,10 @@ Function Invoke-AddCAPolicy {
$results = foreach ($Tenant in $tenants) {
try {
- $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $Request.body.RawJSON -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal'
+ $CAPolicy = New-CIPPCAPolicy -replacePattern $Request.body.replacename -Overwrite $request.body.overwrite -TenantFilter $tenant -state $request.body.NewState -RawJSON $Request.body.RawJSON -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal'
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added Conditional Access Policy $($Displayname)" -Sev 'Info'
"Successfully added Conditional Access Policy for $($Tenant)"
- }
- catch {
+ } catch {
"Failed to add policy for $($Tenant): $($_.Exception.Message)"
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Failed to add Conditional Access Policy $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error'
continue
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1
index 7fc95e0d7af1..3f4b8d651650 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1
@@ -40,6 +40,32 @@ Function Invoke-AddCATemplate {
}
if ($excludelocations) { $JSON.conditions.locations.excludeLocations = $excludelocations }
+ if ($JSON.conditions.users.includeUsers) {
+ $JSON.conditions.users.includeUsers = @($JSON.conditions.users.includeUsers | ForEach-Object {
+ if ($_ -in 'All', 'None', 'GuestOrExternalUsers') { return $_ }
+ (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $TenantFilter).displayName
+ })
+ }
+
+ if ($JSON.conditions.users.excludeUsers) {
+ $JSON.conditions.users.excludeUsers = @($JSON.conditions.users.excludeUsers | ForEach-Object {
+ if ($_ -in 'All', 'None', 'GuestOrExternalUsers') { return $_ }
+ (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $TenantFilter).displayName
+ })
+ }
+
+ if ($JSON.conditions.users.includeGroups) {
+ $JSON.conditions.users.includeGroups = @($JSON.conditions.users.includeGroups | ForEach-Object {
+ if ($_ -in 'All', 'None', 'GuestOrExternalUsers') { return $_ }
+ (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($_)" -tenantid $TenantFilter).displayName
+ })
+ }
+ if ($JSON.conditions.users.excludeGroups) {
+ $JSON.conditions.users.excludeGroups = @($JSON.conditions.users.excludeGroups | ForEach-Object {
+ if ($_ -in 'All', 'None', 'GuestOrExternalUsers') { return $_ }
+ (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($_)" -tenantid $TenantFilter).displayName
+ })
+ }
$JSON | Add-Member -NotePropertyName 'LocationInfo' -NotePropertyValue @($IncludeJSON, $ExcludeJSON)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1
new file mode 100644
index 000000000000..137c55a9c28b
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1
@@ -0,0 +1,58 @@
+using namespace System.Net
+
+Function Invoke-ExecCaCheck {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+
+ $Tenant = $request.body.tenantFilter
+ $UserID = $request.body.userId.value
+ if ($Request.body.IncludeApplications.value) {
+ $IncludeApplications = $Request.body.IncludeApplications.value
+ } else {
+ $IncludeApplications = '67ad5377-2d78-4ac2-a867-6300cda00e85'
+ }
+ $results = try {
+ $CAContext = @{
+ '@odata.type' = '#microsoft.graph.whatIfApplicationContext'
+ 'includeApplications' = @($IncludeApplications)
+ }
+ $ConditionalAccessWhatIfDefinition = @{
+ 'conditionalAccessWhatIfSubject' = @{
+ '@odata.type' = '#microsoft.graph.userSubject'
+ 'userId' = "$userId"
+ }
+ 'conditionalAccessContext' = $CAContext
+ 'conditionalAccessWhatIfConditions' = @{}
+ }
+ $whatIfConditions = $ConditionalAccessWhatIfDefinition.conditionalAccessWhatIfConditions
+ if ($Request.body.UserRiskLevel) { $whatIfConditions.userRiskLevel = $Request.body.UserRiskLevel.value }
+ if ($Request.body.SignInRiskLevel) { $whatIfConditions.signInRiskLevel = $Request.body.SignInRiskLevel.value }
+ if ($Request.body.ClientAppType) { $whatIfConditions.clientAppType = $Request.body.ClientAppType.value }
+ if ($Request.body.DevicePlatform) { $whatIfConditions.devicePlatform = $Request.body.DevicePlatform.value }
+ if ($Request.body.Country) { $whatIfConditions.country = $Request.body.Country.value }
+ if ($Request.body.IpAddress) { $whatIfConditions.ipAddress = $Request.body.IpAddress.value }
+
+ $JSONBody = $ConditionalAccessWhatIfDefinition | ConvertTo-Json -Depth 10
+ Write-Host $JSONBody
+ $Request = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/evaluate' -tenantid $tenant -type POST -body $JsonBody -AsApp $true
+ $Request
+ } catch {
+ "Failed to execute check: $($_.Exception.Message)"
+ }
+
+ $body = [pscustomobject]@{'Results' = $results }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $body
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1
index d6a5965f2055..4739df9c2df1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1
@@ -64,6 +64,8 @@ Function Invoke-ExecGDAPInvite {
} else {
$Message = 'Error creating GDAP relationship request'
}
+
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created GDAP Invite - $InviteUrl" -Sev 'Info'
}
} catch {
$Message = 'Error creating GDAP relationship'
@@ -71,8 +73,6 @@ Function Invoke-ExecGDAPInvite {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $env:TenantID -message "$($Message): $($_.Exception.Message)" -Sev 'Error'
}
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created GDAP Invite - $InviteUrl" -Sev 'Info'
-
$body = @{
Message = $Message
Invite = $InviteEntity
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1
index 567452b932c7..a97bb06cf6de 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1
@@ -15,7 +15,7 @@ Function Invoke-AddStandardsDeploy {
$username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails
try {
- $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value
+ $Tenants = $Request.body.Tenant
$Settings = ($request.body | Select-Object -Property *, v2* -ExcludeProperty Select_*, None )
$Settings | Add-Member -NotePropertyName 'v2.1' -NotePropertyValue $true -Force
if ($Settings.phishProtection.remediate) {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1
new file mode 100644
index 000000000000..27c8774bae3c
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1
@@ -0,0 +1,32 @@
+using namespace System.Net
+
+Function Invoke-AddStandardsTemplate {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $GUID = (New-Guid).GUID
+ $JSON = (ConvertTo-Json -Depth 100 -InputObject ($Request.body | Select-Object standards, name))
+ $Table = Get-CippTable -tablename 'templates'
+ $Table.Force = $true
+ Add-CIPPAzDataTableEntity @Table -Entity @{
+ JSON = "$JSON"
+ RowKey = "$GUID"
+ PartitionKey = 'StandardsTemplate'
+ GUID = "$GUID"
+ }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created CA Template $($Request.body.name) with GUID $GUID" -Sev 'Debug'
+ $body = [pscustomobject]@{'Results' = 'Successfully added template' }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $body
+ })
+
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1
index 7ff48e0ca1c9..0e632d4fba35 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1
@@ -77,7 +77,7 @@ Function Invoke-ListBPA {
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
- Body = ($Results | ConvertTo-Json -Depth 15)
+ Body = (ConvertTo-Json -Depth 15 -InputObject $Results)
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1
new file mode 100644
index 000000000000..acc984d6e0ab
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1
@@ -0,0 +1,27 @@
+using namespace System.Net
+
+Function Invoke-listStandardTemplates {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+
+ $Table = Get-CippTable -tablename 'templates'
+ $Filter = "PartitionKey eq 'StandardsTemplate'"
+ $Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
+ $data = $_.JSON | ConvertFrom-Json -Depth 100
+ $data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force
+ $data
+ } | Sort-Object -Property displayName
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = @($Templates)
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1
index 6587c2c41822..f04c365c5ccf 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1
@@ -33,7 +33,10 @@ Function Invoke-ExecGraphExplorerPreset {
}
$params = $Request.Body.preset | Select-Object endpoint, '$filter', '$select', '$count', '$expand', '$search', NoPagination, '$top', IsShared
- if ($params.'$select') { $params.'$select' = ($params.'$select').value -join ',' }
+
+ if ($params.'$select'.value) {
+ $params.'$select' = ($params.'$select').value -join ','
+ }
$Preset = [PSCustomObject]@{
PartitionKey = 'Preset'
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
index 838f23ee3cd6..eda323666fa1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
@@ -19,8 +19,29 @@ Function Invoke-ExecUniversalSearch {
try {
$tenantfilter = Get-Tenants
- $payload = '{ "returnsPartialResults":true, "displayName":"getUsers", "target": { "allTenants":true }, "operationDefinition": { "values":["@sys.normalize([ConsistencyLevel: eventual GET /v1.0/users?$top=5&$search=\"userPrincipalName:' + $request.query.name + '\" OR \"displayName:' + $request.query.name + '\"])"] }, "aggregationDefinition": { "values":["@sys.append([/result],50)"] } }'
- $GraphRequest = (New-GraphPOSTRequest -noauthcheck $true -type 'POST' -uri 'https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedTenantOperations' -tenantid $env:TenantID -body $payload).result.Results | ConvertFrom-Json | Where-Object { $_.'_TenantId' -in $tenantfilter.customerId }
+ $payload = [PSCustomObject]@{
+ returnsPartialResults = $false
+ displayName = 'getUsers'
+ target = [PSCustomObject]@{
+ allTenants = $true
+ }
+ operationDefinition = [PSCustomObject]@{
+ values = @(
+ "@sys.normalize([ConsistencyLevel: eventual GET /v1.0/users?`$top=5&`$search=`"userPrincipalName:$($Request.query.name)`" OR `"displayName:$($Request.query.name)`"])"
+ )
+ }
+ aggregationDefinition = [PSCustomObject]@{
+ values = @(
+ '@sys.append([/result],50)'
+ )
+ }
+ } | ConvertTo-Json -Depth 10
+ $GraphRequest = (New-GraphPOSTRequest -noauthcheck $true -type 'POST' -uri 'https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedTenantOperations' -tenantid $env:TenantID -body $payload -IgnoreErrors $true)
+ if (!$GraphRequest.result.results) {
+ $GraphRequest = ($GraphRequest.error.message | ConvertFrom-Json).result.results | ConvertFrom-Json | Where-Object { $_.'_TenantId' -in $tenantfilter.customerId }
+ } else {
+ $GraphRequest.result.Results | ConvertFrom-Json -ErrorAction SilentlyContinue | Where-Object { $_.'_TenantId' -in $tenantfilter.customerId }
+ }
$StatusCode = [HttpStatusCode]::OK
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
index 2cd1d9cd9bac..95866c41c395 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
@@ -133,8 +133,13 @@ function Invoke-ListGraphRequest {
else { $StatusCode = [HttpStatusCode]::BadRequest }
}
+ if ($request.Query.Sort) {
+ $GraphRequestData.Results = $GraphRequestData.Results | Sort-Object -Property $request.Query.Sort
+ }
+ $Outputdata = $GraphRequestData | ConvertTo-Json -Depth 20 -Compress
+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
- Body = $GraphRequestData | ConvertTo-Json -Depth 20 -Compress
+ Body = $Outputdata
})
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
index 319b43a00995..a3963bd0bc94 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
@@ -12,7 +12,7 @@ Function Invoke-ListLogs {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
if ($request.Query.Filter -eq 'True') {
- $LogLevel = if ($Request.query.Severity) { ($Request.query.Severity).split(',') } else { 'Info', 'Warn', 'Error', 'Critical', 'Alert' }
+ $LogLevel = if ($Request.query.Severity) { ($Request.query.Severity).split(',') } else { 'Info', 'Warn', 'Error', 'Critical', 'Alert' }
$PartitionKey = $Request.query.DateFilter
$username = $Request.Query.User
} else {
@@ -25,7 +25,7 @@ Function Invoke-ListLogs {
$ReturnedLog = if ($Request.Query.ListLogs) {
Get-CIPPAzDataTableEntity @Table -Property PartitionKey | Sort-Object -Unique PartitionKey | Select-Object PartitionKey | ForEach-Object {
- @{
+ @{
value = $_.PartitionKey
label = $_.PartitionKey
}
@@ -34,13 +34,17 @@ Function Invoke-ListLogs {
$Filter = "PartitionKey eq '{0}'" -f $PartitionKey
$Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Severity -In $LogLevel -and $_.user -like $username }
foreach ($Row in $Rows) {
- @{
+ $LogData = if ($Row.LogData -and (Test-Json -Json $Row.LogData)) {
+ $Row.LogData | ConvertFrom-Json
+ } else { $Row.LogData }
+ [PSCustomObject]@{
DateTime = $Row.Timestamp
Tenant = $Row.Tenant
API = $Row.API
Message = $Row.Message
User = $Row.Username
Severity = $Row.Severity
+ LogData = $LogData
TenantID = if ($Row.TenantID -ne $null) {
$Row.TenantID
} else {
diff --git a/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1 b/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1
index 0d3092fc54c3..9b1885d5c465 100644
--- a/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1
@@ -30,7 +30,7 @@ function Get-CIPPAuthentication {
return $true
} catch {
- Write-LogMessage -message "Could not retrieve keys from Keyvault: $($_.Exception.Message)" -Sev 'CRITICAL' -API 'CIPP Authentication'
+ Write-LogMessage -message 'Could not retrieve keys from Keyvault' -Sev 'CRITICAL' -API 'CIPP Authentication' -LogData (Get-CippException -Exception $_)
return $false
}
}
diff --git a/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1 b/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1
index 7d886ea2912f..a80a5d3b002e 100644
--- a/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1
@@ -4,18 +4,17 @@ function Get-CIPPBitlockerKey {
param (
$device,
$TenantFilter,
- $APIName = "Get Bitlocker key",
+ $APIName = 'Get Bitlocker key',
$ExecutingUser
)
try {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys?`$filter=deviceId eq '$($device)'" -tenantid $TenantFilter | ForEach-Object {
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys?`$filter=deviceId eq '$($device)'" -tenantid $TenantFilter | ForEach-Object {
(New-GraphGetRequest -uri "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys/$($_.id)?`$select=key" -tenantid $TenantFilter).key
}
return $GraphRequest
- }
- catch {
- Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not add OOO for $($userid)" -Sev "Error" -tenant $TenantFilter
+ } catch {
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not add OOO for $($userid)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
return "Could not add out of office message for $($userid). Error: $($_.Exception.Message)"
}
}
diff --git a/Modules/CIPPCore/Public/Get-CIPPDomainAnalyser.ps1 b/Modules/CIPPCore/Public/Get-CIPPDomainAnalyser.ps1
index e39e6d5953ba..fc4ad53915a1 100644
--- a/Modules/CIPPCore/Public/Get-CIPPDomainAnalyser.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPDomainAnalyser.ps1
@@ -6,7 +6,7 @@ function Get-CIPPDomainAnalyser {
# Get all the things
if ($TenantFilter -ne 'AllTenants') {
- $DomainTable.Filter = "TenantId eq '{0}'" -f $TenantFilter
+ $DomainTable.Filter = "TenantGUID eq '{0}'" -f $TenantFilter
}
try {
diff --git a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
index 73a2295b3be1..40eb80366161 100644
--- a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
@@ -3,7 +3,7 @@ function Get-CIPPMFAState {
[CmdletBinding()]
param (
$TenantFilter,
- $APIName = "Get MFA Status",
+ $APIName = 'Get MFA Status',
$ExecutingUser
)
@@ -23,8 +23,7 @@ function Get-CIPPMFAState {
Try {
$MFARegistration = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/reports/credentialUserRegistrationDetails' -tenantid $TenantFilter)
- }
- catch {
+ } catch {
$CAState.Add('Not Licensed for Conditional Access') | Out-Null
$MFARegistration = $null
}
@@ -51,8 +50,7 @@ function Get-CIPPMFAState {
}
}
}
- }
- catch {
+ } catch {
}
}
@@ -68,12 +66,10 @@ function Get-CIPPMFAState {
if ($CA -like '*All Users*') {
if ($ExcludeAllUsers -contains $_.ObjectId) { $UserCAState.Add("Excluded from $($policy.displayName) - All Users") | Out-Null }
else { $UserCAState.Add($CA) | Out-Null }
- }
- elseif ($CA -like '*Specific Applications*') {
+ } elseif ($CA -like '*Specific Applications*') {
if ($ExcludeSpecific -contains $_.ObjectId) { $UserCAState.Add("Excluded from $($policy.displayName) - Specific Applications") | Out-Null }
else { $UserCAState.Add($CA) | Out-Null }
- }
- else {
+ } else {
Write-Host 'Adding to CA'
$UserCAState.Add($CA) | Out-Null
}
@@ -81,7 +77,8 @@ function Get-CIPPMFAState {
$PerUser = if ($_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state -ne $null) { $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state } else { 'Disabled' }
- $MFARegUser = if (($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered -eq $null) { $false } else { ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered }
+ $MFARegUser = if (($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered -eq $null) { $false } else { ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName) }
+
[PSCustomObject]@{
Tenant = $TenantFilter
ID = $_.ObjectId
@@ -90,7 +87,8 @@ function Get-CIPPMFAState {
AccountEnabled = $_.accountEnabled
PerUser = $PerUser
isLicensed = $_.isLicensed
- MFARegistration = $MFARegUser
+ MFARegistration = $MFARegUser.IsMFARegistered
+ MFAMethods = $($MFARegUser.authMethods -join ', ')
CoveredByCA = ($UserCAState -join ', ')
CoveredBySD = $SecureDefaultsState
RowKey = [string]($_.UserPrincipalName).replace('#', '')
diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-CippException.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-CippException.ps1
new file mode 100644
index 000000000000..92c4d936dd22
--- /dev/null
+++ b/Modules/CIPPCore/Public/GraphHelper/Get-CippException.ps1
@@ -0,0 +1,14 @@
+function Get-CippException {
+ Param(
+ $Exception
+ )
+
+ [PSCustomObject]@{
+ Message = $Exception.Exception.Message
+ NormalizedError = Get-NormalizedError -message $Exception.Exception.Message
+ Position = $Exception.InvocationInfo.PositionMessage
+ ScriptName = $Exception.InvocationInfo.ScriptName
+ LineNumber = $Exception.InvocationInfo.ScriptLineNumber
+ Category = $Exception.CategoryInfo.ToString()
+ }
+}
diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
index bcb9b94ef9cc..2cb51e4d929a 100644
--- a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
@@ -32,11 +32,11 @@ function Get-Tenants {
if (($IncludedTenantsCache | Measure-Object).Count -eq 0) {
$BuildRequired = $true
- }
+ }
if ($BuildRequired -or $TriggerRefresh.IsPresent) {
#get the full list of tenants
- $GDAPRelationships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active' and not startsWith(displayName,'MLT_')&`$select=customer,autoExtendDuration,endDateTime" -NoAuthCheck:$true
+ $GDAPRelationships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active' and not startsWith(displayName,'MLT_')&`$select=customer,autoExtendDuration,endDateTime" -NoAuthCheck:$true
$GDAPList = foreach ($Relationship in $GDAPRelationships) {
[PSCustomObject]@{
customerId = $Relationship.customer.tenantId
@@ -72,13 +72,13 @@ function Get-Tenants {
$defaultDomainName = $Domain
$initialDomainName = $Domain
$RequiresRefresh = $true
-
+
} catch {
Write-LogMessage -API 'Get-Tenants' -message "Tried adding $($LatestRelationship.customerId) to tenant list but failed to get domains - $($_.Exception.Message)" -level 'Critical'
}
}
-
+
[PSCustomObject]@{
PartitionKey = 'Tenants'
RowKey = $_.Name
@@ -129,7 +129,7 @@ function Get-Tenants {
Add-CIPPAzDataTableEntity @TenantsTable -Entity $IncludedTenantsCache -Force
$CurrentTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter "PartitionKey eq 'Tenants' and Excluded eq false"
$CurrentTenants | Where-Object { $_.customerId -notin $IncludedTenantsCache.customerId } | ForEach-Object {
- Remove-AzDataTableEntity -Context $TenantsTable -Entity $_ -Force
+ Remove-AzDataTableEntity @TenantsTable -Entity $_
}
}
return ($IncludedTenantsCache | Where-Object { $null -ne $_.defaultDomainName -and ($_.defaultDomainName -notmatch 'Domain Error' -or $IncludeAll.IsPresent) } | Sort-Object -Property displayName)
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1
index 9236b7559fcf..315881e1048b 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1
@@ -1,5 +1,5 @@
-function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $NoAuthCheck, $skipTokenCache, $AddedHeaders, $contentType) {
+function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $NoAuthCheck, $skipTokenCache, $AddedHeaders, $contentType, $IgnoreErrors) {
<#
.FUNCTIONALITY
Internal
@@ -20,7 +20,7 @@ function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $N
$contentType = 'application/json; charset=utf-8'
}
try {
- $ReturnedData = (Invoke-RestMethod -Uri $($uri) -Method $TYPE -Body $body -Headers $headers -ContentType $contentType)
+ $ReturnedData = (Invoke-RestMethod -Uri $($uri) -Method $TYPE -Body $body -Headers $headers -ContentType $contentType -SkipHttpErrorCheck:$IgnoreErrors)
} catch {
$Message = if ($_.ErrorDetails.Message) {
Get-NormalizedError -Message $_.ErrorDetails.Message
diff --git a/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1 b/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1
index fbef7fae41bf..8dec84538272 100644
--- a/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/Write-LogMessage.ps1
@@ -1,14 +1,25 @@
-function Write-LogMessage ($message, $tenant = 'None', $API = 'None', $tenantId = $null, $user, $sev) {
+function Write-LogMessage {
<#
.FUNCTIONALITY
Internal
#>
+ Param(
+ $message,
+ $tenant = 'None',
+ $API = 'None',
+ $tenantId = $null,
+ $user,
+ $sev,
+ $LogData = ''
+ )
try {
$username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails
} catch {
$username = $user
}
+ if ($LogData) { $LogData = ConvertTo-Json -InputObject $LogData -Depth 10 -Compress }
+
$Table = Get-CIPPTable -tablename CippLogs
if (!$tenant) { $tenant = 'None' }
@@ -27,13 +38,14 @@ function Write-LogMessage ($message, $tenant = 'None', $API = 'None', $tenantId
'SentAsAlert' = $false
'PartitionKey' = $PartitionKey
'RowKey' = ([guid]::NewGuid()).ToString()
+ 'LogData' = [string]$LogData
}
if ($tenantId) {
$TableRow.Add('TenantID', [string]$tenantId)
}
-
+
$Table.Entity = $TableRow
Add-CIPPAzDataTableEntity @Table | Out-Null
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Invoke-CIPPPartnerWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPPartnerWebhookProcessing.ps1
new file mode 100644
index 000000000000..5a16c69d530d
--- /dev/null
+++ b/Modules/CIPPCore/Public/Invoke-CIPPPartnerWebhookProcessing.ps1
@@ -0,0 +1,75 @@
+function Invoke-CippPartnerWebhookProcessing {
+ [CmdletBinding()]
+ param (
+ $Data
+ )
+
+ try {
+ if ($Data.AuditUri) {
+ $AuditLog = New-GraphGetRequest -uri $Data.AuditUri -tenantid $env:TenantID -NoAuthCheck $true -scope 'https://api.partnercenter.microsoft.com/.default'
+ }
+
+ Switch ($Data.EventName) {
+ 'test-created' {
+ Write-LogMessage -API 'Webhooks' -message 'Partner Center webhook test received' -Sev 'Info'
+ }
+ default {
+ if ($Data.EventName -eq 'granular-admin-relationship-approved') {
+ if ($AuditLog.resourceNewValue) {
+ $AuditObj = $AuditLog.resourceNewValue | ConvertFrom-Json
+ Write-LogMessage -API 'Webhooks' -message "Partner Webhook: GDAP Relationship for $($AuditObj.customer.organizationDisplayName) was approved, starting onboarding" -LogData $AuditObj -Sev 'Alert'
+ $Id = $AuditObj.Id
+ $OnboardingSteps = [PSCustomObject]@{
+ 'Step1' = @{
+ 'Status' = 'pending'
+ 'Title' = 'Step 1: GDAP Invite'
+ 'Message' = 'Waiting for onboarding job to start'
+ }
+ 'Step2' = @{
+ 'Status' = 'pending'
+ 'Title' = 'Step 2: GDAP Role Test'
+ 'Message' = 'Waiting for Step 1'
+ }
+ 'Step3' = @{
+ 'Status' = 'pending'
+ 'Title' = 'Step 3: GDAP Group Mapping'
+ 'Message' = 'Waiting for Step 2'
+ }
+ 'Step4' = @{
+ 'Status' = 'pending'
+ 'Title' = 'Step 4: CPV Refresh'
+ 'Message' = 'Waiting for Step 3'
+ }
+ 'Step5' = @{
+ 'Status' = 'pending'
+ 'Title' = 'Step 5: Graph API Test'
+ 'Message' = 'Waiting for Step 4'
+ }
+ }
+ $TenantOnboarding = [PSCustomObject]@{
+ PartitionKey = 'Onboarding'
+ RowKey = [string]$Id
+ CustomerId = ''
+ Status = 'queued'
+ OnboardingSteps = [string](ConvertTo-Json -InputObject $OnboardingSteps -Compress)
+ Relationship = ''
+ Logs = ''
+ Exception = ''
+ }
+ $OnboardTable = Get-CIPPTable -TableName 'TenantOnboarding'
+ Add-CIPPAzDataTableEntity @OnboardTable -Entity $TenantOnboarding -Force -ErrorAction Stop
+ Push-ExecOnboardTenantQueue -Item @{ Id = $Id }
+ } else {
+ if ($AuditLog) {
+ Write-LogMessage -API 'Webhooks' -message "Partner Center $($Data.EventName) audit log webhook received" -LogData $AuditObj -Sev 'Alert'
+ } else {
+ Write-LogMessage -API 'Webhooks' -message "Partner Center $($Data.EventName) webhook received" -LogData $Data -Sev 'Alert'
+ }
+ }
+ }
+ }
+ }
+ } catch {
+ Write-LogMessage -API 'Webhooks' -message 'Error processing Partner Center webhook' -LogData (Get-CippException -Exception $_) -Sev 'Error'
+ }
+}
diff --git a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
index db62dae8b160..86e7e8a41c3f 100644
--- a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
+++ b/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
@@ -82,7 +82,7 @@ function Invoke-CippWebhookProcessing {
{ 'UserLoggedIn' -eq $data.operation -and $hosting -eq $true -and !$TrustedIps } { $data.operation = 'HostedIP' }
{ 'UserLoggedIn' -eq $data.operation -and $Country -notin $AllowedLocations -and $data.ResultStatus -eq 'Success' -and $TableObj.ResultStatusDetail -eq 'Success' } {
Write-Host "$($country) is not in $($AllowedLocations)"
- $data.operation = 'UserLoggedInFromUnknownLocation'
+ $data.operation = 'UserLoggedInFromUnknownLocation'
}
{ 'UserloggedIn' -eq $data.operation -and $data.UserType -eq 2 -and $data.ResultStatus -eq 'Success' -and $TableObj.ResultStatusDetail -eq 'Success' } { $data.operation = 'AdminLoggedIn' }
default { break }
@@ -130,7 +130,7 @@ function Invoke-CippWebhookProcessing {
$key = $parts[0]
$operator = $parts[1]
$value = $parts[2]
- if (!$value) {
+ if (!$value) {
Write-Host 'blank value, skip'
continue
}
@@ -165,9 +165,9 @@ function Invoke-CippWebhookProcessing {
$RuleDisabled = 0
New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'get-inboxrule' -cmdParams @{Mailbox = $username } | ForEach-Object {
$null = New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'Disable-InboxRule' -cmdParams @{Confirm = $false; Identity = $_.Identity }
- "Disabled Inbox Rule $($_.Identity) for $username"
+ "Disabled Inbox Rule $($_.Identity) for $username"
$RuleDisabled ++
- }
+ }
if ($RuleDisabled) {
"Disabled $RuleDisabled Inbox Rules for $username"
} else {
@@ -211,7 +211,7 @@ function Invoke-CippWebhookProcessing {
}
}
Write-Host 'Going to create the content'
- foreach ($action in $dos) {
+ foreach ($action in $dos) {
switch ($action.execute) {
'generatemail' {
Write-Host 'Going to create the email'
@@ -220,9 +220,9 @@ function Invoke-CippWebhookProcessing {
Send-CIPPAlert -Type 'email' -Title $GenerateEmail.title -HTMLContent $GenerateEmail.htmlcontent -TenantFilter $TenantFilter
Write-Host 'email should be sent'
- }
+ }
'generatePSA' {
- $GenerateEmail = New-CIPPAlertTemplate -format 'html'-data $Data -LocationInfo $Location -ActionResults $ActionResults
+ $GenerateEmail = New-CIPPAlertTemplate -format 'html' -data $Data -LocationInfo $Location -ActionResults $ActionResults
Send-CIPPAlert -Type 'psa' -Title $GenerateEmail.title -HTMLContent $GenerateEmail.htmlcontent -TenantFilter $TenantFilter
}
'generateWebhook' {
diff --git a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1
index 1d749a69bf76..78f3173c2aee 100644
--- a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1
@@ -6,6 +6,7 @@ function New-CIPPCAPolicy {
$TenantFilter,
$State,
$Overwrite,
+ $ReplacePattern = 'none',
$APIName = 'Create CA Policy',
$ExecutingUser
)
@@ -101,19 +102,42 @@ function New-CIPPCAPolicy {
$index = [array]::IndexOf($JSONObj.conditions.locations.excludeLocations, $location)
$JSONObj.conditions.locations.excludeLocations[$index] = $lookup.id
}
-
+ switch ($ReplacePattern) {
+ 'none' {
+ Write-Host 'Replacement pattern for inclusions and exclusions is none'
+ break
+ }
+ 'AllUsers' {
+ Write-Host 'Replacement pattern for inclusions and exclusions is All users. This policy will now apply to everyone.'
+ if ($JSONObj.conditions.users.includeUsers -ne 'All') { $JSONObj.conditions.users.includeUsers = @('All') }
+ if ($JSONObj.conditions.users.excludeUsers) { $JSONObj.conditions.users.excludeUsers = @() }
+ if ($JSONObj.conditions.users.includeGroups) { $JSONObj.conditions.users.includeGroups = @() }
+ if ($JSONObj.conditions.users.excludeGroups) { $JSONObj.conditions.users.excludeGroups = @() }
+ }
+ 'displayName' {
+ Write-Host 'Replacement pattern for inclusions and exclusions is displayName.'
+ $users = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/users?$select=id,displayName' -tenantid $TenantFilter
+ $Groups = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName' -tenantid $TenantFilter
+
+ if ($JSONObj.conditions.users.includeUsers -notin 'All', 'None', 'GuestOrExternalUsers') { $JSONObj.conditions.users.includeUsers = @(($users | Where-Object -Property displayName -In $JSONObj.conditions.users.includeUsers).id) }
+ if ($JSONObj.conditions.users.excludeUsers) { $JSONObj.conditions.users.excludeUsers = @(($users | Where-Object -Property displayName -In $JSONObj.conditions.users.excludeUsers).id) }
+ if ($JSONObj.conditions.users.includeGroups) { $JSONObj.conditions.users.includeGroups = @(($groups | Where-Object -Property displayName -In $JSONObj.conditions.users.includeGroups).id) }
+ if ($JSONObj.conditions.users.excludeGroups) { $JSONObj.conditions.users.excludeGroups = @(($groups | Where-Object -Property displayName -In $JSONObj.conditions.users.excludeGroups).id) }
+ }
+
+ }
$JsonObj.PSObject.Properties.Remove('LocationInfo')
$RawJSON = $JSONObj | ConvertTo-Json -Depth 10
Write-Host $RawJSON
try {
Write-Host 'Checking'
- $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $TenantFilter
- if ($displayname -in $CheckExististing.displayName) {
+ $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $TenantFilter | Where-Object -Property displayName -EQ $displayname
+ if ($CheckExististing) {
if ($Overwrite -ne $true) {
Throw "Conditional Access Policy with Display Name $($Displayname) Already exists"
return $false
} else {
- Write-Host 'overwriting'
+ Write-Host "overwriting $($CheckExististing.id)"
$PatchRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($CheckExististing.id)" -tenantid $tenantfilter -type PATCH -body $RawJSON
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated Conditional Access Policy $($JSONObj.Displayname) to the template standard." -Sev 'Info'
return "Updated policy $displayname for $tenantfilter"
diff --git a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
index 6eac507448ec..e744232e9e60 100644
--- a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
@@ -11,7 +11,8 @@ function New-CIPPGraphSubscription {
$EventType,
$APIName = 'Create Webhook',
$ExecutingUser,
- [Switch]$Recreate
+ [Switch]$Recreate,
+ [switch]$PartnerCenter
)
$CIPPID = (New-Guid).GUID
$WebhookTable = Get-CIPPTable -TableName webhookTable
@@ -76,13 +77,73 @@ function New-CIPPGraphSubscription {
}
}
}
+ } elseif ($PartnerCenter.IsPresent) {
+ $WebhookFilter = "PartitionKey eq '$($env:TenantId)'"
+ $ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
+ $CIPPID = $env:TenantId
+ $MatchedWebhook = $ExistingWebhooks | Where-Object { $_.Resource -eq 'PartnerCenter' -and $_.RowKey -eq $CIPPID }
+
+ # Required event types
+ $EventList = [System.Collections.Generic.List[string]]@('test-created', 'granular-admin-relationship-approved')
+ if (($EventType | Measure-Object).count -gt 0) {
+ foreach ($Event in $EventType) {
+ if ($EventList -notcontains $Event) {
+ $EventList.Add($Event)
+ }
+ }
+ }
+
+ $Body = [PSCustomObject]@{
+ WebhookUrl = "https://$BaseURL/API/PublicWebhooks?CIPPID=$($CIPPID)&Type=PartnerCenter"
+ WebhookEvents = @($EventList)
+ }
+ $EventCompare = Compare-Object $EventList ($MatchedWebhook.EventType | ConvertFrom-Json)
+ try {
+ $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration'
+ try {
+ $Existing = New-GraphGetRequest -NoAuthCheck $true -uri $Uri -tenantid $env:TenantId -scope 'https://api.partnercenter.microsoft.com/.default'
+ } catch {}
+ if ($Existing.webhookUrl -ne $MatchedWebhook.WebhookNotificationUrl -or $EventCompare) {
+ if ($Existing.WebhookUrl) {
+ $Action = 'Updated'
+ $Method = 'PUT'
+ Write-Host 'updating webhook'
+ } else {
+ $Action = 'Created'
+ $Method = 'POST'
+ Write-Host 'creating webhook'
+ }
+
+ $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration'
+ $GraphRequest = New-GraphPOSTRequest -uri $Uri -type $Method -tenantid $env:TenantId -scope 'https://api.partnercenter.microsoft.com/.default' -body ($Body | ConvertTo-Json) -NoAuthCheck $true
+
+ $WebhookRow = @{
+ PartitionKey = [string]$CIPPID
+ RowKey = [string]$CIPPID
+ EventType = [string](ConvertTo-Json -InputObject $EventList)
+ Resource = [string]'PartnerCenter'
+ SubscriptionID = [string]$GraphRequest.SubscriberId
+ Expiration = 'Does Not Expire'
+ WebhookNotificationUrl = [string]$Body.WebhookUrl
+ }
+ $null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow -Force
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "$Action Partner Center Webhook subscription" -Sev 'Info' -tenant 'PartnerTenant'
+ return "$Action Partner Center Webhook subscription"
+ } else {
+ Write-LogMessage -user $ExecutingUser -API $APIName -message 'Existing Partner Center Webhook subscription found' -Sev 'Info' -tenant 'PartnerTenant'
+ return 'Existing Partner Center Webhook subscription found'
+ }
+ } catch {
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Partner Center Webhook Subscription: $($_.Exception.Message)" -Sev 'Error' -tenant 'PartnerTenant'
+ return "Failed to create Partner Webhook Subscription: $($_.Exception.Message)"
+ }
+
} else {
# First check if there is an exsiting Webhook in place
$WebhookFilter = "PartitionKey eq '$($TenantFilter)'"
$ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
$MatchedWebhook = $ExistingWebhooks | Where-Object { $_.Resource -eq $Resource }
- if (($MatchedWebhook | Measure-Object).count -eq 0 -or $Recreate) {
-
+ if (($MatchedWebhook | Measure-Object).count -eq 0 -or $Recreate.IsPresent) {
$expiredate = (Get-Date).AddDays(1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
$params = @{
changeType = $TypeofSubscription
@@ -90,10 +151,10 @@ function New-CIPPGraphSubscription {
resource = $Resource
expirationDateTime = $expiredate
} | ConvertTo-Json
-
+
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/subscriptions' -tenantid $TenantFilter -type POST -body $params -verbose
- #If creation is succesfull, we store the GUID in the storage table webhookTable to make sure we can check against this later on.
+ #If creation is succesfull, we store the GUID in the storage table webhookTable to make sure we can check against this later on.
#We store the GUID as rowkey, the event type, the resource, and the expiration date as properties, we also add the Tenant name so we can easily find this later on.
#We don't store the return, because Ms decided that a renewal or re-authenticate does not change the url, but does change the id...
$WebhookRow = @{
@@ -108,7 +169,7 @@ function New-CIPPGraphSubscription {
}
$null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow
#todo: add remove webhook function, add check webhook function, add list webhooks function
- #add refresh webhook function based on table.
+ #add refresh webhook function based on table.
Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Graph Webhook subscription for $($TenantFilter)" -Sev 'Info' -tenant $TenantFilter
} else {
Write-LogMessage -user $ExecutingUser -API $APIName -message "Existing Graph Webhook subscription for $($TenantFilter) found" -Sev 'Info' -tenant $TenantFilter
@@ -117,8 +178,6 @@ function New-CIPPGraphSubscription {
return "Created Webhook subscription for $($TenantFilter)"
} catch {
Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription: $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter
- Return "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)"
+ Return "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)"
}
-
}
-
diff --git a/Modules/CIPPCore/Public/Set-CIPPSignature.ps1 b/Modules/CIPPCore/Public/Set-CIPPSignature.ps1
new file mode 100644
index 000000000000..fa2de7dc415b
--- /dev/null
+++ b/Modules/CIPPCore/Public/Set-CIPPSignature.ps1
@@ -0,0 +1,27 @@
+function Set-CIPPOutOfOffice {
+ [CmdletBinding()]
+ param (
+ $userid,
+ $InternalMessage,
+ $ExternalMessage,
+ $TenantFilter,
+ $State,
+ $APIName = 'Set Outlook Roaming Signature',
+ $ExecutingUser,
+ $StartTime,
+ $EndTime
+ )
+
+ try {
+ $SignatureProfile = @'
+[{"name":"Roaming_New_Signature","itemClass":"","id":"","scope":"AdeleV@M365x42953883.OnMicrosoft.com","parentSetting":"","secondaryKey":"","type":"String","timestamp":638296273181532792,"metadata":"","value":"Kelvin","isFirstSync":"true","source":"UserOverride"}]
+'@
+ $GraphRequest = New-GraphPostRequest -uri 'https://substrate.office.com/ows/beta/outlookcloudsettings/settings/global' -tenantid $TenantFilter -type PATCH -contentType 'application/json' -verbose -scope 'https://outlook.office.com/.default'
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Set Out-of-office for $($userid) to $state" -Sev 'Info' -tenant $TenantFilter
+ return "Set Out-of-office for $($userid) to $state."
+
+ } catch {
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not add OOO for $($userid)" -Sev 'Error' -tenant $TenantFilter
+ return "Could not add out of office message for $($userid). Error: $($_.Exception.Message)"
+ }
+}
diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1
index f82b937d9e57..ac2629135250 100644
--- a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1
+++ b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1
@@ -2,7 +2,7 @@ function Test-CIPPAccessPermissions {
[CmdletBinding()]
param (
$TenantFilter,
- $APIName = "Access Check",
+ $APIName = 'Access Check',
$ExecutingUser
)
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Started permissions check' -Sev 'Debug'
@@ -20,12 +20,12 @@ function Test-CIPPAccessPermissions {
TenantId = ''
UserPrincipalName = ''
}
- Write-Host "Setting success to true by default."
+ Write-Host 'Setting success to true by default.'
$Success = $true
try {
Set-Location (Get-Item $PSScriptRoot).FullName
$ExpectedPermissions = Get-Content '.\SAMManifest.json' | ConvertFrom-Json
-
+ Get-CIPPAuthentication
$GraphToken = Get-GraphToken -returnRefresh $true -SkipCache $true
if ($GraphToken) {
$GraphPermissions = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/myorganization/applications?`$filter=appId eq '$env:ApplicationID'" -NoAuthCheck $true
@@ -38,7 +38,7 @@ function Test-CIPPAccessPermissions {
$KV = $ENV:WEBSITE_DEPLOYMENT_ID
$KeyVaultRefresh = Get-AzKeyVaultSecret -VaultName $kv -Name 'RefreshToken' -AsPlainText
if ($ENV:RefreshToken -ne $KeyVaultRefresh) {
- Write-Host "Setting success to false due to nonmaching token."
+ Write-Host 'Setting success to false due to nonmaching token.'
$Success = $false
$Messages.Add('Your refresh token does not match key vault, clear your cache or wait 30 minutes.') | Out-Null
@@ -47,43 +47,38 @@ function Test-CIPPAccessPermissions {
Href = 'https://docs.cipp.app/setup/installation/cleartokencache'
}
) | Out-Null
- }
- else {
+ } else {
$Messages.Add('Your refresh token matches key vault.') | Out-Null
}
- }
- catch {
+ } catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Key vault exception: $($_) " -Sev 'Error'
}
}
try {
$AccessTokenDetails = Read-JwtAccessDetails -Token $GraphToken.access_token -erroraction SilentlyContinue
- }
- catch {
+ } catch {
$AccessTokenDetails = [PSCustomObject]@{
Name = ''
AuthMethods = @()
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Token exception: $($_) " -Sev 'Error'
$Success = $false
- Write-Host "Setting success to false due to not able to decode token."
+ Write-Host 'Setting success to false due to not able to decode token.'
}
if ($AccessTokenDetails.Name -eq '') {
$Messages.Add('Your refresh token is invalid, check for line breaks or missing characters.') | Out-Null
- Write-Host "Setting success to false invalid token."
+ Write-Host 'Setting success to false invalid token.'
$Success = $false
- }
- else {
+ } else {
if ($AccessTokenDetails.AuthMethods -contains 'mfa') {
$Messages.Add('Your access token contains the MFA claim.') | Out-Null
- }
- else {
+ } else {
$Messages.Add('Your access token does not contain the MFA claim, Refresh your SAM tokens.') | Out-Null
- Write-Host "Setting success to False due to invalid list of claims."
+ Write-Host 'Setting success to False due to invalid list of claims.'
$Success = $false
$Links.Add([PSCustomObject]@{
@@ -107,16 +102,14 @@ function Test-CIPPAccessPermissions {
Href = 'https://docs.cipp.app/setup/installation/permissions'
}
) | Out-Null
- }
- else {
+ } else {
$Messages.Add('Your Secure Application Model has all required permissions') | Out-Null
}
- }
- catch {
+ } catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Permissions check failed: $($_) " -Sev 'Error'
$Messages.Add("We could not connect to the API to retrieve the permissions. There might be a problem with the secure application model configuration. The returned error is: $(Get-NormalizedError -message $_)") | Out-Null
- Write-Host "Setting success to False due to not being able to connect."
+ Write-Host 'Setting success to False due to not being able to connect.'
$Success = $false
}
diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1
index f0bf7fcf2d1b..02651d9a2a3f 100644
--- a/Modules/CippEntrypoints/CippEntrypoints.psm1
+++ b/Modules/CippEntrypoints/CippEntrypoints.psm1
@@ -50,7 +50,7 @@ function Receive-CippQueueTrigger {
function Receive-CippOrchestrationTrigger {
param($Context)
-
+ Write-Host 'Orchestrator started'
try {
if (Test-Json -Json $Context.Input) {
$OrchestratorInput = $Context.Input | ConvertFrom-Json
@@ -77,9 +77,10 @@ function Receive-CippOrchestrationTrigger {
}
if (($Batch | Measure-Object).Count -gt 0) {
- foreach ($Item in $Batch) {
- $null = Invoke-DurableActivity -FunctionName 'CIPPActivityFunction' -Input $Item -NoWait -RetryOptions $RetryOptions -ErrorAction Stop
+ $Tasks = foreach ($Item in $Batch) {
+ Invoke-DurableActivity -FunctionName 'CIPPActivityFunction' -Input $Item -NoWait -RetryOptions $RetryOptions -ErrorAction Stop
}
+ $null = Wait-ActivityFunction -Task $Tasks
}
if ($Context.IsReplaying -ne $true -and $OrchestratorInput.SkipLog -ne $true) {
diff --git a/Scheduler_GetWebhooks/run.ps1 b/Scheduler_GetWebhooks/run.ps1
index b262f320738b..b55b57d1f05c 100644
--- a/Scheduler_GetWebhooks/run.ps1
+++ b/Scheduler_GetWebhooks/run.ps1
@@ -3,11 +3,12 @@ param($Timer)
try {
$webhookTable = Get-CIPPTable -tablename webhookTable
- $Webhooks = Get-CIPPAzDataTableEntity @webhookTable
+ $Webhooks = Get-CIPPAzDataTableEntity @webhookTable -Property RowKey
if (($Webhooks | Measure-Object).Count -eq 0) {
Write-Host 'No webhook subscriptions found. Exiting.'
return
}
+ Write-Host 'Processing webhooks'
$InputObject = [PSCustomObject]@{
OrchestratorName = 'WebhookOrchestrator'
@@ -16,8 +17,10 @@ try {
}
SkipLog = $true
}
+ Write-Host ($InputObject | ConvertTo-Json -Depth 5)
$InstanceId = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5)
Write-Host "Started orchestration with ID = '$InstanceId'"
} catch {
- Write-LogMessage -API 'Webhooks' -message "Error processing webhooks - $($_.Exception.Message)" -sev Error
+ Write-LogMessage -API 'Webhooks' -message 'Error processing webhooks' -sev Error -LogData (Get-CippException -Exception $_)
+ Write-Host ( 'Webhook error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
}
diff --git a/profile.ps1 b/profile.ps1
index f30159db12cb..ec6aa4e19b86 100644
--- a/profile.ps1
+++ b/profile.ps1
@@ -15,9 +15,10 @@
# Import modules
@('CippCore', 'CippExtensions', 'Az.KeyVault', 'Az.Accounts') | ForEach-Object {
try {
+ $Module = $_
Import-Module -Name $_ -ErrorAction Stop
} catch {
- Write-LogMessage -message "Failed to import module $($_): $_.Exception.Message" -Sev 'debug'
+ Write-LogMessage -message "Failed to import module - $Module" -LogData (Get-CippException -Exception $_) -Sev 'debug'
$_.Exception.Message
}
}
@@ -32,7 +33,7 @@ try {
$Auth = Get-CIPPAuthentication
}
} catch {
- Write-LogMessage -message "Could not retrieve keys from Keyvault: $($_.Exception.Message)" -Sev 'debug'
+ Write-LogMessage -message 'Could not retrieve keys from Keyvault' -LogData (Get-CippException -Exception $_) -Sev 'debug'
}
# Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell.
diff --git a/version_latest.txt b/version_latest.txt
index 3238344b3b0d..c7ba1e87f75e 100644
--- a/version_latest.txt
+++ b/version_latest.txt
@@ -1 +1 @@
-5.4.4
\ No newline at end of file
+5.5.0
\ No newline at end of file