diff --git a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
index 2e0ad55e9807..9dbddea96dbc 100644
--- a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
+++ b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
@@ -12,6 +12,8 @@ function Test-CIPPAccess {
# Check help for role
$APIRole = $Help.Role
+ $AnyTenantAllowedFunctions = @('ListTenants', 'ListUserSettings', 'ListUserPhoto', 'GetCippAlerts', 'GetVersion')
+
if ($Request.Headers.'x-ms-client-principal-idp' -eq 'aad' -and $Request.Headers.'x-ms-client-principal-name' -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') {
# Direct API Access
$ForwardedFor = $Request.Headers.'x-forwarded-for' -split ',' | Select-Object -First 1
@@ -106,13 +108,14 @@ function Test-CIPPAccess {
}
if ($APIAllowed) {
+ $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter ?? $env:TenantID
# Check tenant level access
if (($Role.BlockedTenants | Measure-Object).Count -eq 0 -and $Role.AllowedTenants -contains 'AllTenants') {
$TenantAllowed = $true
- } elseif ($Request.Query.TenantFilter -eq 'AllTenants' -or $Request.Body.TenantFilter -eq 'AllTenants') {
+ } elseif ($TenantFilter -eq 'AllTenants') {
$TenantAllowed = $false
} else {
- $Tenant = ($Tenants | Where-Object { $Request.Query.TenantFilter -eq $_.customerId -or $Request.Body.TenantFilter -eq $_.customerId -or $Request.Query.TenantFilter -eq $_.defaultDomainName -or $Request.Body.TenantFilter -eq $_.defaultDomainName }).customerId
+ $Tenant = ($Tenants | Where-Object { $TenantFilter -eq $_.customerId -or $TenantFilter -eq $_.defaultDomainName }).customerId
if ($Role.AllowedTenants -contains 'AllTenants') {
$AllowedTenants = $Tenants.customerId
} else {
@@ -132,7 +135,7 @@ function Test-CIPPAccess {
if (!$APIAllowed) {
throw "Access to this CIPP API endpoint is not allowed, the '$($Role.Role)' custom role does not have the required permission: $APIRole"
}
- if (!$TenantAllowed) {
+ if (!$TenantAllowed -and $AnyTenantAllowedFunctions -notcontains $Request.Params.CIPPEndpoint) {
throw 'Access to this tenant is not allowed'
} else {
return $true
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1
index a116159aba13..6249f4cde350 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1
@@ -39,7 +39,8 @@ function Push-ListGraphRequestQueue {
}
$RawGraphRequest = try {
- Get-GraphRequestList @GraphRequestParams
+ $Results = Get-GraphRequestList @GraphRequestParams
+ $Results | Select-Object -First ($Results.Count - 1)
} catch {
$CippException = Get-CippException -Exception $_.Exception
[PSCustomObject]@{
@@ -57,6 +58,7 @@ function Push-ListGraphRequestQueue {
Data = [string]$Json
}
Add-CIPPAzDataTableEntity @Table -Entity $GraphResults -Force | Out-Null
+ return $true
} catch {
Write-Warning "Queue Error: $($_.Exception.Message)"
#Write-Information ($GraphResults | ConvertTo-Json -Depth 10 -Compress)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1
index eacfe5b53646..c264c87ea898 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1
@@ -15,7 +15,7 @@ Function Invoke-ExecSetCIPPAutoBackup {
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
$unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
- if ($Request.Body.Enabled -eq 'True') {
+ if ($Request.Body.Enabled -eq $true) {
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
$AutomatedCIPPBackupTask = Get-AzDataTableEntity @table -Filter "Name eq 'Automated CIPP Backup'"
$task = @{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1
index 045d9e55d818..bd36ddb9462c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1
@@ -15,10 +15,12 @@ function Invoke-ListGraphBulkRequest {
$TenantFilter = $Request.Body.tenantFilter
$AsApp = $Request.Body.asApp
$Requests = $Request.Body.requests
+ $NoPaginateIds = $Request.Body.noPaginateIds
$GraphRequestParams = @{
tenantid = $TenantFilter
Requests = @()
+ NoPaginateIds = $NoPaginateIds ?? @()
}
if ($AsApp) {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1
index 01f7a7d1f2c0..99faf0266fef 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1
@@ -44,7 +44,6 @@ Function Invoke-ListScheduledItems {
}
$Tasks = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Hidden -ne $HiddenTasks }
if ($Type) {
- $Tasks.Command
$Tasks = $Tasks | Where-Object { $_.command -eq $Type }
}
@@ -61,13 +60,16 @@ Function Invoke-ListScheduledItems {
} else {
$Task | Add-Member -NotePropertyName Parameters -NotePropertyValue @{}
}
+ if ($Task.Recurrence -eq 0 -or [string]::IsNullOrEmpty($Task.Recurrence)) {
+ $Task.Recurrence = 'Once'
+ }
$Task
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
- Body = @($ScheduledTasks)
+ Body = @($ScheduledTasks | Sort-Object -Property ExecutedTime -Descending)
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1
index e926564f1f4f..ebd8ee39f7a6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1
@@ -10,8 +10,8 @@ Function Invoke-ExecHideFromGAL {
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $Headers = $Request.Headers
$APIName = $Request.Params.CIPPEndpoint
+ $Headers = $Request.Headers
Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug'
@@ -22,19 +22,17 @@ Function Invoke-ExecHideFromGAL {
$HideFromGAL = [System.Convert]::ToBoolean($HideFromGAL)
Try {
- $HideResults = Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $UserId -hidefromgal $Hidden -Headers $Request.Headers -APIName $APIName
- $Results = [pscustomobject]@{'Results' = $HideResults }
+ $Result = Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $UserId -hidefromgal $HideFromGAL -Headers $Headers -APIName $APIName
$StatusCode = [HttpStatusCode]::OK
} catch {
- $ErrorMessage = Get-CippException -Exception $_
- $Results = [pscustomobject]@{'Results' = "Failed. $($ErrorMessage.NormalizedError)" }
+ $Result = $_.Exception.Message
$StatusCode = [HttpStatusCode]::Forbidden
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
- Body = $Results
+ Body = @{ 'Results' = $Result }
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1
index 6a03af82ed65..86c26f5daf33 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1
@@ -24,7 +24,6 @@ Function Invoke-ExecStartManagedFolderAssistant {
$ExoParams = @{
Identity = $Identity
- AggMailboxCleanup = $true
FullCrawl = $true
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1
index deb836716d5d..89111ef324c8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1
@@ -11,10 +11,11 @@ Function Invoke-ListMailboxes {
param($Request, $TriggerMetadata)
$APIName = $Request.Params.CIPPEndpoint
- Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $Headers = $Request.Headers
+ Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
# Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
+ $TenantFilter = $Request.Query.tenantFilter
try {
$Select = 'id,ExchangeGuid,ArchiveGuid,UserPrincipalName,DisplayName,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses,WhenSoftDeleted,IsInactiveMailbox,ForwardingSmtpAddress,DeliverToMailboxAndForward,ForwardingAddress,HiddenFromAddressListsEnabled,ExternalDirectoryObjectId,MessageCopyForSendOnBehalfEnabled,MessageCopyForSentAsEnabled'
$ExoRequest = @{
@@ -32,6 +33,7 @@ Function Invoke-ListMailboxes {
@{Parameter = 'PublicFolder'; Type = 'Bool' }
@{Parameter = 'RecipientTypeDetails'; Type = 'String' }
@{Parameter = 'SoftDeletedMailbox'; Type = 'Bool' }
+ @{Parameter = 'Identity'; Type = 'String' }
)
foreach ($Param in $Request.Query.PSObject.Properties.Name) {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1
index a54285faeef4..dd44396c9b43 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1
@@ -43,6 +43,16 @@ Function Invoke-ListIntunePolicy {
method = 'GET'
url = "/deviceManagement/windowsFeatureUpdateProfiles?`$expand=assignments&top=200"
}
+ @{
+ id = 'windowsQualityUpdatePolicies'
+ method = 'GET'
+ url = "/deviceManagement/windowsQualityUpdatePolicies?`$expand=assignments&top=200"
+ }
+ @{
+ id = 'windowsQualityUpdateProfiles'
+ method = 'GET'
+ url = "/deviceManagement/windowsQualityUpdateProfiles?`$expand=assignments&top=200"
+ }
@{
id = 'GroupPolicyConfigurations'
method = 'GET'
@@ -78,6 +88,11 @@ Function Invoke-ListIntunePolicy {
'*microsoft.graph.macOSEndpointProtectionConfiguration*' { 'MacOS Endpoint Protection' }
'*microsoft.graph.androidWorkProfileGeneralDeviceConfiguration*' { 'Android Configuration' }
'*windowsFeatureUpdateProfiles*' { 'Feature Update' }
+ '*windowsQualityUpdatePolicies*' { 'Quality Update' }
+ '*windowsQualityUpdateProfiles*' { 'Quality Update' }
+ '*iosUpdateConfiguration*' { 'iOS Update Configuration' }
+ '*windowsDriverUpdateProfiles*' { 'Driver Update' }
+ '*configurationPolicies*' { 'Device Configuration' }
default { $_.'assignments@odata.context' }
}
$Assignments = $_.assignments.target | Select-Object -Property '@odata.type', groupId
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1
index d2b0e4efce53..d22cca0f8e9e 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1
@@ -1,47 +1,47 @@
-function Invoke-ExecDismissRiskyUser {
- <#
- .FUNCTIONALITY
- Entrypoint
- .ROLE
- Identity.User.ReadWrite
- #>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
-
- $APIName = $Request.Params.CIPPEndpoint
- $Headers = $Request.Headers
- Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
-
- # Interact with the query or body of the request
- $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter
- $SuspectUser = $Request.Query.userId ?? $Request.Body.userId
- $userDisplayName = $Request.Query.userDisplayName ?? $Request.Body.userDisplayName
-
- $GraphRequest = @{
- 'uri' = 'https://graph.microsoft.com/beta/riskyUsers/dismiss'
- 'tenantid' = $TenantFilter
- 'type' = 'POST'
- 'contentType' = 'application/json; charset=utf-8'
- 'body' = @{
- 'userIds' = @($SuspectUser)
- } | ConvertTo-Json
- }
-
- try {
- $GraphResults = New-GraphPostRequest @GraphRequest
- Write-LogMessage -API $APIName -tenant $TenantFilter -message "Dismissed user risk for $userDisplayName" -sev 'Info'
- $Result = "Successfully dismissed User Risk for user $userDisplayName. $GraphResults"
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-CippException -Exception $_
- $Result = "Failed to dismiss user risk for $userDisplayName. $($ErrorMessage.NormalizedError)"
- Write-LogMessage -API $APIName -tenant $TenantFilter -message $Result -sev 'Error' -LogData $ErrorMessage
- $StatusCode = [HttpStatusCode]::InternalServerError
- }
-
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @{ 'Results' = $Result }
- })
-}
+function Invoke-ExecDismissRiskyUser {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $Request.Params.CIPPEndpoint
+ $Headers = $Request.Headers
+ Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
+
+ # Interact with the query or body of the request
+ $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter
+ $SuspectUser = $Request.Query.userId ?? $Request.Body.userId
+ $userDisplayName = $Request.Query.userDisplayName ?? $Request.Body.userDisplayName
+
+ $GraphRequest = @{
+ 'uri' = 'https://graph.microsoft.com/beta/riskyUsers/dismiss'
+ 'tenantid' = $TenantFilter
+ 'type' = 'POST'
+ 'contentType' = 'application/json; charset=utf-8'
+ 'body' = @{
+ 'userIds' = @($SuspectUser)
+ } | ConvertTo-Json
+ }
+
+ try {
+ $GraphResults = New-GraphPostRequest @GraphRequest
+ Write-LogMessage -API $APIName -tenant $TenantFilter -message "Dismissed user risk for $userDisplayName" -sev 'Info'
+ $Result = "Successfully dismissed User Risk for user $userDisplayName. $GraphResults"
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-CippException -Exception $_
+ $Result = "Failed to dismiss user risk for $userDisplayName. $($ErrorMessage.NormalizedError)"
+ Write-LogMessage -API $APIName -tenant $TenantFilter -message $Result -sev 'Error' -LogData $ErrorMessage
+ $StatusCode = [HttpStatusCode]::InternalServerError
+ }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @{ 'Results' = $Result }
+ })
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1
index cac7e39d7514..9f3d7a4f9092 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1
@@ -183,7 +183,20 @@ Function Invoke-ListUserMailboxDetails {
AutoExpandingArchive = $AutoExpandingArchiveEnabled
RecipientTypeDetails = $MailboxDetailedRequest.RecipientTypeDetails
Mailbox = $MailboxDetailedRequest
- }
+ MailboxActionsData = ($MailboxDetailedRequest | Select-Object id, ExchangeGuid, ArchiveGuid, WhenSoftDeleted, @{ Name = 'UPN'; Expression = { $_.'UserPrincipalName' } },
+ @{ Name = 'displayName'; Expression = { $_.'DisplayName' } },
+ @{ Name = 'primarySmtpAddress'; Expression = { $_.'PrimarySMTPAddress' } },
+ @{ Name = 'recipientType'; Expression = { $_.'RecipientType' } },
+ @{ Name = 'recipientTypeDetails'; Expression = { $_.'RecipientTypeDetails' } },
+ @{ Name = 'AdditionalEmailAddresses'; Expression = { ($_.'EmailAddresses' | Where-Object { $_ -clike 'smtp:*' }).Replace('smtp:', '') -join ', ' } },
+ @{Name = 'ForwardingSmtpAddress'; Expression = { $_.'ForwardingSmtpAddress' -replace 'smtp:', '' } },
+ @{Name = 'InternalForwardingAddress'; Expression = { $_.'ForwardingAddress' } },
+ DeliverToMailboxAndForward,
+ HiddenFromAddressListsEnabled,
+ ExternalDirectoryObjectId,
+ MessageCopyForSendOnBehalfEnabled,
+ MessageCopyForSentAsEnabled)
+ } # Select statement taken from ListMailboxes to save a EXO request
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1
index 1d24bf7e2ddd..cd84ca1057b1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1
@@ -18,8 +18,9 @@ Function Invoke-ListBPATemplates {
$Table = Get-CippTable -tablename 'templates'
$Templates = Get-ChildItem 'Config\*.BPATemplate.json' | ForEach-Object {
+ $TemplateJson = Get-Content $_ | ConvertFrom-Json | ConvertTo-Json -Compress -Depth 10
$Entity = @{
- JSON = "$(Get-Content $_)"
+ JSON = "$TemplateJson"
RowKey = "$($_.name)"
PartitionKey = 'BPATemplate'
GUID = "$($_.name)"
@@ -31,10 +32,14 @@ Function Invoke-ListBPATemplates {
$Templates = Get-CIPPAzDataTableEntity @Table -Filter $Filter
if ($Request.Query.RawJson) {
+ foreach ($Template in $Templates) {
+ $Template.JSON = $Template.JSON -replace '"parameters":', '"Parameters":'
+ }
$Templates = $Templates.JSON | ConvertFrom-Json
} else {
$Templates = $Templates | ForEach-Object {
- $Template = $_.JSON | ConvertFrom-Json
+ $TemplateJson = $_.JSON -replace '"parameters":', '"Parameters":'
+ $Template = $TemplateJson | ConvertFrom-Json
@{
GUID = $_.GUID
Data = $Template.fields
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1
index 011839ad6364..514473f084a6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1
@@ -18,7 +18,7 @@ Function Invoke-AddBPATemplate {
$Table = Get-CippTable -tablename 'templates'
$Table.Force = $true
Add-CIPPAzDataTableEntity @Table -Entity @{
- JSON = "$($Request.body | ConvertTo-Json -Depth 10)"
+ JSON = "$($Request.body | ConvertTo-Json -Depth 10 -Compress)"
RowKey = $Request.body.name
PartitionKey = 'BPATemplate'
GUID = $Request.body.name
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1
index 6753e0053477..2036ff01b2c6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1
@@ -14,13 +14,19 @@ Function Invoke-ListCSPsku {
Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$TenantFilter = $Request.Query.tenantFilter
- if ($Request.Query.currentSkuOnly) {
- $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter
- } else {
- $GraphRequest = Get-SherwebCatalog -TenantFilter $TenantFilter
+ try {
+ if ($Request.Query.currentSkuOnly) {
+ $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter
+ } else {
+ $GraphRequest = Get-SherwebCatalog -TenantFilter $TenantFilter
+ }
+ } catch {
+ $GraphRequest = [PSCustomObject]@{
+ name = @(@{value = 'Error getting catalog' })
+ sku = $_.Exception.Message
+ }
}
-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = @($GraphRequest)
diff --git a/Modules/CIPPCore/Public/Get-CIPPLAPSPassword.ps1 b/Modules/CIPPCore/Public/Get-CIPPLAPSPassword.ps1
index e7fa518f0b7b..4f007009a130 100644
--- a/Modules/CIPPCore/Public/Get-CIPPLAPSPassword.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPLAPSPassword.ps1
@@ -12,7 +12,11 @@ function Get-CIPPLapsPassword {
$GraphRequest = (New-GraphGetRequest -noauthcheck $true -uri "https://graph.microsoft.com/beta/directory/deviceLocalCredentials/$($device)?`$select=credentials" -tenantid $TenantFilter).credentials | Select-Object -First 1 | ForEach-Object {
$PlainText = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($_.passwordBase64))
$date = $_.BackupDateTime
- "The password for $($_.AccountName) is $($PlainText) generated at $($date)"
+ [PSCustomObject]@{
+ resultText = "LAPS password retrieved, generated at $($date). Copy the password by clicking the copy button"
+ copyField = $PlainText
+ state = 'success'
+ }
}
if ($GraphRequest) { return $GraphRequest } else { return "No LAPS password found for $device" }
} catch {
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
index dcdb0a3ae7a0..01935a2928fa 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
@@ -31,7 +31,7 @@ function New-ExoRequest {
[Parameter(ParameterSetName = 'AvailableCmdlets')]
[switch]$AvailableCmdlets,
- $ModuleVersion = '3.5.1',
+ $ModuleVersion = '3.7.1',
[switch]$AsApp
)
if ((Get-AuthorisedRequest -TenantID $tenantid) -or $NoAuthCheck -eq $True) {
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
index d0502b973082..de474b22f1f7 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
@@ -8,7 +8,8 @@ function New-GraphBulkRequest {
$NoAuthCheck,
$scope,
$asapp,
- $Requests
+ $Requests,
+ $NoPaginateIds = @()
)
if ($NoAuthCheck -or (Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) {
@@ -43,6 +44,9 @@ function New-GraphBulkRequest {
$Return
}
foreach ($MoreData in $ReturnedData.Responses | Where-Object { $_.body.'@odata.nextLink' }) {
+ if ($NoPaginateIds -contains $MoreData.id) {
+ continue
+ }
Write-Host 'Getting more'
Write-Host $MoreData.body.'@odata.nextLink'
$AdditionalValues = New-GraphGetRequest -ComplexFilter -uri $MoreData.body.'@odata.nextLink' -tenantid $tenantid -NoAuthCheck $NoAuthCheck -scope $scope -AsApp $asapp
diff --git a/Modules/CIPPCore/Public/New-CIPPBackup.ps1 b/Modules/CIPPCore/Public/New-CIPPBackup.ps1
index 9e67a03f1ba0..4727cbe71914 100644
--- a/Modules/CIPPCore/Public/New-CIPPBackup.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPBackup.ps1
@@ -40,7 +40,7 @@ function New-CIPPBackup {
$Table = Get-CippTable -tablename 'CIPPBackup'
try {
if ($PSCmdlet.ShouldProcess('CIPP Backup', 'Create')) {
- $Result = Add-CIPPAzDataTableEntity @Table -Entity $entity -Force
+ $null = Add-CIPPAzDataTableEntity @Table -Entity $entity -Force
Write-LogMessage -headers $Headers -API $APINAME -message 'Created CIPP Backup' -Sev 'Debug'
}
} catch {
@@ -66,21 +66,24 @@ function New-CIPPBackup {
RowKey = $RowKey
TenantFilter = $TenantFilter
}
- Write-Host "Scheduled backup value psproperties: $(([pscustomobject]$ScheduledBackupValues).psobject.Properties)"
+ Write-Information "Scheduled backup value psproperties: $(([pscustomobject]$ScheduledBackupValues).psobject.Properties)"
foreach ($ScheduledBackup in ([pscustomobject]$ScheduledBackupValues).psobject.Properties.Name) {
- $BackupResult = New-CIPPBackupTask -Task $ScheduledBackup -TenantFilter $TenantFilter | ConvertTo-Json -Depth 100 -Compress | Out-String
- $entity[$ScheduledBackup] = "$BackupResult"
+ try {
+ $BackupResult = New-CIPPBackupTask -Task $ScheduledBackup -TenantFilter $TenantFilter | ConvertTo-Json -Depth 100 -Compress | Out-String
+ $entity[$ScheduledBackup] = "$BackupResult"
+ } catch {
+ Write-Information "Failed to create backup for $ScheduledBackup - $($_.Exception.Message)"
+ }
}
$Table = Get-CippTable -tablename 'ScheduledBackup'
try {
- $Result = Add-CIPPAzDataTableEntity @Table -entity $entity -Force
+ $null = Add-CIPPAzDataTableEntity @Table -entity $entity -Force
Write-LogMessage -headers $Headers -API $APINAME -message 'Created backup' -Sev 'Debug'
$State = 'Backup finished succesfully'
- $Result
} catch {
$State = 'Failed to write backup to table storage'
$ErrorMessage = Get-CippException -Exception $_
- Write-LogMessage -headers $Headers -API $APINAME -message "Failed to create backup for Conditional Access Policies: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage
+ Write-LogMessage -headers $Headers -API $APINAME -message "Failed to create tenant backup: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage
[pscustomobject]@{'Results' = "Backup Creation failed: $($ErrorMessage.NormalizedError)" }
}
}
diff --git a/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1 b/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1
index 142958410cfd..05f2b0added7 100644
--- a/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1
@@ -23,7 +23,7 @@ function New-CIPPBackupTask {
}
'ca' {
Write-Host "Backup Conditional Access Policies for $TenantFilter"
- $Policies = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/conditionalAccess/policies?$top=999' -tenantid $TenantFilter
+ $Policies = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/conditionalAccess/policies?$top=999' -tenantid $TenantFilter -AsApp $true
Write-Host 'Creating templates for found Conditional Access Policies'
foreach ($policy in $policies) {
try {
@@ -40,6 +40,9 @@ function New-CIPPBackupTask {
"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=999"
"https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations?`$expand=assignments&`$filter=microsoft.graph.androidManagedStoreAppConfiguration/appSupportsOemConfig%20eq%20true"
'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsFeatureUpdateProfiles'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdatePolicies'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdateProfiles'
)
$Policies = foreach ($url in $GraphURLS) {
@@ -129,13 +132,6 @@ function New-CIPPBackupTask {
$ScheduledTasks = Get-CIPPTable -TableName 'ScheduledTasks'
Get-CIPPAzDataTableEntity @ScheduledTasks | Where-Object { $_.hidden -eq $true -and $_.command -like 'Get-CippAlert*' -and $TenantFilter -in $_.Tenant }
}
- 'CippStandards' {
- Write-Host "Backup Standards for $TenantFilter"
- $Table = Get-CippTable -tablename 'standards'
- $Filter = "PartitionKey eq 'standards' and RowKey eq '$($TenantFilter)'"
- (Get-CIPPAzDataTableEntity @Table -Filter $Filter)
- }
-
}
return $BackupData
}
diff --git a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1
index 6b89083b332b..452e81574db6 100644
--- a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1
@@ -103,6 +103,18 @@ function New-CIPPIntuneTemplate {
$DisplayName = $Template.displayName
$TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
}
+ 'windowsQualityUpdatePolicies' {
+ $Type = 'windowsQualityUpdatePolicies'
+ $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime'
+ $DisplayName = $Template.displayName
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
+ }
+ 'windowsQualityUpdateProfiles' {
+ $Type = 'windowsQualityUpdateProfiles'
+ $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime'
+ $DisplayName = $Template.displayName
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
+ }
}
return [PSCustomObject]@{
TemplateJson = $TemplateJson
diff --git a/Modules/CIPPCore/Public/New-CIPPRestore.ps1 b/Modules/CIPPCore/Public/New-CIPPRestore.ps1
index 484b6178199c..52042e261780 100644
--- a/Modules/CIPPCore/Public/New-CIPPRestore.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPRestore.ps1
@@ -11,7 +11,7 @@ function New-CIPPRestore {
Write-Host "Scheduled Restore psproperties: $(([pscustomobject]$RestoreValues).psobject.Properties)"
Write-LogMessage -headers $Headers -API $APINAME -message 'Restored backup' -Sev 'Debug'
$RestoreData = foreach ($ScheduledBackup in ([pscustomobject]$RestoreValues).psobject.Properties.Name | Where-Object { $_ -notin 'email', 'webhook', 'psa', 'backup', 'overwrite' }) {
- New-CIPPRestoreTask -Task $ScheduledBackup -TenantFilter $TenantFilter -backup $RestoreValues.backup.value -overwrite $RestoreValues.overwrite -Headers $Headers -APIName $APIName
+ New-CIPPRestoreTask -Task $ScheduledBackup -TenantFilter $TenantFilter -backup $RestoreValues.backup -overwrite $RestoreValues.overwrite -Headers $Headers -APIName $APIName
}
return $RestoreData
}
diff --git a/Modules/CIPPCore/Public/New-CIPPRestoreTask.ps1 b/Modules/CIPPCore/Public/New-CIPPRestoreTask.ps1
index 3f4a3bc2a6cb..a16760daf7ce 100644
--- a/Modules/CIPPCore/Public/New-CIPPRestoreTask.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPRestoreTask.ps1
@@ -479,7 +479,6 @@ function New-CIPPRestoreTask {
}
}
}
-
'CippWebhookAlerts' {
Write-Host "Restore Webhook Alerts for $TenantFilter"
$WebhookTable = Get-CIPPTable -TableName 'WebhookRules'
@@ -502,18 +501,6 @@ function New-CIPPRestoreTask {
"Could not restore Scripted Alerts $ErrorMessage "
}
}
- 'CippStandards' {
- Write-Host "Restore Standards for $TenantFilter"
- $Table = Get-CippTable -tablename 'standards'
- $StandardsBackup = $BackupData.CippStandards | ConvertFrom-Json
- try {
- Add-CIPPAzDataTableEntity @Table -Entity $StandardsBackup -Force
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- "Could not restore Standards $ErrorMessage "
- }
- }
-
}
return $RestoreData
}
diff --git a/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1 b/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1
index ba6144f6b69d..1c10bda343be 100644
--- a/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1
@@ -90,6 +90,9 @@ function New-CIPPTemplateRun {
"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=999"
"https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations?`$expand=assignments&`$filter=microsoft.graph.androidManagedStoreAppConfiguration/appSupportsOemConfig%20eq%20true"
'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsFeatureUpdateProfiles'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdatePolicies'
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdateProfiles'
)
$Policies = foreach ($url in $GraphURLS) {
diff --git a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1
index 173a37b874a9..49c40c9c6c4a 100644
--- a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1
+++ b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1
@@ -122,6 +122,8 @@ function Set-CIPPIntunePolicy {
$DisplayName = ($RawJSON | ConvertFrom-Json).Name
$CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter
if ($DisplayName -in $CheckExististing.name) {
+ $PolicyFile = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty Platform, PolicyType, CreationSource
+ $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress
$ExistingID = $CheckExististing | Where-Object -Property Name -EQ $DisplayName
$CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON
$CreateRequest = $CheckExististing | Where-Object -Property Name -EQ $DisplayName
@@ -140,11 +142,12 @@ function Set-CIPPIntunePolicy {
$CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter
if ($DisplayName -in $CheckExististing.displayName) {
$PostType = 'edited'
+ $PolicyFile = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty inventorySyncStatus, newUpdates, deviceReporting, approvalType
+ $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress
$ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname
Write-Host 'We are editing'
- $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON
$CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName
-
} else {
$PostType = 'added'
$CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON
@@ -159,9 +162,11 @@ function Set-CIPPIntunePolicy {
$CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter
if ($DisplayName -in $CheckExististing.displayName) {
$PostType = 'edited'
+ $PolicyFile = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty deployableContentDisplayName, endOfSupportDate, installLatestWindows10OnWindows11IneligibleDevice
+ $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress
$ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname
Write-Host 'We are editing'
- $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON
$CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName
} else {
@@ -170,7 +175,46 @@ function Set-CIPPIntunePolicy {
Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info'
}
}
-
+ 'windowsQualityUpdatePolicies' {
+ $PlatformType = 'deviceManagement'
+ $TemplateTypeURL = 'windowsQualityUpdatePolicies'
+ $File = ($RawJSON | ConvertFrom-Json)
+ $DisplayName = $File.displayName ?? $File.Name
+ $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter
+ if ($DisplayName -in $CheckExististing.displayName) {
+ $PostType = 'edited'
+ $PolicyFile = $RawJSON | ConvertFrom-Json | Select-Object *
+ $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress
+ $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname
+ Write-Host 'We are editing'
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON
+ $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName
+ } else {
+ $PostType = 'added'
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON
+ Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info'
+ }
+ }
+ 'windowsQualityUpdateProfiles' {
+ $PlatformType = 'deviceManagement'
+ $TemplateTypeURL = 'windowsQualityUpdateProfiles'
+ $File = ($RawJSON | ConvertFrom-Json)
+ $DisplayName = $File.displayName ?? $File.Name
+ $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter
+ if ($DisplayName -in $CheckExististing.displayName) {
+ $PostType = 'edited'
+ $PolicyFile = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty releaseDateDisplayName, deployableContentDisplayName
+ $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress
+ $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname
+ Write-Host 'We are editing'
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON
+ $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName
+ } else {
+ $PostType = 'added'
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON
+ Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info'
+ }
+ }
}
Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "$($PostType) policy $($Displayname)" -Sev 'Info'
if ($AssignTo) {
diff --git a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
index 53417bacbeab..58cf21e284ee 100644
--- a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
+++ b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
@@ -17,16 +17,16 @@ function Get-CIPPStandards {
$Table = Get-CippTable -tablename 'templates'
$Filter = "PartitionKey eq 'StandardsTemplateV2'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter | Sort-Object TimeStamp).JSON |
- ForEach-Object {
- try {
- # Fix old "Action" => "action"
- $JSON = $_ -replace '"Action":', '"action":'
- ConvertFrom-Json -InputObject $JSON -ErrorAction SilentlyContinue
- } catch {}
- } |
- Where-Object {
- $_.GUID -like $TemplateId -and $_.runManually -eq $runManually
- }
+ ForEach-Object {
+ try {
+ # Fix old "Action" => "action"
+ $JSON = $_ -replace '"Action":', '"action":' -replace '"permissionlevel":', '"permissionLevel":'
+ ConvertFrom-Json -InputObject $JSON -ErrorAction SilentlyContinue
+ } catch {}
+ } |
+ Where-Object {
+ $_.GUID -like $TemplateId -and $_.runManually -eq $runManually
+ }
# 2. Get tenant list, filter if needed
$AllTenantsList = Get-Tenants
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1
index c36603c329b4..ca72eac437d5 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1
@@ -47,8 +47,9 @@ function Invoke-CIPPStandardGroupTemplate {
'mailNickname' = $groupobj.username
mailEnabled = [bool]$false
securityEnabled = [bool]$true
- isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ 'AzureRole')
-
+ }
+ if ($groupobj.groupType -eq 'AzureRole') {
+ $BodyToship | Add-Member -NotePropertyName 'isAssignableToRole' -NotePropertyValue $true
}
if ($groupobj.membershipRules) {
$BodyToship | Add-Member -NotePropertyName 'membershipRule' -NotePropertyValue ($groupobj.membershipRules)
@@ -56,6 +57,7 @@ function Invoke-CIPPStandardGroupTemplate {
$BodyToship | Add-Member -NotePropertyName 'membershipRuleProcessingState' -NotePropertyValue 'On'
}
if (!$CheckExististing) {
+ $ActionType = 'create'
if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') {
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose
} else {
@@ -80,6 +82,7 @@ function Invoke-CIPPStandardGroupTemplate {
}
Write-LogMessage -API 'Standards' -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev 'Info'
} else {
+ $ActionType = 'update'
if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') {
$GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($CheckExististing.id)" -tenantid $tenant -type PATCH -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose
} else {
@@ -107,10 +110,8 @@ function Invoke-CIPPStandardGroupTemplate {
}
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create group: $ErrorMessage" -sev 'Error'
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to $ActionType group $($groupobj.displayname). Error: $ErrorMessage" -sev 'Error'
}
}
-
-
}
}
diff --git a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1
index bfea4f518ebe..42adae4b24de 100644
--- a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1
+++ b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1
@@ -85,7 +85,7 @@ function Invoke-CippWebhookProcessing {
}
$LogId = Send-CIPPAlert @CIPPAlert
- $AuditLogLink = '{0}/tenant/administration/audit-logs/log?logId={2}' -f $CIPPURL, $LogId
+ $AuditLogLink = '{0}/tenant/administration/audit-logs/log?logId={1}&tenantFilter={2}' -f $CIPPURL, $LogId, $Tenant.defaultDomainName
$GenerateEmail = New-CIPPAlertTemplate -format 'html' -data $Data -ActionResults $ActionResults -CIPPURL $CIPPURL -Tenant $Tenant.defaultDomainName -AuditLogLink $AuditLogLink
Write-Host 'Going to create the content'
diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1
index 1b8732c5b702..c3ef710b52b2 100644
--- a/Modules/CippEntrypoints/CippEntrypoints.psm1
+++ b/Modules/CippEntrypoints/CippEntrypoints.psm1
@@ -187,9 +187,9 @@ function Receive-CippActivityTrigger {
if ($Item.FunctionName) {
$FunctionName = 'Push-{0}' -f $Item.FunctionName
try {
- Write-Warning "Activity starting Function: Push-$FunctionName."
+ Write-Warning "Activity starting Function: $FunctionName."
Invoke-Command -ScriptBlock { & $FunctionName -Item $Item }
- Write-Warning "Activity completed Function: Push-$FunctionName."
+ Write-Warning "Activity completed Function: $FunctionName."
if ($TaskStatus) {
$QueueTask.Status = 'Completed'
$null = Set-CippQueueTask @QueueTask
diff --git a/Modules/CippExtensions/Public/Extension Functions/Register-CippExtensionScheduledTasks.ps1 b/Modules/CippExtensions/Public/Extension Functions/Register-CippExtensionScheduledTasks.ps1
index a560660fd8eb..fadd489958f0 100644
--- a/Modules/CippExtensions/Public/Extension Functions/Register-CippExtensionScheduledTasks.ps1
+++ b/Modules/CippExtensions/Public/Extension Functions/Register-CippExtensionScheduledTasks.ps1
@@ -14,7 +14,7 @@ function Register-CIPPExtensionScheduledTasks {
$PushTasks = Get-CIPPAzDataTableEntity @ScheduledTasksTable -Filter 'Hidden eq true' | Where-Object { $_.Command -match 'Push-CippExtensionData' }
$Tenants = Get-Tenants -IncludeErrors
- $Extensions = @('Hudu')
+ $Extensions = @('Hudu', 'NinjaOne')
$MappedTenants = [System.Collections.Generic.List[string]]::new()
foreach ($Extension in $Extensions) {
$ExtensionConfig = $Config.$Extension
@@ -30,14 +30,9 @@ function Register-CIPPExtensionScheduledTasks {
$SyncTypes.Add('Overview')
$SyncTypes.Add('Groups')
-
- if ($FieldSync.Users) {
- $SyncTypes.Add('Users')
- $SyncTypes.Add('Mailboxes')
- }
- if ($FieldSync.Devices) {
- $SyncTypes.Add('Devices')
- }
+ $SyncTypes.Add('Users')
+ $SyncTypes.Add('Mailboxes')
+ $SyncTypes.Add('Devices')
foreach ($Mapping in $Mappings) {
$Tenant = $Tenants | Where-Object { $_.customerId -eq $Mapping.RowKey }
@@ -73,7 +68,7 @@ function Register-CIPPExtensionScheduledTasks {
}
$ExistingPushTask = $PushTasks | Where-Object { $_.Tenant -eq $Tenant.defaultDomainName -and $_.SyncType -eq $Extension }
- if (!$ExistingPushTask -or $Reschedule.IsPresent) {
+ if ((!$ExistingPushTask -or $Reschedule.IsPresent) -and $Extension -ne 'NinjaOne') {
# push cached data to extension
$in30mins = [int64](([datetime]::UtcNow.AddMinutes(30)) - (Get-Date '1/1/1970')).TotalSeconds
$Task = [pscustomobject]@{
diff --git a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1
index 7f5826e18556..889034fc4278 100644
--- a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1
+++ b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1
@@ -1045,24 +1045,24 @@ function Invoke-NinjaOneTenantSync {
$CIPPUserLinksData = @(
@{
Name = 'View User'
- Link = "https://$($CIPPURL)/identity/administration/users/view?userId=$($User.id)&tenantDomain=$($Customer.defaultDomainName)"
+ Link = "https://$($CIPPURL)/identity/administration/users/user?userId=$($User.id)&tenantFilter=$($Customer.defaultDomainName)"
Icon = 'far fa-eye'
},
@{
Name = 'Edit User'
- Link = "https://$($CIPPURL)/identity/administration/users/edit?userId=$($User.id)&tenantDomain=$($Customer.defaultDomainName)"
+ Link = "https://$($CIPPURL)/identity/administration/users/user/edit?userId=$($User.id)&tenantFilter=$($Customer.defaultDomainName)"
Icon = 'fas fa-users-cog'
},
@{
Name = 'Research Compromise'
- Link = "https://$($CIPPURL)/identity/administration/ViewBec?userId=$($User.id)&tenantDomain=$($Customer.defaultDomainName)"
+ Link = "https://$($CIPPURL)/identity/administration/users/user/bec?userId=$($User.id)&tenantFilter=$($Customer.defaultDomainName)"
Icon = 'fas fa-user-secret'
}
)
# Actions
$ActionsHTML = @"
-
+
"@
diff --git a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCatalog.ps1 b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCatalog.ps1
index a7cd3a8f406a..e1970e058b62 100644
--- a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCatalog.ps1
+++ b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCatalog.ps1
@@ -4,13 +4,18 @@ function Get-SherwebCatalog {
[string]$CustomerId,
[string]$TenantFilter
)
+
if ($TenantFilter) {
- Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | ForEach-Object {
- Write-Host "Extracted customer id from tenant filter - It's $($_.IntegrationId)"
- $CustomerId = $_.IntegrationId
- }
+ $TenantFilter = (Get-Tenants -TenantFilter $TenantFilter).customerId
+ $CustomerId = Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | Select-Object -ExpandProperty IntegrationId
+ }
+
+ if (![string]::IsNullOrEmpty($CustomerId)) {
+ Write-Information "Getting catalog for $CustomerId"
+ $AuthHeader = Get-SherwebAuthentication
+ $SubscriptionsList = Invoke-RestMethod -Uri "https://api.sherweb.com/service-provider/v1/customer-catalogs/$CustomerId" -Method GET -Headers $AuthHeader
+ return $SubscriptionsList.catalogItems
+ } else {
+ throw 'No Sherweb mapping found'
}
- $AuthHeader = Get-SherwebAuthentication
- $SubscriptionsList = Invoke-RestMethod -Uri "https://api.sherweb.com/service-provider/v1/customer-catalogs/$CustomerId" -Method GET -Headers $AuthHeader
- return $SubscriptionsList.catalogItems
}
diff --git a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCurrentSubscription.ps1 b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCurrentSubscription.ps1
index aada3ea21a9c..f0cf0308dc7c 100644
--- a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCurrentSubscription.ps1
+++ b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCurrentSubscription.ps1
@@ -11,6 +11,7 @@ function Get-SherwebCurrentSubscription {
$CustomerId = Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | Select-Object -ExpandProperty IntegrationId
}
+ Write-Information "Getting current subscription for $CustomerId"
$AuthHeader = Get-SherwebAuthentication
$Uri = "https://api.sherweb.com/service-provider/v1/billing/subscriptions/details?customerId=$CustomerId"
$SubscriptionDetails = Invoke-RestMethod -Uri $Uri -Method GET -Headers $AuthHeader
diff --git a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCustomerConfiguration.ps1 b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCustomerConfiguration.ps1
index b315ee4ae057..d59d5e168357 100644
--- a/Modules/CippExtensions/Public/Sherweb/Get-SherwebCustomerConfiguration.ps1
+++ b/Modules/CippExtensions/Public/Sherweb/Get-SherwebCustomerConfiguration.ps1
@@ -5,10 +5,8 @@ function Get-SherwebCustomerConfiguration {
[string]$TenantFilter
)
if ($TenantFilter) {
- Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | ForEach-Object {
- Write-Host "Extracted customer id from tenant filter - It's $($_.IntegrationId)"
- $CustomerId = $_.IntegrationId
- }
+ $TenantFilter = (Get-Tenants -TenantFilter $TenantFilter).customerId
+ $CustomerId = Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | Select-Object -ExpandProperty IntegrationId
}
$AuthHeader = Get-SherwebAuthentication
$Uri = "https://api.sherweb.com/service-provider/v1/customers/$($CustomerId)/platforms-configurations/"
diff --git a/Modules/CippExtensions/Public/Sherweb/Remove-SherwebSubscription.ps1 b/Modules/CippExtensions/Public/Sherweb/Remove-SherwebSubscription.ps1
index cfdfc21c8148..87ca1c483d48 100644
--- a/Modules/CippExtensions/Public/Sherweb/Remove-SherwebSubscription.ps1
+++ b/Modules/CippExtensions/Public/Sherweb/Remove-SherwebSubscription.ps1
@@ -7,10 +7,8 @@ function Remove-SherwebSubscription {
[string]$TenantFilter
)
if ($TenantFilter) {
- Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | ForEach-Object {
- Write-Host "Extracted customer id from tenant filter - It's $($_.IntegrationId)"
- $CustomerId = $_.IntegrationId
- }
+ $TenantFilter = (Get-Tenants -TenantFilter $TenantFilter).customerId
+ $CustomerId = Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | Select-Object -ExpandProperty IntegrationId
}
$AuthHeader = Get-SherwebAuthentication
$Body = ConvertTo-Json -Depth 10 -InputObject @{
diff --git a/Modules/CippExtensions/Public/Sherweb/Set-SherwebSubscription.ps1 b/Modules/CippExtensions/Public/Sherweb/Set-SherwebSubscription.ps1
index 057a198966ac..d0ebc5d35616 100644
--- a/Modules/CippExtensions/Public/Sherweb/Set-SherwebSubscription.ps1
+++ b/Modules/CippExtensions/Public/Sherweb/Set-SherwebSubscription.ps1
@@ -10,10 +10,8 @@ function Set-SherwebSubscription {
[string]$TenantFilter
)
if ($TenantFilter) {
- Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | ForEach-Object {
- Write-Host "Extracted customer id from tenant filter - It's $($_.IntegrationId)"
- $CustomerId = $_.IntegrationId
- }
+ $TenantFilter = (Get-Tenants -TenantFilter $TenantFilter).customerId
+ $CustomerId = Get-ExtensionMapping -Extension 'Sherweb' | Where-Object { $_.RowKey -eq $TenantFilter } | Select-Object -ExpandProperty IntegrationId
}
$AuthHeader = Get-SherwebAuthentication
$ExistingSubscription = Get-SherwebCurrentSubscription -CustomerId $CustomerId -SKU $SKU
diff --git a/version_latest.txt b/version_latest.txt
index 643916c03f1f..eab246c063bd 100644
--- a/version_latest.txt
+++ b/version_latest.txt
@@ -1 +1 @@
-7.3.1
+7.3.2