diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000000..b0c2c5085172
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+insert_final_newline = true
+
+[*.{ps1, psd1, psm1}]
+indent_size = 4
+end_of_line = crlf
+trim_trailing_whitespace = true
+
+[*.json]
+indent_size = 2
+end_of_line = crlf
+trim_trailing_whitespace = true
+
+[*.{md, txt}]
+end_of_line = crlf
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/BestPracticeAnalyser_OrchestrationStarter/run.ps1 b/BestPracticeAnalyser_OrchestrationStarter/run.ps1
index aba14651622b..0afc6fdc07e0 100644
--- a/BestPracticeAnalyser_OrchestrationStarter/run.ps1
+++ b/BestPracticeAnalyser_OrchestrationStarter/run.ps1
@@ -32,7 +32,6 @@ $InputObject = [PSCustomObject]@{
Batch = @($BPAReports)
OrchestratorName = 'BPAOrchestrator'
SkipLog = $true
- DurableMode = 'Sequence'
}
Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
diff --git a/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1 b/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
index 6c34fc501c62..f111844160d4 100644
--- a/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
+++ b/BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
@@ -31,6 +31,5 @@ $InputObject = [PSCustomObject]@{
Batch = @($BPAReports)
OrchestratorName = 'BPAOrchestrator'
SkipLog = $true
- DurableMode = 'Sequence'
}
Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
diff --git a/Cache_SAMSetup/SAMManifest.json b/Cache_SAMSetup/SAMManifest.json
index 82bab306ef89..b6b291da57b4 100644
--- a/Cache_SAMSetup/SAMManifest.json
+++ b/Cache_SAMSetup/SAMManifest.json
@@ -157,7 +157,9 @@
{ "id": "885f682f-a990-4bad-a642-36736a74b0c7", "type": "Scope" },
{ "id": "913b9306-0ce1-42b8-9137-6a7df690a760", "type": "Role" },
{ "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope" },
- { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" }
+ { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" },
+ { "id": "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", "type": "Role" },
+ { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" }
]
},
{
diff --git a/DomainAnalyser_OrchestrationStarter/run.ps1 b/DomainAnalyser_OrchestrationStarter/run.ps1
index a5a4b2f904f2..9c16b32afdba 100644
--- a/DomainAnalyser_OrchestrationStarter/run.ps1
+++ b/DomainAnalyser_OrchestrationStarter/run.ps1
@@ -16,7 +16,6 @@ $InputObject = [PSCustomObject]@{
}
OrchestratorName = 'DomainAnalyser_Tenants'
SkipLog = $true
- DurableMode = 'Sequence'
}
Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAdminPassword.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAdminPassword.ps1
index 2b92dc01a0ab..27e911fe98b0 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAdminPassword.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAdminPassword.ps1
@@ -7,7 +7,8 @@ function Get-CIPPAlertAdminPassword {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertApnCertExpiry.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertApnCertExpiry.ps1
index 25d63b23ebcd..bf6086581cf6 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertApnCertExpiry.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertApnCertExpiry.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertApnCertExpiry {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAppSecretExpiry.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAppSecretExpiry.ps1
index cc4884df294b..cef5ba03ba14 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAppSecretExpiry.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertAppSecretExpiry.ps1
@@ -6,30 +6,28 @@ function Get-CIPPAlertAppSecretExpiry {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
Write-Host "Checking app expire for $($TenantFilter)"
$appList = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/applications?`$select=appId,displayName,passwordCredentials" -tenantid $TenantFilter
- $AlertData = foreach ($App in $applist) {
- Write-Host "checking $($App.displayName)"
- if ($App.passwordCredentials) {
- foreach ($Credential in $App.passwordCredentials) {
- if ($Credential.endDateTime -lt (Get-Date).AddDays(30) -and $Credential.endDateTime -gt (Get-Date).AddDays(-7)) {
- Write-Host ("Application '{0}' has secrets expiring on {1}" -f $App.displayName, $Credential.endDateTime)
- @{ DisplayName = $App.displayName; Expires = $Credential.endDateTime }
- }
+ } catch {
+ return
+ }
+
+ $AlertData = foreach ($App in $applist) {
+ Write-Host "checking $($App.displayName)"
+ if ($App.passwordCredentials) {
+ foreach ($Credential in $App.passwordCredentials) {
+ if ($Credential.endDateTime -lt (Get-Date).AddDays(30) -and $Credential.endDateTime -gt (Get-Date).AddDays(-7)) {
+ Write-Host ("Application '{0}' has secrets expiring on {1}" -f $App.displayName, $Credential.endDateTime)
+ @{ DisplayName = $App.displayName; Expires = $Credential.endDateTime }
}
}
- Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
-
- } else {
- Write-Host "Skipping app expire for $($TenantFilter)"
}
- } catch {
- #Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check App registration expiry for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
}
+ Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
}
-
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderMalware.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderMalware.ps1
index 6129c3b6ab3f..ea4812c62548 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderMalware.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderMalware.ps1
@@ -7,7 +7,8 @@ function Get-CIPPAlertDefenderMalware {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderStatus.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderStatus.ps1
index cccb46f13f5b..8dca902b18a5 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderStatus.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDefenderStatus.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertDefenderStatus {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDepTokenExpiry.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDepTokenExpiry.ps1
index c67ff7bc39d0..1bf1e9c4463e 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDepTokenExpiry.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertDepTokenExpiry.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertDepTokenExpiry {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
@@ -22,7 +23,7 @@ function Get-CIPPAlertDepTokenExpiry {
} catch {}
-
+
} catch {
Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check Apple Device Enrollment Program token expiry for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
}
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertExpiringLicenses.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertExpiringLicenses.ps1
index bf41dbc3e74c..1c8046934429 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertExpiringLicenses.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertExpiringLicenses.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertExpiringLicenses {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAdmins.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAdmins.ps1
index d1eb7df2c93a..411e3c96a806 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAdmins.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAdmins.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertMFAAdmins {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAlertUsers.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAlertUsers.ps1
index 386dbde00c5f..0b59055ed560 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAlertUsers.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertMFAAlertUsers.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertMFAAlertUsers {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1
index 9fe0dc66271d..3708942b4759 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1
@@ -7,7 +7,8 @@ function Get-CIPPAlertNewAppApproval {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewRole.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewRole.ps1
index 65fc84b35315..04beb6a6d523 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewRole.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewRole.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertNewRole {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
$Deltatable = Get-CIPPTable -Table DeltaCompare
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNoCAConfig.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNoCAConfig.ps1
index 2875b082fa6a..2bbc9e5a55a5 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNoCAConfig.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNoCAConfig.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertNoCAConfig {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertOverusedLicenses.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertOverusedLicenses.ps1
index dedead01d535..b02a8bb00676 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertOverusedLicenses.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertOverusedLicenses.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertOverusedLicenses {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1
index 675dbeb8251e..32b63925c02a 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1
@@ -6,22 +6,25 @@ function Get-CIPPAlertQuotaUsed {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
-
try {
- $AlertData = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/getMailboxUsageDetail(period='D7')?`$format=application/json" -tenantid $TenantFilter | ForEach-Object {
- if ($_.StorageUsedInBytes -eq 0) { return }
- $PercentLeft = [math]::round($_.StorageUsedInBytes / $_.prohibitSendReceiveQuotaInBytes * 100)
- if ($Input) { $Value = $input } else { $Value = 90 }
- if ($PercentLeft -gt $Value) {
- "$($_.UserPrincipalName): Mailbox is more than $($value)% full. Mailbox is $PercentLeft% full"
- }
-
- }
- Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
+ $AlertData = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/getMailboxUsageDetail(period='D7')?`$format=application/json" -tenantid $TenantFilter
} catch {
+ return
+ }
+ $AlertData | ForEach-Object {
+ if ($_.StorageUsedInBytes -eq 0) { return }
+ $PercentLeft = [math]::round(($_.storageUsedInBytes / $_.prohibitSendReceiveQuotaInBytes) * 100)
+ if ($InputValue) { $Value = [int]$InputValue } else { $Value = 90 }
+ if ($PercentLeft -gt $Value) {
+ "$($_.userPrincipalName): Mailbox is more than $($value)% full. Mailbox is $PercentLeft% full"
+ }
+
}
+ Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
+
}
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSecDefaultsUpsell.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSecDefaultsUpsell.ps1
index 8f3ff0fd48c2..c560d47329cb 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSecDefaultsUpsell.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSecDefaultsUpsell.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertSecDefaultsUpsell {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1
index db33c5a1a4f1..4cb04042f495 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1
@@ -7,7 +7,8 @@ function Get-CIPPAlertSharepointQuota {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
Try {
@@ -15,16 +16,15 @@ function Get-CIPPAlertSharepointQuota {
$sharepointToken = (Get-GraphToken -scope "https://$($tenantName)-admin.sharepoint.com/.default" -tenantid $TenantFilter)
$sharepointToken.Add('accept', 'application/json')
$sharepointQuota = (Invoke-RestMethod -Method 'GET' -Headers $sharepointToken -Uri "https://$($tenantName)-admin.sharepoint.com/_api/StorageQuotas()?api-version=1.3.2" -ErrorAction Stop).value
- if ($sharepointQuota) {
- if ($input -Is [Boolean]) { $Value = 90 } else { $Value = $input }
- $UsedStoragePercentage = [int](($sharepointQuota.GeoUsedStorageMB / $sharepointQuota.TenantStorageMB) * 100)
- if ($UsedStoragePercentage -gt $Value) {
- $AlertData = "SharePoint Storage is at $($UsedStoragePercentage)%. Your alert threshold is $($Value)%"
- Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
- }
- }
} catch {
+ return
+ }
+ if ($sharepointQuota) {
+ if ($InputValue -Is [Boolean]) { $Value = 90 } else { $Value = $InputValue }
+ $UsedStoragePercentage = [int](($sharepointQuota.GeoUsedStorageMB / $sharepointQuota.TenantStorageMB) * 100)
+ if ($UsedStoragePercentage -gt $Value) {
+ $AlertData = "SharePoint Storage is at $($UsedStoragePercentage)%. Your alert threshold is $($Value)%"
+ Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
+ }
}
-
-
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertUnusedLicenses.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertUnusedLicenses.ps1
index 5344c17d9ce3..d8fc1dd69e2c 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertUnusedLicenses.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertUnusedLicenses.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertUnusedLicenses {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertVppTokenExpiry.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertVppTokenExpiry.ps1
index 6fb0c2695d57..224d23857005 100644
--- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertVppTokenExpiry.ps1
+++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertVppTokenExpiry.ps1
@@ -6,7 +6,8 @@ function Get-CIPPAlertVppTokenExpiry {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
- $input,
+ [Alias('input')]
+ $InputValue,
$TenantFilter
)
try {
@@ -23,7 +24,7 @@ function Get-CIPPAlertVppTokenExpiry {
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
} catch {}
-
+
} catch {
# Error handling
}
diff --git a/Modules/CIPPCore/Public/Assert-CippVersion.ps1 b/Modules/CIPPCore/Public/Assert-CippVersion.ps1
new file mode 100644
index 000000000000..83f77f43edd0
--- /dev/null
+++ b/Modules/CIPPCore/Public/Assert-CippVersion.ps1
@@ -0,0 +1,27 @@
+function Assert-CippVersion {
+ <#
+ .SYNOPSIS
+ Compare the local version of CIPP with the latest version.
+
+ .DESCRIPTION
+ Retrieves the local version of CIPP and compares it with the latest version in GitHub.
+
+ .PARAMETER CIPPVersion
+ Local version of CIPP frontend
+
+ #>
+ Param($CIPPVersion)
+ $APIVersion = (Get-Content 'version_latest.txt' -Raw).trim()
+
+ $RemoteAPIVersion = (Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP-API/master/version_latest.txt').trim()
+ $RemoteCIPPVersion = (Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP/master/public/version_latest.txt').trim()
+
+ [PSCustomObject]@{
+ LocalCIPPVersion = $CIPPVersion
+ RemoteCIPPVersion = $RemoteCIPPVersion
+ LocalCIPPAPIVersion = $APIVersion
+ RemoteCIPPAPIVersion = $RemoteAPIVersion
+ OutOfDateCIPP = ([version]$RemoteCIPPVersion -gt [version]$CIPPVersion)
+ OutOfDateCIPPAPI = ([version]$RemoteAPIVersion -gt [version]$APIVersion)
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1 b/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1
new file mode 100644
index 000000000000..968fa5f70b9a
--- /dev/null
+++ b/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1
@@ -0,0 +1,37 @@
+function Get-CIPPHttpFunctions {
+ Param(
+ [switch]$ByRole,
+ [switch]$ByRoleGroup
+ )
+
+ try {
+ $Functions = Get-Command -Module CippCore | Where-Object { $_.Visibility -eq 'Public' -and $_.Name -match 'Invoke-*' }
+ $Results = foreach ($Function in $Functions) {
+ $Help = Get-Help $Function
+ if ($Help.Functionality -ne 'Entrypoint') { continue }
+ [PSCustomObject]@{
+ Function = $Function.Name
+ Role = $Help.Role
+ }
+ }
+
+ if ($ByRole.IsPresent -or $ByRoleGroup.IsPresent) {
+ $Results = $Results | Group-Object -Property Role | Select-Object -Property @{l = 'Permission'; e = { $_.Name -eq '' ? 'None' : $_.Name } }, Count, @{l = 'Functions'; e = { $_.Group.Function -replace 'Invoke-' } } | Sort-Object -Property Permission
+
+ if ($ByRoleGroup.IsPresent) {
+ $RoleGroup = @{}
+ foreach ($Permission in $Results) {
+ $PermSplit = $Permission.Permission -split '\.'
+ if ($PermSplit.Count -ne 3) { continue }
+ if ($RoleGroup[$PermSplit[0]] -eq $null) { $RoleGroup[$PermSplit[0]] = @{} }
+ if ($RoleGroup[$PermSplit[0]][$PermSplit[1]] -eq $null) { $RoleGroup[$PermSplit[0]][$PermSplit[1]] = @{} }
+ $RoleGroup[$PermSplit[0]][$PermSplit[1]][$PermSplit[2]] = @($Permission.Functions)
+ }
+ $Results = $RoleGroup
+ }
+ }
+ $Results
+ } catch {
+ "Function Error $($_.Exception.Message): $($_.InvocationInfo.PositionMessage)"
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Authentication/Get-CIPPRolePermissions.ps1 b/Modules/CIPPCore/Public/Authentication/Get-CIPPRolePermissions.ps1
new file mode 100644
index 000000000000..f3e1f525ac57
--- /dev/null
+++ b/Modules/CIPPCore/Public/Authentication/Get-CIPPRolePermissions.ps1
@@ -0,0 +1,30 @@
+function Get-CIPPRolePermissions {
+ <#
+ .SYNOPSIS
+ Get the permissions associated with a role.
+ .PARAMETER RoleName
+ The role to get the permissions for.
+ .EXAMPLE
+ Get-CIPPRolePermissions -RoleName 'mycustomrole'
+ #>
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]$RoleName
+ )
+
+ $Table = Get-CippTable -tablename 'CustomRoles'
+ $Filter = "RowKey eq '$RoleName'"
+ $Role = Get-CIPPAzDataTableEntity @Table -Filter $Filter
+ if ($Role) {
+ $Permissions = $Role.Permissions | ConvertFrom-Json
+ [PSCustomObject]@{
+ Role = $Role.RowKey
+ Permissions = $Permissions.PSObject.Properties.Value
+ AllowedTenants = if ($Role.AllowedTenants) { $Role.AllowedTenants | ConvertFrom-Json } else { @() }
+ BlockedTenants = if ($Role.BlockedTenants) { $Role.BlockedTenants | ConvertFrom-Json } else { @() }
+ }
+ } else {
+ throw "Role $RoleName not found."
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
new file mode 100644
index 000000000000..acdaba4e0cee
--- /dev/null
+++ b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
@@ -0,0 +1,113 @@
+function Test-CIPPAccess {
+ param(
+ $Request,
+ [switch]$TenantList
+ )
+ if ($Request.Params.CIPPEndpoint -eq 'ExecSAMSetup') { return $true }
+ if (!$Request.Headers.'x-ms-client-principal') {
+ # Direct API Access
+ $CustomRoles = @('CIPP-API')
+ } else {
+ $DefaultRoles = @('admin', 'editor', 'readonly', 'anonymous', 'authenticated')
+ $User = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Request.Headers.'x-ms-client-principal')) | ConvertFrom-Json
+ if ($User.userRoles -contains 'admin' -or $User.userRoles -contains 'superadmin') {
+ if ($TenantList.IsPresent) {
+ return @('AllTenants')
+ }
+ return $true
+ }
+
+ $CustomRoles = $User.userRoles | ForEach-Object {
+ if ($DefaultRoles -notcontains $_) {
+ $_
+ }
+ }
+ }
+ if (($CustomRoles | Measure-Object).Count -gt 0) {
+ $Tenants = Get-Tenants -IncludeErrors
+ $PermissionsFound = $false
+ $PermissionSet = foreach ($CustomRole in $CustomRoles) {
+ try {
+ Get-CIPPRolePermissions -Role $CustomRole
+ $PermissionsFound = $true
+ } catch {
+ Write-Information $_.Exception.Message
+ continue
+ }
+ }
+ if ($PermissionsFound) {
+ if ($TenantList.IsPresent) {
+ $LimitedTenantList = foreach ($Permission in $PermissionSet) {
+ if (($Permission.AllowedTenants | Measure-Object).Count -eq 0 -and ($Permission.BlockedTenants | Measure-Object).Count -eq 0) {
+ return @('AllTenants')
+ } else {
+ if ($Permission.AllowedTenants -contains 'AllTenants') {
+ $Permission.AllowedTenants = $Tenants.customerId
+ }
+ $Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
+ }
+ }
+ return $LimitedTenantList
+ }
+
+ if (($PermissionSet | Measure-Object).Count -eq 0) {
+ return $true
+ } else {
+ $FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint
+ $Help = Get-Help $FunctionName
+ # Check API for required role
+ $APIRole = $Help.Role
+ foreach ($Role in $PermissionSet) {
+ # Loop through each custom role permission and check API / Tenant access
+ $TenantAllowed = $false
+ $APIAllowed = $false
+ foreach ($Perm in $Role.Permissions) {
+ if ($Perm -match $APIRole) {
+ $APIAllowed = $true
+ break
+ }
+ }
+ if ($APIAllowed) {
+ # 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') {
+ $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
+ if ($Role.AllowedTenants -contains 'AllTenants') {
+ $AllowedTenants = $Tenants.customerId
+ } else {
+ $AllowedTenants = $Role.AllowedTenants
+ }
+ if ($Tenant) {
+ $TenantAllowed = $AllowedTenants -contains $Tenant -and $Role.BlockedTenants -notcontains $Tenant
+ if (!$TenantAllowed) { continue }
+ break
+ } else {
+ $TenantAllowed = $true
+ break
+ }
+ }
+ }
+ }
+ 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) {
+ throw 'Access to this tenant is not allowed'
+ } else {
+ return $true
+ }
+ }
+ } else {
+ # No permissions found for any roles
+ if ($TenantList.IsPresent) {
+ return @('AllTenants')
+ }
+ return $true
+ }
+ } else {
+ return $true
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1
index d04193b88d3a..ef4357efefd5 100644
--- a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1
+++ b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1
@@ -2,6 +2,8 @@ function Invoke-ListCippQueue {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
param($Request = $null, $TriggerMetadata = $null)
diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1
index 32c577f6d356..656aa592c8a7 100644
--- a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1
+++ b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1
@@ -2,6 +2,8 @@ function Invoke-RemoveCippQueue {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ CIPP.Core.ReadWrite
#>
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Clear-CippDurables.ps1 b/Modules/CIPPCore/Public/Clear-CippDurables.ps1
new file mode 100644
index 000000000000..eb1949a39078
--- /dev/null
+++ b/Modules/CIPPCore/Public/Clear-CippDurables.ps1
@@ -0,0 +1,62 @@
+function Clear-CippDurables {
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ Param()
+ # Collect info
+ $StorageContext = New-AzStorageContext -ConnectionString $env:AzureWebJobsStorage
+ $FunctionName = $env:WEBSITE_SITE_NAME
+
+ # Get orchestrators
+ $InstancesTable = Get-CippTable -TableName ('{0}Instances' -f $FunctionName)
+ $HistoryTable = Get-CippTable -TableName ('{0}History' -f $FunctionName)
+ $Yesterday = (Get-Date).AddDays(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
+ $Filter = "CreatedTime ge datetime'$Yesterday' or RuntimeStatus eq 'Pending' or RuntimeStatus eq 'Running'"
+ $Instances = Get-CippAzDataTableEntity @InstancesTable -Filter $Filter
+
+ $Queues = Get-AzStorageQueue -Context $StorageContext -Name ('{0}*' -f $FunctionName) | Select-Object -Property Name, ApproximateMessageCount, QueueClient
+
+ $RunningQueues = $Queues | Where-Object { $_.ApproximateMessageCount -gt 0 }
+ foreach ($Queue in $RunningQueues) {
+ Write-Information "- Removing queue: $($Queue.Name), message count: $($Queue.ApproximateMessageCount)"
+ if ($PSCmdlet.ShouldProcess($Queue.Name, 'Clear Queue')) {
+ $Queue.QueueClient.ClearMessagesAsync()
+ }
+ }
+
+ $QueueTable = Get-CippTable -TableName 'CippQueue'
+ $CippQueue = Invoke-ListCippQueue
+ $QueueEntities = foreach ($Queue in $CippQueue) {
+ if ($Queue.Status -eq 'Running') {
+ $Queue.TotalTasks = $Queue.CompletedTasks
+ $Queue | Select-Object -Property PartitionKey, RowKey, TotalTasks
+ }
+ }
+ if (($QueueEntities | Measure-Object).Count -gt 0) {
+ if ($PSCmdlet.ShouldProcess('Queues', 'Mark Failed')) {
+ Update-AzDataTableEntity @QueueTable -Entity $QueueEntities
+ }
+ }
+
+ $CippQueueTasks = Get-CippTable -TableName 'CippQueueTasks'
+ $RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "Status eq 'Running'" -Property RowKey, PartitionKey, Status
+ if (($RunningTasks | Measure-Object).Count -gt 0) {
+ if ($PSCmdlet.ShouldProcess('Tasks', 'Mark Failed')) {
+ $UpdatedTasks = foreach ($Task in $RunningTasks) {
+ $Task.Status = 'Failed'
+ $Task
+ }
+ Update-AzDataTableEntity @CippQueueTasks -Entity $UpdatedTasks
+ }
+ }
+
+ Remove-AzDataTable @InstancesTable
+ Remove-AzDataTable @HistoryTable
+ $BlobContainer = '{0}-largemessages' -f $Function.Name
+ if (Get-AzStorageContainer -Name $BlobContainer -Context $StorageContext -ErrorAction SilentlyContinue) {
+ Write-Information "- Removing blob container: $BlobContainer"
+ if ($PSCmdlet.ShouldProcess($BlobContainer, 'Remove Blob Container')) {
+ Remove-AzStorageContainer -Name $BlobContainer -Context $StorageContext -Confirm:$false -Force
+ }
+ }
+ $null = Get-CippTable -TableName ('{0}History' -f $FunctionName)
+ Write-Information 'Durable Orchestrators and Queues have been cleared'
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1
index c80d265bf0ba..5366603a4492 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1
@@ -122,8 +122,8 @@ function Push-DomainAnalyserDomain {
}
} catch {
$Message = 'SPF Error'
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
- throw $Message
+ Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error
+ return $Message
}
# Check SPF Record
@@ -185,8 +185,8 @@ function Push-DomainAnalyserDomain {
}
} catch {
$Message = 'DMARC Error'
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
- throw $Message
+ Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error
+ return $Message
}
# DNS Sec Check
@@ -203,8 +203,8 @@ function Push-DomainAnalyserDomain {
}
} catch {
$Message = 'DNSSEC Error'
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
- throw $Message
+ Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error
+ return $Message
}
# DKIM Check
@@ -232,8 +232,8 @@ function Push-DomainAnalyserDomain {
}
} catch {
$Message = 'DKIM Exception'
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message $Message -LogData (Get-CippException -Exception $_) -sev Error
- throw $Message
+ Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error
+ return $Message
}
# Final Score
$Result.Score = $ScoreDomain
@@ -248,9 +248,9 @@ function Push-DomainAnalyserDomain {
Add-CIPPAzDataTableEntity @DomainTable -Entity $DomainObject -Force
# Final Write to Output
- Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.tenant -message "DNS Analyser Finished For $Domain" -sev Info
+ Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "DNS Analyser Finished For $Domain" -sev Info
} catch {
- Write-LogMessage -API -API 'DomainAnalyser' -tenant $tenant.tenant -message "Error saving domain $Domain to table " -sev Error -LogData (Get-CippException -Exception $_)
+ Write-LogMessage -API -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "Error saving domain $Domain to table " -sev Error -LogData (Get-CippException -Exception $_)
}
return $null
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1
index 729ffbccee8b..605c56bebb53 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1
@@ -41,8 +41,9 @@ function Push-DomainAnalyserTenant {
$DomainCount = ($TenantDomains | Measure-Object).Count
if ($DomainCount -gt 0) {
Write-Host "$DomainCount tenant Domains"
+ $TenantDomainObjects = [System.Collections.Generic.List[object]]::new()
try {
- $TenantDomainObjects = foreach ($TenantDomain in $TenantDomains) {
+ foreach ($TenantDomain in $TenantDomains) {
$TenantDetails = ($TenantDomain | ConvertTo-Json -Compress).ToString()
$Filter = "PartitionKey eq '{0}' and RowKey eq '{1}'" -f $TenantDomain.Tenant, $TenantDomain.Domain
$OldDomain = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter
@@ -78,19 +79,23 @@ function Push-DomainAnalyserTenant {
}
}
# Return domain object to list
- $Domain
+ $TenantDomainObjects.Add($Domain)
}
# Batch insert tenant domains
try {
Add-CIPPAzDataTableEntity @DomainTable -Entity $TenantDomainObjects -Force
$InputObject = [PSCustomObject]@{
- Batch = $TenantDomainObjects | Select-Object RowKey, @{n = 'FunctionName'; exp = { 'DomainAnalyserDomain' } }
+ QueueFunction = @{
+ FunctionName = 'GetTenantDomains'
+ TenantGUID = $Tenant.customerId
+ }
OrchestratorName = "DomainAnalyser_$($Tenant.defaultDomainName)"
SkipLog = $true
- DurableMode = 'Sequence'
}
Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+ Write-Host "Started analysis for $DomainCount tenant domains in $($Tenant.defaultDomainName)"
+ Write-LogMessage -API 'DomainAnalyser' -tenant $Tenant.defaultDomainName -message "Started analysis for $DomainCount tenant domains" -sev Info
} catch {
Write-LogMessage -API 'DomainAnalyser' -message 'Domain Analyser GetTenantDomains error' -sev info -LogData (Get-CippException -Exception $_)
}
@@ -99,7 +104,7 @@ function Push-DomainAnalyserTenant {
}
}
} catch {
- Write-Host (Get-CippException -Exception $_ | ConvertTo-Json)
+ #Write-Host (Get-CippException -Exception $_ | ConvertTo-Json)
Write-LogMessage -API 'DomainAnalyser' -tenant $tenant.defaultDomainName -message 'DNS Analyser GraphGetRequest' -LogData (Get-CippException -Exception $_) -sev Error
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-GetTenantDomains.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-GetTenantDomains.ps1
new file mode 100644
index 000000000000..5fb9c64cdad1
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-GetTenantDomains.ps1
@@ -0,0 +1,7 @@
+function Push-GetTenantDomains {
+ Param($Item)
+ $DomainTable = Get-CippTable -tablename 'Domains'
+ $Filter = "PartitionKey eq 'TenantDomains' and TenantGUID eq '{0}'" -f $Item.TenantGUID
+ $Domains = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter -Property RowKey | Select-Object RowKey, @{n = 'FunctionName'; exp = { 'DomainAnalyserDomain' } }
+ return @($Domains)
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
index 78223a4bdf93..3e597fab6553 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1
@@ -278,7 +278,7 @@ Function Push-ExecOnboardTenantQueue {
$Tenant = Get-Tenants -TriggerRefresh -IncludeAll | Where-Object { $_.customerId -eq $Relationship.customer.tenantId } | Select-Object -First 1
$y++
Start-Sleep -Seconds 20
- } while (!$Tenant -and $y -le 4)
+ } while (!$Tenant -and $y -le 10)
if ($Tenant) {
$Logs.Add([PSCustomObject]@{ Date = Get-Date -UFormat $DateFormat; Log = 'Tenant found in customer list' })
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1
index ddfa5a2f29eb..20746f57fa52 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1
@@ -4,16 +4,17 @@ function Push-ExecScheduledCommand {
Entrypoint
#>
param($Item)
- Write-Host "We are going to be running a scheduled task: $($Item.TaskInfo | ConvertTo-Json)"
+ Write-Host "We are going to be running a scheduled task: $($Item.TaskInfo | ConvertTo-Json -Depth 10)"
$Table = Get-CippTable -tablename 'ScheduledTasks'
$task = $Item.TaskInfo
- $commandParameters = $Item.Parameters | ConvertTo-Json | ConvertFrom-Json -AsHashtable
+ $commandParameters = $Item.Parameters | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable
$tenant = $Item.Parameters['TenantFilter']
Write-Host "Started Task: $($Item.Command) for tenant: $tenant"
try {
try {
+ Write-Host "Starting task: $($Item.Command) with parameters: "
$results = & $Item.Command @commandParameters
} catch {
$results = "Task Failed: $($_.Exception.Message)"
@@ -53,15 +54,15 @@ function Push-ExecScheduledCommand {
Results = "$errorMessage"
TaskState = $State
}
- Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): $errorMessage" -sev Error
+ Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): $errorMessage" -sev Error -LogData (Get-CippExceptionData -Exception $_.Exception)
}
Write-Host 'Sending task results to target. Updating the task state.'
if ($Results) {
$TableDesign = ''
$FinalResults = if ($results -is [array] -and $results[0] -is [string]) { $Results | ConvertTo-Html -Fragment -Property @{ l = 'Text'; e = { $_ } } } else { $Results | ConvertTo-Html -Fragment }
- $HTML = $FinalResults -replace '
', "$TableDesign" | Out-String
- $title = "$TaskType - $($task.Name)"
+ $HTML = $FinalResults -replace '', "This alert is for tenant $tenant.
$TableDesign" | Out-String
+ $title = "$TaskType - $($task.Name) - $tenant"
Write-Host 'Scheduler: Sending the results to the target.'
Write-Host "The content of results is: $Results"
switch -wildcard ($task.PostExecution) {
@@ -79,7 +80,8 @@ function Push-ExecScheduledCommand {
}
Write-Host 'Sent the results to the target. Updating the task state.'
- if ($task.Recurrence -eq '0' -or $task.Recurrence -eq $null) {
+ if ($task.Recurrence -eq '0' -or [string]::IsNullOrEmpty($task.Recurrence)) {
+ Write-Host 'Recurrence empty or 0. Task is not recurring. Setting task state to completed.'
Update-AzDataTableEntity @Table -Entity @{
PartitionKey = $task.PartitionKey
RowKey = $task.RowKey
@@ -107,5 +109,7 @@ function Push-ExecScheduledCommand {
ScheduledTime = "$nextRunUnixTime"
}
}
- Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Successfully executed task: $($task.Name)" -sev Info
+ if ($TaskType -ne 'Alert') {
+ Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Successfully executed task: $($task.Name)" -sev Info
+ }
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
index cb8e46acde61..0669c01fabfa 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1
@@ -11,7 +11,7 @@ function Push-PublicWebhookProcess {
if ($Webhook.Type -eq 'GraphSubscription') {
Invoke-CippGraphWebhookProcessing -Data ($Webhook.Data | ConvertFrom-Json) -CIPPID $Webhook.CIPPID -WebhookInfo ($Webhook.Webhookinfo | ConvertFrom-Json)
} elseif ($Webhook.Type -eq 'AuditLog') {
- Invoke-CippWebhookProcessing -TenantFilter $Webhook.TenantFilter -Data ($Webhook.Data | ConvertFrom-Json) -CIPPPURL $Webhook.CIPPURL
+ Invoke-CippWebhookProcessing -TenantFilter $Webhook.TenantFilter -Data ($Webhook.Data | ConvertFrom-Json) -CIPPURL $Webhook.CIPPURL
} elseif ($Webhook.Type -eq 'PartnerCenter') {
Invoke-CippPartnerWebhookProcessing -Data ($Webhook.Data | ConvertFrom-Json)
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1
index d3ca1dc6b455..8c56ccb98971 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1
@@ -7,8 +7,9 @@ function Push-Schedulerwebhookcreation {
$item
)
$Table = Get-CIPPTable -TableName 'SchedulerConfig'
- $WebhookTable = Get-CIPPTable -TableName 'WebhookTable'
+ $WebhookTable = Get-CIPPTable -TableName 'webhookTable'
+ #Write-Information ($item | ConvertTo-Json -Depth 10)
$Row = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($item.SchedulerRow)'"
if (!$Row) {
Write-Host "No row found for $($item.SchedulerRow). Full received item was $($item | ConvertTo-Json)"
@@ -34,7 +35,7 @@ function Push-Schedulerwebhookcreation {
$NewSub = New-CIPPGraphSubscription -TenantFilter $Tenant -EventType $Row.webhookType -BaseURL $Row.CIPPURL -auditLogAPI $true
if ($NewSub.Success -and $Row.tenantid -ne 'AllTenants') {
Remove-AzDataTableEntity @Table -Entity $Row
- } else {
+ } else {
Write-Host "Failed to create webhook for $Tenant - $($Row.webhookType) - $($_.Exception.Message)"
Write-LogMessage -message "Failed to create webhook for $Tenant - $($Row.webhookType)" -Sev 'Error' -LogData $_.Exception
}
@@ -47,5 +48,5 @@ function Push-Schedulerwebhookcreation {
}
}
}
-
+
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdateTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdateTenants.ps1
index f60a27a57b26..811d54b229be 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdateTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdateTenants.ps1
@@ -10,13 +10,24 @@ function Push-UpdateTenants {
Write-Host 'Update Tenants already running'
return
}
- $Queue = New-CippQueueEntry -Name 'Update Tenants' -Reference $QueueReference
+ $Queue = New-CippQueueEntry -Name 'Update Tenants' -Reference $QueueReference -TotalTasks 1
try {
+ $QueueTask = @{
+ QueueId = $Queue.RowKey
+ Name = 'Get tenant list'
+ Status = 'Running'
+ }
+ $TaskStatus = Set-CippQueueTask @QueueTask
+ $QueueTask.TaskId = $TaskStatus.RowKey
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Running'
- Get-Tenants | Out-Null
+ Get-Tenants -IncludeAll -TriggerRefresh | Out-Null
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Completed'
+ $QueueTask.Status = 'Completed'
+ Set-CippQueueTask @QueueTask
} catch {
Write-Host "Queue Error: $($_.Exception.Message)"
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Failed'
+ $QueueTask.Status = 'Failed'
+ Set-CippQueueTask @QueueTask
}
}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1
index 1e1ecbfc0fcc..81a079c2401d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAddAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1
index 6028762273c6..09da6bd2c990 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1
@@ -2,6 +2,8 @@ function Invoke-ExecDurableFunctions {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param($Request, $TriggerMetadata)
@@ -139,9 +141,13 @@ function Invoke-ExecDurableFunctions {
$HistoryTable = Get-CippTable -TableName ('{0}History' -f $FunctionName)
if ($Request.Query.PartitionKey) {
$HistoryEntities = Get-CIPPAzDataTableEntity @HistoryTable -Filter "PartitionKey eq '$($Request.Query.PartitionKey)'" -Property RowKey, PartitionKey
- Remove-AzDataTableEntity @HistoryTable -Entity $HistoryEntities
+ if ($HistoryEntities) {
+ Remove-AzDataTableEntity @HistoryTable -Entity $HistoryEntities
+ }
$Instance = Get-CIPPAzDataTableEntity @InstancesTable -Filter "PartitionKey eq '$($Request.Query.PartitionKey)'" -Property RowKey, PartitionKey
- Remove-AzDataTableEntity @InstancesTable -Entity $Instance
+ if ($Instance) {
+ Remove-AzDataTableEntity @InstancesTable -Entity $Instance
+ }
$Body = [PSCustomObject]@{
Results = 'Orchestrator {0} purged successfully' -f $Request.Query.PartitionKey
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1
index 4998a8447406..053395d7d293 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecEditTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,7 +13,7 @@ Function Invoke-ExecEditTemplate {
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- try {
+ try {
$Table = Get-CippTable -tablename 'templates'
$Table.Force = $true
$guid = $request.body.guid
@@ -33,7 +35,7 @@ Function Invoke-ExecEditTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Edited template $($Request.body.name) with GUID $GUID" -Sev 'Debug'
}
$body = [pscustomobject]@{ 'Results' = 'Successfully saved the template' }
-
+
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to edit template: $($_.Exception.Message)" -Sev 'Error'
$body = [pscustomobject]@{'Results' = "Editing template failed: $($_.Exception.Message)" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1
index 3410320f99a8..6c252b12c28c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGeoIPLookup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1
new file mode 100644
index 000000000000..90b7e41bc4c9
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1
@@ -0,0 +1,21 @@
+using namespace System.Net
+
+Function Invoke-ExecListBackup {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ CIPP.Backup.Read
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $Result = Get-CIPPBackup -type $Request.body.Type -TenantFilter $Request.body.TenantFilter
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Alerts' -message $request.body.text -Sev $request.body.Severity
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = @($Result)
+ })
+
+}
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
index d6efbbe307f0..5a235ee7cb7d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1
@@ -2,6 +2,8 @@ function Invoke-ExecPartnerWebhook {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
Param($Request, $TriggerMetadata)
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
new file mode 100644
index 000000000000..2d04df48933c
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1
@@ -0,0 +1,43 @@
+using namespace System.Net
+
+Function Invoke-ExecSetCIPPAutoBackup {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ CIPP.Backup.Read
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+ $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
+ if ($Request.query.Enabled -eq 'True') {
+ $Table = Get-CIPPTable -TableName 'ScheduledTasks'
+ $AutomatedCIPPBackupTask = Get-AzDataTableEntity @table -Filter "Name eq 'Automated CIPP Backup'"
+ $task = @{
+ RowKey = $AutomatedCIPPBackupTask.RowKey
+ PartitionKey = 'ScheduledTask'
+ }
+ Remove-AzDataTableEntity @Table -Entity $task | Out-Null
+
+ $TaskBody = @{
+ TenantFilter = 'AllTenants'
+ Name = 'Automated CIPP Backup'
+ Command = @{
+ value = 'New-CIPPBackup'
+ label = 'New-CIPPBackup'
+ }
+ Parameters = @{ backupType = 'CIPP' }
+ ScheduledTime = $unixtime
+ Recurrence = '1d'
+ }
+ Add-CIPPScheduledTask -Task $TaskBody -hidden $false
+ $Result = @{ 'Results' = 'Scheduled Task Successfully created' }
+ }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Alerts' -message $request.body.text -Sev $request.body.Severity
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Result
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1
index d0bbaea27dfc..1ec68eb1a7c7 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1
@@ -3,60 +3,48 @@ using namespace System.Net
Function Invoke-GetCippAlerts {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $Alerts = [System.Collections.ArrayList]@()
+ $Alerts = [System.Collections.Generic.List[object]]::new()
$Table = Get-CippTable -tablename CippAlerts
$PartitionKey = Get-Date -UFormat '%Y%m%d'
$Filter = "PartitionKey eq '{0}'" -f $PartitionKey
$Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Sort-Object TableTimestamp -Descending | Select-Object -First 10
$role = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json).userRoles
- $APIVersion = Get-Content 'version_latest.txt' | Out-String
- $CIPPVersion = $request.query.localversion
-
- $RemoteAPIVersion = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP-API/master/version_latest.txt'
- $RemoteCIPPVersion = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP/master/public/version_latest.txt'
-
- $version = [PSCustomObject]@{
- LocalCIPPVersion = $CIPPVersion
- RemoteCIPPVersion = $RemoteCIPPVersion
- LocalCIPPAPIVersion = $APIVersion
- RemoteCIPPAPIVersion = $RemoteAPIVersion
- OutOfDateCIPP = ([version]$RemoteCIPPVersion -gt [version]$CIPPVersion)
- OutOfDateCIPPAPI = ([version]$RemoteAPIVersion -gt [version]$APIVersion)
- }
- if ($version.outOfDateCIPP) {
- $Alerts.add(@{Alert = 'Your CIPP Frontend is out of date. Please update to the latest version. Find more on the following '; link = 'https://docs.cipp.app/setup/installation/updating'; type = 'warning' })
+ $CIPPVersion = $Request.Query.localversion
+ $Version = Assert-CippVersion -CIPPVersion $CIPPVersion
+ if ($Version.OutOfDateCIPP) {
+ $Alerts.Add(@{Alert = 'Your CIPP Frontend is out of date. Please update to the latest version. Find more on the following '; link = 'https://docs.cipp.app/setup/installation/updating'; type = 'warning' })
Write-LogMessage -message 'Your CIPP Frontend is out of date. Please update to the latest version' -API 'Updates' -tenant 'All Tenants' -sev Alert
}
- if ($version.outOfDateCIPPAPI) {
- $Alerts.add(@{Alert = 'Your CIPP API is out of date. Please update to the latest version. Find more on the following'; link = 'https://docs.cipp.app/setup/installation/updating'; type = 'warning' })
+ if ($Version.OutOfDateCIPPAPI) {
+ $Alerts.Add(@{Alert = 'Your CIPP API is out of date. Please update to the latest version. Find more on the following'; link = 'https://docs.cipp.app/setup/installation/updating'; type = 'warning' })
Write-LogMessage -message 'Your CIPP API is out of date. Please update to the latest version' -API 'Updates' -tenant 'All Tenants' -sev Alert
}
-
- if ($env:ApplicationID -eq 'LongApplicationID' -or $null -eq $ENV:ApplicationID) { $Alerts.add(@{Alert = 'You have not yet setup your SAM Setup. Please go to the SAM Wizard in settings to finish setup'; link = '/cipp/setup'; type = 'warning' }) }
- if ($role -like '*superadmin*') { $Alerts.add(@{Alert = 'You are logged in under a superadmin account. This account should not be used for normal usage.'; link = 'https://docs.cipp.app/setup/installation/owntenant'; type = 'danger' }) }
- if ($env:WEBSITE_RUN_FROM_PACKAGE -ne '1') {
- $Alerts.add(
+ if ($env:ApplicationID -eq 'LongApplicationID' -or $null -eq $ENV:ApplicationID) { $Alerts.Add(@{Alert = 'You have not yet completed your SAM Setup. Please go to the SAM Setup Wizard in settings to connect CIPP to your tenant.'; link = '/cipp/setup'; type = 'warning' }) }
+ if ($role -like '*superadmin*') { $Alerts.Add(@{Alert = 'You are logged in under a superadmin account. This account should not be used for normal usage.'; link = 'https://docs.cipp.app/setup/installation/owntenant'; type = 'danger' }) }
+ if ($env:WEBSITE_RUN_FROM_PACKAGE -ne '1' -and $env:AzureWebJobsStorage -ne 'UseDevelopmentStorage=true') {
+ $Alerts.Add(
@{Alert = 'Your Function App is running in write mode. This will cause performance issues and increase cost. Please check this '
- link = 'https://docs.cipp.app/setup/installation/runfrompackage'
- type = 'warning'
- })
+ link = 'https://docs.cipp.app/setup/installation/runfrompackage'
+ type = 'warning'
+ })
}
- if ($Rows) { $Rows | ForEach-Object { $alerts.add($_) } }
+ if ($Rows) { $Rows | ForEach-Object { $Alerts.Add($_) } }
$Alerts = @($Alerts)
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
-
# Write to the Azure Functions log stream.
-
+
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1
index b92ecb48d6e6..61df91438485 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-GetVersion {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,20 +13,9 @@ Function Invoke-GetVersion {
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $APIVersion = Get-Content 'version_latest.txt' | Out-String
$CIPPVersion = $request.query.localversion
- $RemoteAPIVersion = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP-API/master/version_latest.txt'
- $RemoteCIPPVersion = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/KelvinTegelaar/CIPP/master/public/version_latest.txt'
-
- $version = [PSCustomObject]@{
- LocalCIPPVersion = $CIPPVersion
- RemoteCIPPVersion = $RemoteCIPPVersion
- LocalCIPPAPIVersion = $APIVersion
- RemoteCIPPAPIVersion = $RemoteAPIVersion
- OutOfDateCIPP = ([version]$RemoteCIPPVersion -gt [version]$CIPPVersion)
- OutOfDateCIPPAPI = ([version]$RemoteAPIVersion -gt [version]$APIVersion)
- }
+ $Version = Assert-CippVersion -CIPPVersion $CIPPVersion
# Write to the Azure Functions log stream.
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1
index 44dbfa761030..50860f6e034b 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddScheduledItem {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Scheduler.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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 71aa6aa536fe..81231ca9df96 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListScheduledItems {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Scheduler.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,14 +13,22 @@ Function Invoke-ListScheduledItems {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
- if ($Request.query.Showhidden -eq 'true') {
+ if ($Request.Query.Showhidden -eq $true) {
$HiddenTasks = $false
} else {
$HiddenTasks = $true
}
$Tasks = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'ScheduledTask'" | Where-Object { $_.Hidden -ne $HiddenTasks }
+ $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
+ if ($AllowedTenants -notcontains 'AllTenants') {
+ $Tasks = $Tasks | Where-Object -Property TenantId -In $AllowedTenants
+ }
$ScheduledTasks = foreach ($Task in $tasks) {
- $Task.Parameters = $Task.Parameters | ConvertFrom-Json
+ if ($Task.Parameters) {
+ $Task.Parameters = $Task.Parameters | ConvertFrom-Json -ErrorAction SilentlyContinue
+ } else {
+ $Task | Add-Member -NotePropertyName Parameters -NotePropertyValue @{}
+ }
$Task
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1
index 629760a2ca68..f21b1b88e275 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveScheduledItem {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Scheduler.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,8 +14,6 @@ Function Invoke-RemoveScheduledItem {
RowKey = $Request.Query.ID
PartitionKey = 'ScheduledTask'
}
-
-
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
Remove-AzDataTableEntity @Table -Entity $task
@@ -21,7 +21,7 @@ Function Invoke-RemoveScheduledItem {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
- Body = @{ Results = 'Task removed successfully.' }
+ Body = @{ Results = 'Task removed successfully.' }
})
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAPIPermissionList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAPIPermissionList.ps1
new file mode 100644
index 000000000000..a877e4b829d2
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAPIPermissionList.ps1
@@ -0,0 +1,17 @@
+function Invoke-ExecAPIPermissionList {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ CIPP.SuperAdmin.Read
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $Roles = Get-CIPPHttpFunctions -ByRoleGroup | ConvertTo-Json -Depth 10
+
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Roles
+ })
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1
index 93a72e2e296d..f655b21c2a91 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAccessChecks {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,14 +16,14 @@ Function Invoke-ExecAccessChecks {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
- if ($Request.query.Permissions -eq 'true') {
- $Results = Test-CIPPAccessPermissions -tenantfilter $ENV:tenantid -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ if ($Request.Query.Permissions -eq 'true') {
+ $Results = Test-CIPPAccessPermissions -tenantfilter $ENV:tenantid -APIName $APINAME -ExecutingUser $Request.Headers.'x-ms-client-principal'
}
- if ($Request.query.Tenants -eq 'true') {
- $Results = Test-CIPPAccessTenant -Tenantcsv $Request.body.TenantId
+ if ($Request.Query.Tenants -eq 'true') {
+ $Results = Test-CIPPAccessTenant -TenantCSV $Request.Body.tenantid
}
- if ($Request.query.GDAP -eq 'true') {
+ if ($Request.Query.GDAP -eq 'true') {
$Results = Test-CIPPGDAPRelationships
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAddTrustedIP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAddTrustedIP.ps1
index db587ae67959..4613ea2c3c68 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAddTrustedIP.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAddTrustedIP.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAddTrustedIP {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1
index 4a29002ad122..4c0adc7368e8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecBackendURLs {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1
index 4703972094e4..db0bae59c71b 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecCPVPermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1
new file mode 100644
index 000000000000..a1e92d2c3f89
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1
@@ -0,0 +1,64 @@
+function Invoke-ExecCustomRole {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ CIPP.SuperAdmin.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $Table = Get-CippTable -tablename 'CustomRoles'
+ switch ($Request.Query.Action) {
+ 'AddUpdate' {
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API 'ExecCustomRole' -message "Saved custom role $($Request.Body.RoleName)" -Sev 'Info'
+ $Role = @{
+ 'PartitionKey' = 'CustomRoles'
+ 'RowKey' = "$($Request.Body.RoleName)"
+ 'Permissions' = "$($Request.Body.Permissions | ConvertTo-Json -Compress)"
+ 'AllowedTenants' = "$($Request.Body.AllowedTenants | ConvertTo-Json -Compress)"
+ 'BlockedTenants' = "$($Request.Body.BlockedTenants | ConvertTo-Json -Compress)"
+ }
+ Add-CIPPAzDataTableEntity @Table -Entity $Role -Force | Out-Null
+ $Body = @{Results = 'Custom role saved' }
+ }
+ 'Delete' {
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API 'ExecCustomRole' -message "Deleted custom role $($Request.Body.RoleName)" -Sev 'Info'
+ $Role = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($Request.Body.RoleName)'" -Property RowKey, PartitionKey
+ Remove-AzDataTableEntity @Table -Entity $Role
+ $Body = @{Results = 'Custom role deleted' }
+ }
+ default {
+ $Body = Get-CIPPAzDataTableEntity @Table
+
+ if (!$Body) {
+ $Body = @(
+ @{
+ RowKey = 'No custom roles found'
+ }
+ )
+ } else {
+ $Body = foreach ($Role in $Body) {
+ $Role.Permissions = $Role.Permissions | ConvertFrom-Json
+ if ($Role.AllowedTenants) {
+ $Role.AllowedTenants = @($Role.AllowedTenants | ConvertFrom-Json)
+ } else {
+ $Role | Add-Member -NotePropertyName AllowedTenants -NotePropertyValue @() -Force
+ }
+ if ($Role.BlockedTenants) {
+ $Role.BlockedTenants = @($Role.BlockedTenants | ConvertFrom-Json)
+ } else {
+ $Role | Add-Member -NotePropertyName BlockedTenants -NotePropertyValue @() -Force
+ }
+ $Role
+ }
+ $Body = @($Body)
+ }
+ }
+ }
+
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Body
+ })
+}
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 41768a704af5..147855eab44c 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecDnsConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1
index c20795dcb97c..8b18bb186e4a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecExcludeLicenses {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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 ca3e85feed9a..76c414414905 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecExcludeTenant {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionMapping.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionMapping.ps1
index e848d7df1669..77b8e277c780 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionMapping.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionMapping.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecExtensionMapping {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionSync.ps1
index 3abce0100b91..2f069988996a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionSync.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionSync.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecExtensionSync {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionTest.ps1
index afbdfacc402c..78e82e78121a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionTest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionTest.ps1
@@ -1,50 +1,60 @@
- using namespace System.Net
+using namespace System.Net
- Function Invoke-ExecExtensionTest {
+Function Invoke-ExecExtensionTest {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
-Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug"
-$Table = Get-CIPPTable -TableName Extensionsconfig
-$Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json)
-# Interact with query parameters or the body of the request.
-try {
- switch ($Request.query.extensionName) {
- "HaloPSA" {
- $token = Get-HaloToken -configuration $Configuration.HaloPSA
- $Results = [pscustomobject]@{"Results" = "Successfully Connected to HaloPSA" }
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $Table = Get-CIPPTable -TableName Extensionsconfig
+ $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json)
+ # Interact with query parameters or the body of the request.
+ try {
+ switch ($Request.query.extensionName) {
+ 'HaloPSA' {
+ $token = Get-HaloToken -configuration $Configuration.HaloPSA
+ $Results = [pscustomobject]@{'Results' = 'Successfully Connected to HaloPSA' }
}
- "Gradient" {
- $GradientToken = Get-GradientToken -Configuration $Configuration.Gradient
- $ExistingIntegrations = Invoke-RestMethod -Uri 'https://app.usegradient.com/api/vendor-api/organization' -Method GET -Headers $GradientToken
- if ($ExistingIntegrations.Status -ne "active") {
- $ActivateRequest = Invoke-RestMethod -Uri 'https://app.usegradient.com/api/vendor-api/organization/status/active' -Method PATCH -Headers $GradientToken
- }
- $Results = [pscustomobject]@{"Results" = "Succesfully Connected to Gradient" }
+ 'Gradient' {
+ $GradientToken = Get-GradientToken -Configuration $Configuration.Gradient
+ $ExistingIntegrations = Invoke-RestMethod -Uri 'https://app.usegradient.com/api/vendor-api/organization' -Method GET -Headers $GradientToken
+ if ($ExistingIntegrations.Status -ne 'active') {
+ $ActivateRequest = Invoke-RestMethod -Uri 'https://app.usegradient.com/api/vendor-api/organization/status/active' -Method PATCH -Headers $GradientToken
+ }
+ $Results = [pscustomobject]@{'Results' = 'Succesfully Connected to Gradient' }
}
- "CIPP-API" {
- $Results = [pscustomobject]@{"Results" = "You cannot test the CIPP-API from CIPP. Please check the documentation on how to test the CIPP-API." }
+ 'CIPP-API' {
+ $Results = [pscustomobject]@{'Results' = 'You cannot test the CIPP-API from CIPP. Please check the documentation on how to test the CIPP-API.' }
}
- "NinjaOne" {
- $token = Get-NinjaOneToken -configuration $Configuration.NinjaOne
- $Results = [pscustomobject]@{"Results" = "Succesfully Connected to NinjaOne" }
+ 'NinjaOne' {
+ $token = Get-NinjaOneToken -configuration $Configuration.NinjaOne
+ $Results = [pscustomobject]@{'Results' = 'Succesfully Connected to NinjaOne' }
}
- }
-}
-catch {
- $Results = [pscustomobject]@{"Results" = "Failed to connect: $($_.Exception.Message) $($_.InvocationInfo.ScriptLineNumber)" }
-}
+ 'PWPush' {
+ $Payload = 'This is a test from CIPP'
+ $PasswordLink = New-PwPushLink -Payload $Payload
+ if ($PasswordLink) {
+ $Results = [pscustomobject]@{'Results' = 'Succesfully generated PWPush'; 'Link' = $PasswordLink }
+ } else {
+ $Results = [pscustomobject]@{'Results' = 'PWPush is not enabled' }
+ }
+ }
+ }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed to connect: $($_.Exception.Message) $($_.InvocationInfo.ScriptLineNumber)" }
+ }
-# Associate values to output bindings by calling 'Push-OutputBinding'.
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $Results
- })
+ })
- }
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionsConfig.ps1
index 50675339a8f8..fd3b8764959d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionsConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExtensionsConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecExtensionsConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1
index 567e6dc3a1c4..fe01aed3123e 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecMaintenanceScripts {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -17,7 +19,7 @@ Function Invoke-ExecMaintenanceScripts {
$ReplacementStrings = @{
'##TENANTID##' = $env:TenantID
'##RESOURCEGROUP##' = $env:WEBSITE_RESOURCE_GROUP
- '##FUNCTIONAPP##' = $env:WEBSITE_SITE_NAME
+ '##FUNCTIONAPP##' = $env:WEBSITE_SITE_NAME
'##SUBSCRIPTION##' = (($env:WEBSITE_OWNER_NAME).split('+') | Select-Object -First 1)
'##TOKENIP##' = $AccessTokenDetails.IPAddress
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1
index f1f39d9bcc90..411400303392 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecNotificationConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPartnerMode.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPartnerMode.ps1
index b7a2a621fb64..a7d2ba3511bb 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPartnerMode.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPartnerMode.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecPartnerMode {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.SuperAdmin.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -29,7 +31,7 @@ Function Invoke-ExecPartnerMode {
})
}
-
+
if ($request.query.action -eq 'ListCurrent') {
$CurrentState = Get-CIPPAzDataTableEntity @Table
$CurrentState = if (!$CurrentState) {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1
index 78e27e7f01f3..9f4815e3f25d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecPasswordConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-ExecPasswordConfig {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
- $results = try {
+ $results = try {
if ($Request.Query.List) {
@{ passwordType = $PasswordType.passwordType }
} else {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1
index 0342d10f68c5..b9820352bfdd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1
@@ -3,14 +3,16 @@ using namespace System.Net
Function Invoke-ExecRestoreBackup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- try {
+ try {
foreach ($line in ($Request.body | ConvertFrom-Json | Select-Object * -ExcludeProperty ETag)) {
Write-Host ($line)
$Table = Get-CippTable -tablename $line.table
@@ -23,7 +25,7 @@ Function Invoke-ExecRestoreBackup {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Created backup' -Sev 'Debug'
$body = [pscustomobject]@{
- 'Results' = 'Succesfully restored backup.'
+ 'Results' = 'Succesfully restored backup.'
}
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create backup: $($_.Exception.Message)" -Sev 'Error'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRunBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRunBackup.ps1
index a237798e8e01..ef8d564acdca 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRunBackup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRunBackup.ps1
@@ -3,43 +3,20 @@ using namespace System.Net
Function Invoke-ExecRunBackup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- try {
- if ($request.query.Selected) {
- $BackupTables = $request.query.Selected -split ','
- } else {
- $BackupTables = @(
- 'bpa'
- 'Config'
- 'Domains'
- 'ExcludedLicenses'
- 'templates'
- 'standards'
- 'SchedulerConfig'
- )
- }
- $CSVfile = foreach ($CSVTable in $BackupTables) {
- $Table = Get-CippTable -tablename $CSVTable
- Get-CIPPAzDataTableEntity @Table | Select-Object *, @{l = 'table'; e = { $CSVTable } }
- }
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Created backup' -Sev 'Debug'
-
- $body = [pscustomobject]@{
- 'Results' = 'Created backup'
- backup = $CSVfile
- }
- } catch {
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create backup: $($_.Exception.Message)" -Sev 'Error'
- $body = [pscustomobject]@{'Results' = "Backup Creation failed: $($_.Exception.Message)" }
+ $CSVfile = New-CIPPBackup -BackupType 'CIPP'
+ $body = [pscustomobject]@{
+ 'Results' = 'Created backup'
+ backup = $CSVfile
}
-
-
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1
index 97e293d285ce..9f38b50965a0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1
@@ -3,13 +3,15 @@ using namespace System.Net
Function Invoke-ExecSAMSetup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$UserCreds = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json)
- if ($Request.query.error) {
+ if ($Request.Query.error) {
Add-Type -AssemblyName System.Web
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
ContentType = 'text/html'
@@ -59,25 +61,25 @@ Function Invoke-ExecSAMSetup {
$Rows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -GT (Get-Date).AddMinutes(-10)
try {
- if ($Request.query.count -lt 1 ) { $Results = 'No authentication code found. Please go back to the wizard.' }
+ if ($Request.Query.count -lt 1 ) { $Results = 'No authentication code found. Please go back to the wizard.' }
- if ($request.body.setkeys) {
+ if ($Request.Body.setkeys) {
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
- if ($request.body.TenantId) { $Secret.TenantId = $Request.body.tenantid }
- if ($request.body.RefreshToken) { $Secret.RefreshToken = $Request.body.RefreshToken }
- if ($request.body.applicationid) { $Secret.ApplicationId = $Request.body.ApplicationId }
- if ($request.body.ApplicationSecret) { $Secret.ApplicationSecret = $Request.body.ApplicationSecret }
+ if ($Request.Body.TenantId) { $Secret.TenantId = $Request.Body.tenantid }
+ if ($Request.Body.RefreshToken) { $Secret.RefreshToken = $Request.Body.RefreshToken }
+ if ($Request.Body.applicationid) { $Secret.ApplicationId = $Request.Body.ApplicationId }
+ if ($Request.Body.ApplicationSecret) { $Secret.ApplicationSecret = $Request.Body.ApplicationSecret }
Add-CIPPAzDataTableEntity @DevSecretsTable -Entity $Secret -Force
} else {
- if ($request.body.tenantid) { Set-AzKeyVaultSecret -VaultName $kv -Name 'tenantid' -SecretValue (ConvertTo-SecureString -String $request.body.tenantid -AsPlainText -Force) }
- if ($request.body.RefreshToken) { Set-AzKeyVaultSecret -VaultName $kv -Name 'RefreshToken' -SecretValue (ConvertTo-SecureString -String $request.body.RefreshToken -AsPlainText -Force) }
- if ($request.body.applicationid) { Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationid' -SecretValue (ConvertTo-SecureString -String $request.body.applicationid -AsPlainText -Force) }
- if ($request.body.applicationsecret) { Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -SecretValue (ConvertTo-SecureString -String $request.body.applicationsecret -AsPlainText -Force) }
+ if ($Request.Body.tenantid) { Set-AzKeyVaultSecret -VaultName $kv -Name 'tenantid' -SecretValue (ConvertTo-SecureString -String $Request.Body.tenantid -AsPlainText -Force) }
+ if ($Request.Body.RefreshToken) { Set-AzKeyVaultSecret -VaultName $kv -Name 'RefreshToken' -SecretValue (ConvertTo-SecureString -String $Request.Body.RefreshToken -AsPlainText -Force) }
+ if ($Request.Body.applicationid) { Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationid' -SecretValue (ConvertTo-SecureString -String $Request.Body.applicationid -AsPlainText -Force) }
+ if ($Request.Body.applicationsecret) { Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -SecretValue (ConvertTo-SecureString -String $Request.Body.applicationsecret -AsPlainText -Force) }
}
$Results = @{ Results = 'The keys have been replaced. Please perform a permissions check.' }
}
- if ($Request.query.error -eq 'invalid_client') { $Results = 'Client ID was not found in Azure. Try waiting 10 seconds to try again, if you have gotten this error after 5 minutes, please restart the process.' }
- if ($request.query.code) {
+ if ($Request.Query.error -eq 'invalid_client') { $Results = 'Client ID was not found in Azure. Try waiting 10 seconds to try again, if you have gotten this error after 5 minutes, please restart the process.' }
+ if ($Request.Query.code) {
try {
$TenantId = $Rows.tenantid
if (!$TenantId) { $TenantId = $ENV:TenantId }
@@ -87,10 +89,11 @@ Function Invoke-ExecSAMSetup {
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
$clientsecret = $Secret.ApplicationSecret
} else {
- $clientsecret = Get-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -AsPlainText
+ $clientsecret = Get-AzKeyVaultSecret -VaultName $kv -Name 'ApplicationSecret' -AsPlainText
}
if (!$clientsecret) { $clientsecret = $ENV:ApplicationSecret }
- $RefreshToken = Invoke-RestMethod -Method POST -Body "client_id=$appid&scope=https://graph.microsoft.com/.default+offline_access+openid+profile&code=$($request.query.code)&grant_type=authorization_code&redirect_uri=$($url)&client_secret=$clientsecret" -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
+ Write-Host "client_id=$appid&scope=https://graph.microsoft.com/.default+offline_access+openid+profile&code=$($Request.Query.code)&grant_type=authorization_code&redirect_uri=$($url)&client_secret=$clientsecret" -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
+ $RefreshToken = Invoke-RestMethod -Method POST -Body "client_id=$appid&scope=https://graph.microsoft.com/.default+offline_access+openid+profile&code=$($Request.Query.code)&grant_type=authorization_code&redirect_uri=$($url)&client_secret=$clientsecret" -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -ContentType 'application/x-www-form-urlencoded'
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
$Secret.RefreshToken = $RefreshToken.refresh_token
@@ -110,7 +113,7 @@ Function Invoke-ExecSAMSetup {
$Results = "Authentication failed. $($_.Exception.message)"
}
}
- if ($request.query.CreateSAM) {
+ if ($Request.Query.CreateSAM) {
$Rows = @{
RowKey = 'setup'
PartitionKey = 'setup'
@@ -123,7 +126,7 @@ Function Invoke-ExecSAMSetup {
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
$Rows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -GT (Get-Date).AddMinutes(-10)
- if ($Request.query.partnersetup) {
+ if ($Request.Query.partnersetup) {
$SetupPhase = $Rows.partnersetup = $true
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
}
@@ -133,46 +136,46 @@ Function Invoke-ExecSAMSetup {
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
$Results = @{ message = "Your code is $($DeviceLogon.user_code). Enter the code" ; step = $step; url = $DeviceLogon.verification_uri }
}
- if ($Request.query.CheckSetupProcess -and $request.query.step -eq 1) {
+ if ($Request.Query.CheckSetupProcess -and $Request.Query.step -eq 1) {
$SAMSetup = $Rows.SamSetup | ConvertFrom-Json -ErrorAction SilentlyContinue
$Token = (New-DeviceLogin -clientid '1b730954-1685-4b74-9bfd-dac224a7b894' -Scope 'https://graph.microsoft.com/.default' -device_code $SAMSetup.device_code)
- if ($token.Access_Token) {
+ if ($Token.access_token) {
$step = 2
$URL = ($Request.headers.'x-ms-original-url').split('?') | Select-Object -First 1
$PartnerSetup = $Rows.partnersetup
- $TenantId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/organization' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method GET -ContentType 'application/json').value.id
+ $TenantId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/organization' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method GET -ContentType 'application/json').value.id
$SetupPhase = $rows.tenantid = [string]($TenantId)
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
if ($PartnerSetup) {
$app = Get-Content '.\Cache_SAMSetup\SAMManifest.json' | ConvertFrom-Json
$App.web.redirectUris = @($App.web.redirectUris + $URL)
$app = $app | ConvertTo-Json -Depth 15
- $AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body $app -ContentType 'application/json')
+ $AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body $app -ContentType 'application/json')
$rows.appid = [string]($AppId.appId)
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
$attempt = 0
do {
try {
try {
- $SPNDefender = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body "{ `"appId`": `"fc780465-2017-40d4-a0c5-307022471b92`" }" -ContentType 'application/json')
+ $SPNDefender = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body "{ `"appId`": `"fc780465-2017-40d4-a0c5-307022471b92`" }" -ContentType 'application/json')
} catch {
Write-Host "didn't deploy spn for defender, probably already there."
}
try {
- $SPNTeams = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body "{ `"appId`": `"48ac35b8-9aa8-4d74-927d-1f4a14a0b239`" }" -ContentType 'application/json')
+ $SPNTeams = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body "{ `"appId`": `"48ac35b8-9aa8-4d74-927d-1f4a14a0b239`" }" -ContentType 'application/json')
} catch {
Write-Host "didn't deploy spn for Teams, probably already there."
}
try {
- $SPNPartnerCenter = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body "{ `"appId`": `"fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd`" }" -ContentType 'application/json')
+ $SPNPartnerCenter = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body "{ `"appId`": `"fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd`" }" -ContentType 'application/json')
} catch {
Write-Host "didn't deploy spn for PartnerCenter, probably already there."
}
- $SPN = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body "{ `"appId`": `"$($AppId.appId)`" }" -ContentType 'application/json')
+ $SPN = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/servicePrincipals' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body "{ `"appId`": `"$($AppId.appId)`" }" -ContentType 'application/json')
Start-Sleep 3
- $GroupID = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/groups?`$filter=startswith(displayName,'AdminAgents')" -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method Get -ContentType 'application/json').value.id
+ $GroupID = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/groups?`$filter=startswith(displayName,'AdminAgents')" -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method Get -ContentType 'application/json').value.id
Write-Host "Id is $GroupID"
- $AddingToAdminAgent = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/groups/$($GroupID)/members/`$ref" -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body "{ `"@odata.id`": `"https://graph.microsoft.com/v1.0/directoryObjects/$($SPN.id)`"}" -ContentType 'application/json')
+ $AddingToAdminAgent = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/groups/$($GroupID)/members/`$ref" -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body "{ `"@odata.id`": `"https://graph.microsoft.com/v1.0/directoryObjects/$($SPN.id)`"}" -ContentType 'application/json')
Write-Host 'Added to adminagents'
$attempt ++
} catch {
@@ -181,21 +184,22 @@ Function Invoke-ExecSAMSetup {
} until ($attempt -gt 5)
} else {
$app = Get-Content '.\Cache_SAMSetup\SAMManifestNoPartner.json'
- $AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body $app -ContentType 'application/json')
- $rows.appid = [string]($AppId.appId)
+ $AppId = (Invoke-RestMethod 'https://graph.microsoft.com/v1.0/applications' -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body $app -ContentType 'application/json')
+ $Rows.appid = [string]($AppId.appId)
Add-CIPPAzDataTableEntity @Table -Entity $Rows -Force | Out-Null
}
- $AppPassword = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/applications/$($AppID.id)/addPassword" -Headers @{ authorization = "Bearer $($Token.Access_Token)" } -Method POST -Body '{"passwordCredential":{"displayName":"CIPPInstall"}}' -ContentType 'application/json').secretText
+ $AppPassword = (Invoke-RestMethod "https://graph.microsoft.com/v1.0/applications/$($AppId.id)/addPassword" -Headers @{ authorization = "Bearer $($Token.access_token)" } -Method POST -Body '{"passwordCredential":{"displayName":"CIPPInstall"}}' -ContentType 'application/json').secretText
if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
- $Secret.TenantId = $Request.body.tenantid
- $Secret.ApplicationId = $Request.body.ApplicationId
- $Secret.ApplicationSecret = $Request.body.ApplicationSecret
+ $Secret.TenantId = $TenantId
+ $Secret.ApplicationId = $AppId.appId
+ $Secret.ApplicationSecret = $AppPassword
Add-CIPPAzDataTableEntity @DevSecretsTable -Entity $Secret -Force
+ Write-Information ($Secret | ConvertTo-Json -Depth 5)
} else {
Set-AzKeyVaultSecret -VaultName $kv -Name 'tenantid' -SecretValue (ConvertTo-SecureString -String $TenantId -AsPlainText -Force)
- Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationid' -SecretValue (ConvertTo-SecureString -String $Appid.appid -AsPlainText -Force)
+ Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationid' -SecretValue (ConvertTo-SecureString -String $Appid.appId -AsPlainText -Force)
Set-AzKeyVaultSecret -VaultName $kv -Name 'applicationsecret' -SecretValue (ConvertTo-SecureString -String $AppPassword -AsPlainText -Force)
}
$Results = @{'message' = 'Created application. Waiting 30 seconds for Azure propagation'; step = $step }
@@ -205,7 +209,7 @@ Function Invoke-ExecSAMSetup {
}
}
- switch ($request.query.step) {
+ switch ($Request.Query.step) {
2 {
$step = 2
$TenantId = $Rows.tenantid
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1
index ebd0d9be935b..c52e2e60ffbd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddContact {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Contact.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -31,8 +33,7 @@ Function Invoke-AddContact {
$body = [pscustomobject]@{'Results' = 'Successfully added a contact.' }
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "Created contact $($contactobj.displayname) with id $($GraphRequest.id) for " -Sev 'Info'
- }
- catch {
+ } catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($contactobj.tenantid) -message "Contact creation API failed. $($_.Exception.Message)" -Sev 'Error'
$body = [pscustomobject]@{'Results' = "Failed to create contact. $($_.Exception.Message)" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1
index b3246cea773d..d1a29a85a67d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddExConnector {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -17,7 +19,7 @@ Function Invoke-AddExConnector {
$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value
$Result = foreach ($Tenantfilter in $tenants) {
try {
- $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams
+ $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams
"Successfully created Connector for $Tenantfilter."
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Tenantfilter -message "Created Connector for $($Tenantfilter)" -sev 'Info'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1
index 73cf56b8d910..222c01f420ff 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddExConnectorTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -15,8 +17,8 @@ Function Invoke-AddExConnectorTemplate {
try {
$GUID = (New-Guid).GUID
- $Select = if ($Request.body.cippconnectortype -eq 'outbound') {
- @(
+ $Select = if ($Request.body.cippconnectortype -eq 'outbound') {
+ @(
'name', 'AllAcceptedDomains', 'CloudServicesMailEnabled', 'Comment', 'Confirm', 'ConnectorSource', 'ConnectorType', 'Enabled', 'IsTransportRuleScoped', 'RecipientDomains', 'RouteAllMessagesViaOnPremises', 'SenderRewritingEnabled', 'SmartHosts', 'TestMode', 'TlsDomain', 'TlsSettings', 'UseMXRecord'
)
}
@@ -28,7 +30,7 @@ Function Invoke-AddExConnectorTemplate {
$JSON = ([pscustomobject]$Request.body | Select-Object $Select) | ForEach-Object {
$NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name
- $_ | Select-Object -Property $NonEmptyProperties
+ $_ | Select-Object -Property $NonEmptyProperties
}
$JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, * | ConvertTo-Json -Depth 10)
$Table = Get-CippTable -tablename 'templates'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1
index c3017c7cf881..20af9ebdd475 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddSharedMailbox {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -40,7 +42,7 @@ Function Invoke-AddSharedMailbox {
try {
if ($Aliases) {
-
+
Start-Sleep 3 # Sleep since there is apparently a race condition with the mailbox creation if we don't delay for a lil bit
$AliasBodyToShip = [pscustomobject] @{
'Identity' = $AddSharedRequest.Guid
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1
index 789b3eaffe9d..deb78b344897 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1
@@ -3,12 +3,14 @@ using namespace System.Net
Function Invoke-AddSpamFilter {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
+
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1
index 9aeef51f243c..37cf34b88916 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddSpamFilterTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Spamfilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,7 +14,7 @@ Function Invoke-AddSpamFilterTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
Write-Host ($request | ConvertTo-Json -Compress)
- try {
+ try {
$GUID = (New-Guid).GUID
$JSON = if ($request.body.PowerShellCommand) {
Write-Host 'PowerShellCommand'
@@ -21,7 +23,7 @@ Function Invoke-AddSpamFilterTemplate {
else {
([pscustomobject]$Request.body | Select-Object name, AddXHeaderValue, AdminDisplayName, AllowedSenderDomains, AllowedSenders, BlockedSenderDomains, BlockedSenders, BulkQuarantineTag, BulkSpamAction, BulkThreshold, Confirm, DownloadLink, EnableEndUserSpamNotifications, EnableLanguageBlockList, EnableRegionBlockList, EndUserSpamNotificationCustomFromAddress, EndUserSpamNotificationCustomFromName, EndUserSpamNotificationCustomSubject, EndUserSpamNotificationFrequency, EndUserSpamNotificationLanguage, EndUserSpamNotificationLimit, HighConfidencePhishAction, HighConfidencePhishQuarantineTag, HighConfidenceSpamAction, HighConfidenceSpamQuarantineTag, IncreaseScoreWithBizOrInfoUrls, IncreaseScoreWithImageLinks, IncreaseScoreWithNumericIps, IncreaseScoreWithRedirectToOtherPort, InlineSafetyTipsEnabled, LanguageBlockList, MarkAsSpamBulkMail, MarkAsSpamEmbedTagsInHtml, MarkAsSpamEmptyMessages, MarkAsSpamFormTagsInHtml, MarkAsSpamFramesInHtml, MarkAsSpamFromAddressAuthFail, MarkAsSpamJavaScriptInHtml, MarkAsSpamNdrBackscatter, MarkAsSpamObjectTagsInHtml, MarkAsSpamSensitiveWordList, MarkAsSpamSpfRecordHardFail, MarkAsSpamWebBugsInHtml, ModifySubjectValue, PhishQuarantineTag, PhishSpamAction, PhishZapEnabled, QuarantineRetentionPeriod, RecommendedPolicyType, RedirectToRecipients, RegionBlockList, SpamAction, SpamQuarantineTag, SpamZapEnabled, TestModeAction, TestModeBccToRecipients ) | ForEach-Object {
$NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name
- $_ | Select-Object -Property $NonEmptyProperties
+ $_ | Select-Object -Property $NonEmptyProperties
}
}
$JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10)
@@ -34,7 +36,7 @@ Function Invoke-AddSpamFilterTemplate {
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Spam Filter Template $($Request.body.name) with GUID $GUID" -Sev 'Debug'
$body = [pscustomobject]@{'Results' = 'Successfully added template' }
-
+
}
catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Spam Filter Template: $($_.Exception.Message)" -Sev 'Error'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1
index 64c394ee2852..acd265572aa5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddTransportRule {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,7 +13,7 @@ Function Invoke-AddTransportRule {
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications
+ $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications
$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value
$Result = foreach ($Tenantfilter in $tenants) {
@@ -28,7 +30,7 @@ Function Invoke-AddTransportRule {
$GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-TransportRule' -cmdParams $RequestParams -useSystemMailbox $true
"Successfully created transport rule for $tenantfilter."
}
-
+
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Created transport rule for $($tenantfilter)" -sev Info
}
catch {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1
index 6028c15578b6..0f7fb738e6ff 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddTransportTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,7 +14,7 @@ Function Invoke-AddTransportTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
Write-Host ($request | ConvertTo-Json -Compress)
- try {
+ try {
$GUID = (New-Guid).GUID
$JSON = if ($request.body.PowerShellCommand) {
Write-Host 'PowerShellCommand'
@@ -21,7 +23,7 @@ Function Invoke-AddTransportTemplate {
else {
([pscustomobject]$Request.body | Select-Object Name, ActivationDate, ADComparisonAttribute, ADComparisonOperator, AddManagerAsRecipientType, AddToRecipients, AnyOfCcHeader, AnyOfCcHeaderMemberOf, AnyOfRecipientAddressContainsWords, AnyOfRecipientAddressMatchesPatterns, AnyOfToCcHeader, AnyOfToCcHeaderMemberOf, AnyOfToHeader, AnyOfToHeaderMemberOf, ApplyClassification, ApplyHtmlDisclaimerFallbackAction, ApplyHtmlDisclaimerLocation, ApplyHtmlDisclaimerText, ApplyOME, ApplyRightsProtectionCustomizationTemplate, ApplyRightsProtectionTemplate, AttachmentContainsWords, AttachmentExtensionMatchesWords, AttachmentHasExecutableContent, AttachmentIsPasswordProtected, AttachmentIsUnsupported, AttachmentMatchesPatterns, AttachmentNameMatchesPatterns, AttachmentProcessingLimitExceeded, AttachmentPropertyContainsWords, AttachmentSizeOver, BetweenMemberOf1, BetweenMemberOf2, BlindCopyTo, Comments, Confirm, ContentCharacterSetContainsWords, CopyTo, DeleteMessage, DlpPolicy, DomainController, Enabled, ExceptIfADComparisonAttribute, ExceptIfADComparisonOperator, ExceptIfAnyOfCcHeader, ExceptIfAnyOfCcHeaderMemberOf, ExceptIfAnyOfRecipientAddressContainsWords, ExceptIfAnyOfRecipientAddressMatchesPatterns, ExceptIfAnyOfToCcHeader, ExceptIfAnyOfToCcHeaderMemberOf, ExceptIfAnyOfToHeader, ExceptIfAnyOfToHeaderMemberOf, ExceptIfAttachmentContainsWords, ExceptIfAttachmentExtensionMatchesWords, ExceptIfAttachmentHasExecutableContent, ExceptIfAttachmentIsPasswordProtected, ExceptIfAttachmentIsUnsupported, ExceptIfAttachmentMatchesPatterns, ExceptIfAttachmentNameMatchesPatterns, ExceptIfAttachmentProcessingLimitExceeded, ExceptIfAttachmentPropertyContainsWords, ExceptIfAttachmentSizeOver, ExceptIfBetweenMemberOf1, ExceptIfBetweenMemberOf2, ExceptIfContentCharacterSetContainsWords, ExceptIfFrom, ExceptIfFromAddressContainsWords, ExceptIfFromAddressMatchesPatterns, ExceptIfFromMemberOf, ExceptIfFromScope, ExceptIfHasClassification, ExceptIfHasNoClassification, ExceptIfHasSenderOverride, ExceptIfHeaderContainsMessageHeader, ExceptIfHeaderContainsWords, ExceptIfHeaderMatchesMessageHeader, ExceptIfHeaderMatchesPatterns, ExceptIfManagerAddresses, ExceptIfManagerForEvaluatedUser, ExceptIfMessageContainsDataClassifications, ExceptIfMessageSizeOver, ExceptIfMessageTypeMatches, ExceptIfRecipientADAttributeContainsWords, ExceptIfRecipientADAttributeMatchesPatterns, ExceptIfRecipientAddressContainsWords, ExceptIfRecipientAddressMatchesPatterns, ExceptIfRecipientDomainIs, ExceptIfRecipientInSenderList, ExceptIfSCLOver, ExceptIfSenderADAttributeContainsWords, ExceptIfSenderADAttributeMatchesPatterns, ExceptIfSenderDomainIs, ExceptIfSenderInRecipientList, ExceptIfSenderIpRanges, ExceptIfSenderManagementRelationship, ExceptIfSentTo, ExceptIfSentToMemberOf, ExceptIfSentToScope, ExceptIfSubjectContainsWords, ExceptIfSubjectMatchesPatterns, ExceptIfSubjectOrBodyContainsWords, ExceptIfSubjectOrBodyMatchesPatterns, ExceptIfWithImportance, ExpiryDate, From, FromAddressContainsWords, FromAddressMatchesPatterns, FromMemberOf, FromScope, GenerateIncidentReport, GenerateNotification, HasClassification, HasNoClassification, HasSenderOverride, HeaderContainsMessageHeader, HeaderContainsWords, HeaderMatchesMessageHeader, HeaderMatchesPatterns, IncidentReportContent, IncidentReportOriginalMail, LogEventText, ManagerAddresses, ManagerForEvaluatedUser, MessageContainsDataClassifications, MessageSizeOver, MessageTypeMatches, Mode, ModerateMessageByManager, ModerateMessageByUser, NotifySender, PrependSubject, Quarantine, RecipientADAttributeContainsWords, RecipientADAttributeMatchesPatterns, RecipientAddressContainsWords, RecipientAddressMatchesPatterns, RecipientAddressType, RecipientDomainIs, RecipientInSenderList, RedirectMessageTo, RejectMessageEnhancedStatusCode, RejectMessageReasonText, RemoveHeader, RemoveOME, RemoveOMEv2, RemoveRMSAttachmentEncryption, RouteMessageOutboundConnector, RouteMessageOutboundRequireTls, RuleErrorAction, RuleSubType, SCLOver, SenderADAttributeContainsWords, SenderADAttributeMatchesPatterns, SenderAddressLocation, SenderDomainIs, SenderInRecipientList, SenderIpRanges, SenderManagementRelationship, SentTo, SentToMemberOf, SentToScope, SetAuditSeverity, SetHeaderName, SetHeaderValue, SetSCL, SmtpRejectMessageRejectStatusCode, SmtpRejectMessageRejectText, StopRuleProcessing, SubjectContainsWords, SubjectMatchesPatterns, SubjectOrBodyContainsWords, SubjectOrBodyMatchesPatterns, UseLegacyRegex, WithImportance ) | ForEach-Object {
$NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name
- $_ | Select-Object -Property $NonEmptyProperties
+ $_ | Select-Object -Property $NonEmptyProperties
}
}
$JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10)
@@ -34,7 +36,7 @@ Function Invoke-AddTransportTemplate {
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created Transport Rule Template $($Request.body.name) with GUID $GUID" -Sev 'Debug'
$body = [pscustomobject]@{'Results' = 'Successfully added template' }
-
+
}
catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create Transport Rule Template: $($_.Exception.Message)" -Sev 'Error'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1
index 9042e7fdfa0a..b1c622f621fd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditExConnector {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1
index 9f98d280f511..931299cb6102 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditSpamFilter {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,13 +20,12 @@ Function Invoke-EditSpamFilter {
try {
$cmdlet = if ($request.query.state -eq 'enable') { 'Enable-HostedContentFilterRule' } else { 'Disable-HostedContentFilterRule' }
- $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params
+ $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true
$Result = "Set Spamfilter rule to $($request.query.State)"
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Set Spamfilter rule $($Request.query.name) to $($request.query.State)" -sev Info
- }
- catch {
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Failed setting Spamfilter rule $($Request.query.guid) to $($request.query.State). Error:$($_.Exception.Message)" -Sev 'Error'
- $ErrorMessage = Get-NormalizedError -Message $_.Exception
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantfilter -message "Failed setting Spamfilter rule $($Request.query.guid) to $($request.query.State). Error:$ErrorMessage" -Sev 'Error'
$Result = $ErrorMessage
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1
index 20f93fd4014f..8d968077db70 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditTransportRule {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1
index cb16432e8937..ed59a074c1ac 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecConverttoSharedMailbox {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1
index a039be57dfba..4aadbd74c563 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecCopyForSent {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecDisableEmailForward.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecDisableEmailForward.ps1
index 12c57868e68d..d2894b583ee4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecDisableEmailForward.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecDisableEmailForward.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecDisableEmailForward {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1
index 346deef09dcc..eebb7139649d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecEditCalendarPermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1
index 97200abfc763..d017f8ae65a4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecEditMailboxPermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -17,11 +19,11 @@ Function Invoke-ExecEditMailboxPermissions {
$Results = [System.Collections.ArrayList]@()
$RemoveFullAccess = ($Request.body.RemoveFullAccess).value
- foreach ($RemoveUser in $RemoveFullAccess) {
+ foreach ($RemoveUser in $RemoveFullAccess) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Remove-mailboxpermission' -cmdParams @{Identity = $userid; user = $RemoveUser; accessRights = @('FullAccess'); }
$results.add("Removed $($removeuser) from $($username) Shared Mailbox permissions")
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME-message "Removed $($RemoveUser) from $($username) Shared Mailbox permission" -Sev 'Info' -tenant $TenantFilter
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME-message "Removed $($RemoveUser) from $($username) Shared Mailbox permission" -Sev 'Info' -tenant $TenantFilter
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME-message "Could not remove mailbox permissions for $($removeuser) on $($username)" -Sev 'Error' -tenant $TenantFilter
$results.add("Could not remove $($removeuser) shared mailbox permissions for $($username). Error: $($_.Exception.Message)")
@@ -29,7 +31,7 @@ Function Invoke-ExecEditMailboxPermissions {
}
$AddFullAccess = ($Request.body.AddFullAccess).value
- foreach ($UserAutomap in $AddFullAccess) {
+ foreach ($UserAutomap in $AddFullAccess) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Add-MailboxPermission' -cmdParams @{Identity = $userid; user = $UserAutomap; accessRights = @('FullAccess'); automapping = $true }
$results.add( "Granted $($UserAutomap) access to $($username) Mailbox with automapping")
@@ -42,7 +44,7 @@ Function Invoke-ExecEditMailboxPermissions {
}
$AddFullAccessNoAutoMap = ($Request.body.AddFullAccessNoAutoMap).value
- foreach ($UserNoAutomap in $AddFullAccessNoAutoMap) {
+ foreach ($UserNoAutomap in $AddFullAccessNoAutoMap) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Add-MailboxPermission' -cmdParams @{Identity = $userid; user = $UserNoAutomap; accessRights = @('FullAccess'); automapping = $false }
$results.add( "Granted $UserNoAutomap access to $($username) Mailbox without automapping")
@@ -55,7 +57,7 @@ Function Invoke-ExecEditMailboxPermissions {
$AddSendAS = ($Request.body.AddSendAs).value
- foreach ($UserSendAs in $AddSendAS) {
+ foreach ($UserSendAs in $AddSendAS) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Add-RecipientPermission' -cmdParams @{Identity = $userid; Trustee = $UserSendAs; accessRights = @('SendAs') }
$results.add( "Granted $UserSendAs access to $($username) with Send As permissions")
@@ -68,7 +70,7 @@ Function Invoke-ExecEditMailboxPermissions {
$RemoveSendAs = ($Request.body.RemoveSendAs).value
- foreach ($UserSendAs in $RemoveSendAs) {
+ foreach ($UserSendAs in $RemoveSendAs) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Remove-RecipientPermission' -cmdParams @{Identity = $userid; Trustee = $UserSendAs; accessRights = @('SendAs') }
$results.add( "Removed $UserSendAs from $($username) with Send As permissions")
@@ -81,7 +83,7 @@ Function Invoke-ExecEditMailboxPermissions {
$AddSendOnBehalf = ($Request.body.AddSendOnBehalf).value
- foreach ($UserSendOnBehalf in $AddSendOnBehalf) {
+ foreach ($UserSendOnBehalf in $AddSendOnBehalf) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; add = $UserSendOnBehalf }; }
$results.add( "Granted $UserSendOnBehalf access to $($username) with Send On Behalf Permissions")
@@ -94,7 +96,7 @@ Function Invoke-ExecEditMailboxPermissions {
$RemoveSendOnBehalf = ($Request.body.RemoveSendOnBehalf).value
- foreach ($UserSendOnBehalf in $RemoveSendOnBehalf) {
+ foreach ($UserSendOnBehalf in $RemoveSendOnBehalf) {
try {
$MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $UserSendOnBehalf }; }
$results.add( "Removed $UserSendOnBehalf from $($username) Send on Behalf Permissions")
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1
index f9b05a8f662a..9ddf5aa7b523 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecEmailForward {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -23,12 +25,12 @@ Function Invoke-ExecEmailForward {
$results = "Forwarding all email for $($username) to $($ForwardingAddress) and not keeping a copy"
} elseif ($request.body.KeepCopy) {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Set Forwarding for $($username) to $($ForwardingAddress) and keeping a copy" -Sev 'Info' -tenant $TenantFilter
- $results = "Forwarding all email for $($username) to $($ForwardingAddress) and keeping a copy"
+ $results = "Forwarding all email for $($username) to $($ForwardingAddress) and keeping a copy"
}
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not add forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter
$results = "Could not add forwarding for $($username). Error: $($_.Exception.Message)"
-
+
}
}
@@ -40,12 +42,12 @@ Function Invoke-ExecEmailForward {
$results = "Forwarding all email for $($username) to $($ForwardingSMTPAddress) and not keeping a copy"
} elseif ($request.body.KeepCopy) {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Set forwarding for $($username) to $($ForwardingSMTPAddress) and keeping a copy" -Sev 'Info' -tenant $TenantFilter
- $results = "Forwarding all email for $($username) to $($ForwardingSMTPAddress) and keeping a copy"
+ $results = "Forwarding all email for $($username) to $($ForwardingSMTPAddress) and keeping a copy"
}
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not add forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter
$results = "Could not add forwarding for $($username). Error: $($_.Exception.Message)"
-
+
}
}
@@ -58,7 +60,7 @@ Function Invoke-ExecEmailForward {
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not disable Email forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter
$results = "Could not disable Email forwarding for $($username). Error: $($_.Exception.Message)"
-
+
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1
index ac4cf5f8686b..f1dfb475b1cd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecEnableArchive {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1
index c4f5be9d67f7..d66af4964171 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGroupsDelete {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1
index d77c8a56d6e7..1f096507bd61 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGroupsDeliveryManagement {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,7 +20,7 @@ Function Invoke-ExecGroupsDeliveryManagement {
# Interact with query parameters or the body of the request.
Try {
- $SetResults = Set-CIPPGroupAuthentication -ID $Request.query.id -GroupType $Request.query.GroupType -OnlyAllowInternalString $Request.query.OnlyAllowInternal -tenantFilter $Request.query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ $SetResults = Set-CIPPGroupAuthentication -ID $Request.query.id -GroupType $Request.query.GroupType -OnlyAllowInternalString $Request.query.OnlyAllowInternal -tenantFilter $Request.query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
$Results = [pscustomobject]@{'Results' = $SetResults }
} catch {
$Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1
index 6307f2ef898d..caf559918240 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGroupsHideFromGAL {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -13,7 +15,7 @@ Function Invoke-ExecGroupsHideFromGAL {
# Interact with query parameters or the body of the request.
Try {
- $GroupStatus = Set-CIPPGroupGAL -Id $Request.query.id -tenantFilter $Request.query.TenantFilter -GroupType $Request.query.groupType -HiddenString $Request.query.HidefromGAL -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ $GroupStatus = Set-CIPPGroupGAL -Id $Request.query.id -tenantFilter $Request.query.TenantFilter -GroupType $Request.query.groupType -HiddenString $Request.query.HidefromGAL -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
$Results = [pscustomobject]@{'Results' = $GroupStatus }
} catch {
$Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1
index 787bdd798e36..7dac7da9c2fd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecHideFromGAL {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1
index 483594d83889..a80a812b45d6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1
@@ -2,7 +2,9 @@ using namespace System.Net
Function Invoke-ExecMailTest {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1
index 15f96d33503a..7b58b76afc7c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecMailboxMobileDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1
index 8dc0bf5981f6..fb66074d979d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1
@@ -1,7 +1,9 @@
function Invoke-ExecMailboxRestore {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
Param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1
index 7f85df715207..e22301a7629c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecQuarantineManagement {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,9 +20,9 @@ Function Invoke-ExecQuarantineManagement {
# Interact with query parameters or the body of the request.
Try {
- $tenantfilter = $Request.Query.TenantFilter
+ $tenantfilter = $Request.Query.TenantFilter
$params = @{
- Identity = $request.query.ID
+ Identity = $request.query.ID
AllowSender = [boolean]$Request.query.AllowSender
ReleasetoAll = [boolean]$Request.query.type
ActionType = $Request.query.type
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1
index f2059365139c..a55f1a420a1b 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSetMailboxQuota {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1
index c0a004791254..fab2212d888c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSetOoO {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1
index 4b1a1c68b57f..fcdf05d199fb 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailQuarantine {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1
index 5ec6203892c4..25a5e57b1e59 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMessageTrace {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,10 +20,10 @@ Function Invoke-ListMessageTrace {
StartDate = (Get-Date).AddDays( - $($request.query.days)).ToString('s')
EndDate = (Get-Date).ToString('s')
}
-
+
if ($null -ne $request.query.recipient) { $Searchparams.Add('RecipientAddress', $($request.query.recipient)) }
if ($null -ne $request.query.sender) { $Searchparams.Add('SenderAddress', $($request.query.sender)) }
- $type = $request.query.Tracedetail
+ $type = $request.query.Tracedetail
$trace = if ($Request.Query.Tracedetail) {
New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MessageTraceDetail' -cmdParams $Searchparams
Get-MessageTraceDetail -MessageTraceId $Request.Query.ID -RecipientAddress $request.query.recipient -erroraction stop | Select-Object Event, Action, Detail, @{ Name = 'Date'; Expression = { $_.Date.Tostring('s') } }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1
index b83c74d7dd42..dc3a35d2201c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListOoO {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListPhishPolicies.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListPhishPolicies.ps1
index 1b3d767f85fd..28e46a3b88c4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListPhishPolicies.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListPhishPolicies.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListPhishPolicies {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1
index 29bc8bd8a01a..e995daa9231c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListRecipients {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -26,9 +28,9 @@ Function Invoke-ListRecipients {
Select = $select
}
- $GraphRequest = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid,
- @{ Name = 'UPN'; Expression = { $_.'PrimarySmtpAddress' } },
- @{ Name = 'mail'; Expression = { $_.'PrimarySmtpAddress' } },
+ $GraphRequest = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid,
+ @{ Name = 'UPN'; Expression = { $_.'PrimarySmtpAddress' } },
+ @{ Name = 'mail'; Expression = { $_.'PrimarySmtpAddress' } },
@{ Name = 'displayName'; Expression = { $_.'DisplayName' } }
$StatusCode = [HttpStatusCode]::OK
} catch {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1
index 9782073ffb25..e38c63bbedbf 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSpamFilterTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,12 +16,12 @@ Function Invoke-ListSpamFilterTemplates {
#List new policies
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'SpamfilterTemplate'"
+ $Filter = "PartitionKey eq 'SpamfilterTemplate'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
$GUID = $_.RowKey
- $data = $_.JSON | ConvertFrom-Json
+ $data = $_.JSON | ConvertFrom-Json
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $GUID
- $data
+ $data
}
if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property RowKey -EQ $Request.query.id }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1
index 3e705b9f46a5..cb58d1a378f2 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSpamfilter {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1
index 18e9fb3959d2..283afe12e1ee 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTransportRules {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1
index 1c42c21d9470..31fe9e6b04a9 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTransportRulesTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -13,7 +15,7 @@ Function Invoke-ListTransportRulesTemplates {
$Table = Get-CippTable -tablename 'templates'
$Templates = Get-ChildItem 'Config\*.TransportRuleTemplate.json' | ForEach-Object {
-
+
$Entity = @{
JSON = "$(Get-Content $_)"
RowKey = "$($_.name)"
@@ -26,12 +28,12 @@ Function Invoke-ListTransportRulesTemplates {
#List new policies
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'TransportTemplate'"
+ $Filter = "PartitionKey eq 'TransportTemplate'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
$GUID = $_.RowKey
- $data = $_.JSON | ConvertFrom-Json
+ $data = $_.JSON | ConvertFrom-Json
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $GUID
- $data
+ $data
}
if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property RowKey -EQ $Request.query.id }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1
index 7c94dbe33d81..f554fd228f7b 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddChocoApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1
index 5ecd0a49fcb9..663a490927e9 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddMSPApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -21,37 +23,37 @@ Function Invoke-AddMSPApp {
$Results = foreach ($Tenant in $tenants) {
$InstallParams = [pscustomobject]$RMMApp.params
switch ($rmmapp.RMMName.value) {
- 'datto' {
+ 'datto' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.DattoURL) -GUID $($InstallParams.DattoGUID["$($tenant.customerId)"])"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
- 'ninja' {
+ 'ninja' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
- 'Huntress' {
+ 'Huntress' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -OrgKey $($InstallParams.Orgkey["$($tenant.customerId)"]) -acctkey $($InstallParams.AccountKey)"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\install.ps1 -Uninstall'
}
- 'Immybot' {
+ 'Immybot' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -url $($InstallParams.ClientURL["$($tenant.customerId)"])"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
- 'syncro' {
+ 'syncro' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.ClientURL["$($tenant.customerId)"])"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
- 'NCentral' {
+ 'NCentral' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
- 'automate' {
+ 'automate' {
$installcommandline = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\install.ps1 -Server $($InstallParams.Server) -InstallerToken $($InstallParams.InstallerToken["$($tenant.customerId)"]) -LocationID $($InstallParams.LocationID["$($tenant.customerId)"])"
$UninstallCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\uninstall.ps1 -Server $($InstallParams.Server)"
$DetectionScript = (Get-Content 'AddMSPApp\automate.detection.ps1' -Raw) -replace '##SERVER##', $InstallParams.Server
$intuneBody.detectionRules[0].scriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($DetectionScript))
}
- 'cwcommand' {
+ 'cwcommand' {
$installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -Url $($InstallParams.ClientURL["$($tenant.customerId)"])"
$UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1
index 865449257a89..e5a73e7dcb6c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddOfficeApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -61,14 +63,14 @@ Function Invoke-AddOfficeApp {
'updateChannel' = $request.body.updateChannel.value
'useSharedComputerActivation' = [bool]$request.body.SharedComputerActivation
'productIds' = $products
- 'largeIcon' = @{
+ 'largeIcon' = @{
'type' = 'image/png'
'value' = 'iVBORw0KGgoAAAANSUhEUgAAAF0AAAAeCAMAAAEOZNKlAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJhUExURf////7z7/i9qfF1S/KCW/i+qv3q5P/9/PrQwfOMae1RG+s8AOxGDfBtQPWhhPvUx/759/zg1vWgg+9fLu5WIvKFX/rSxP728/nCr/FyR+tBBvOMaO1UH+1RHOs+AvSScP3u6f/+/v3s5vzg1+xFDO9kNPOOa/i7pvzj2/vWyes9Af76+Pzh2PrTxf/6+f7y7vOGYexHDv3t5+1SHfi8qPOIZPvb0O1NFuxDCe9hMPSVdPnFs/3q4/vaz/STcu5VIe5YJPWcfv718v/9/e1MFfF4T/F4TvF2TP3o4exECvF0SexIEPONavzn3/vZze1QGvF3Te5dK+5cKvrPwPrQwvKAWe1OGPexmexKEveulfezm/BxRfamiuxLE/apj/zf1e5YJfSXd/OHYv3r5feznPakiPze1P7x7f739f3w6+xJEfnEsvWdf/Wfge1LFPe1nu9iMvnDsfBqPOs/BPOIY/WZevJ/V/zl3fnIt/vTxuxHD+xEC+9mN+5ZJv749vBpO/KBWvBwRP/8+/SUc/etlPjArP/7+vOLZ/F7UvWae/708e1OF/aihvSWdvi8p+tABfSZefvVyPWihfSVde9lNvami+9jM/zi2fKEXvBuQvOKZvalifF5UPJ/WPSPbe9eLfrKuvvd0uxBB/7w7Pzj2vrRw/rOv+1PGfi/q/eymu5bKf3n4PnJuPBrPf3t6PWfgvWegOxCCO9nOO9oOfaskvSYePi5pPi2oPnGtO5eLPevlvKDXfrNvv739Pzd0/708O9gL+9lNfJ9VfrLu/OPbPnDsPBrPus+A/nArfarkQAAAGr5HKgAAADLdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AvuakogAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAz5JREFUOE+tVTtu4zAQHQjppmWzwIJbEVCzpTpjbxD3grQHSOXKRXgCAT6EC7UBVAmp3KwBnmvfzNCyZTmxgeTZJsXx43B+HBHRE34ZkXgkerXFTheeiCkRrbB4UXmp4wSWz5raaQEMTM5TZwuiXoaKgV+6FsmkZQcSy0kA71yMTMGHanX+AzMMGLAQCxU1F/ZwjULPugazl82GM0NEKm/U8EqFwEkO3/EAT4grgl0nucwlk9pcpTTJ4VPA4g/Rb3yIRhhp507e9nTQmZ1OS5RO4sS7nIRPEeHXCHdkw9ZEW2yVE5oIS7peD58Avs7CN+PVCmHh21oOqBdjDzIs+FldPJ74TFESUSJEfVzy9U/dhu+AuOT6eBp6gGKyXEx8euO450ZE4CMfstMFT44broWw/itkYErWXRx+fFArt9Ca9os78TFed0LVIUsmIHrwbwaw3BEOnOk94qVpQ6Ka2HjxewJnfyd6jUtGDQLdWlzmYNYLeKbbGOucJsNabCq1Yub0o92rtR+i30V2dapxYVEePXcOjeCKPnYyit7BtKeNlZqHbr+gt7i+AChWA9RsRs03pxTQc67ouWpxyESvjK5Vs3DVSy3IpkxPm5X+wZoBi+MFHWW69/w8FRhc7VBe6HAhMB2b8Q0XqDzTNZtXUMnKMjwKVaCrB/CSUL7WSx/HsdJC86lFGXwnioTeOMPjV+szlFvrZLA5VMVK4y+41l4e1xfx7Z88o4hkilRUH/qKqwNVlgDgpvYCpH3XwAy5eMCRnezIUxffVXoDql2rTHFDO+pjWnTWzAfrYXn6BFECblUpWGrvPZvBipETjS5ydM7tdXpH41ZCEbBNy/+wFZu71QO2t9pgT+iZEf657Q1vpN94PQNDxUHeKR103LV9nPVOtDikcNKO+2naCw7yKBhOe9Hm79pe8C4/CfC2wDjXnqC94kEeBU3WwN7dt/2UScXas7zDl5GpkY+M8WKv2J7fd4Ib2rGTk+jsC2cleEM7jI9veF7B0MBJrsZqfKd/81q9pR2NZfwJK2JzsmIT1Ns8jUH0UusQBpU8d2JzsHiXg1zXGLqxfitUNTDT/nUUeqDBp2HZVr+Ocqi/Ty3Rf4Jn82xxfSNtAAAAAElFTkSuQmCC'
}
}
Write-Host ($ObjBody | ConvertTo-Json -Compress)
$OfficeAppID = New-graphPostRequest -Uri 'https://graph.microsoft.com/beta/deviceAppManagement/mobileApps' -tenantid $tenant -Body (ConvertTo-Json -InputObject $ObjBody -Depth 10) -type POST
- } else {
+ } else {
"Office deployment already exists for $($Tenant)"
Continue
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddWinGetApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddWinGetApp.ps1
index d59307524615..8097c6d328e2 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddWinGetApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddWinGetApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddWinGetApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1
index 4825fc8a9f81..74a83ce92927 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAssignApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -24,7 +26,7 @@ Function Invoke-ExecAssignApp {
'AllUsers' {
@'
{"mobileAppAssignments":[{"@odata.type":"#microsoft.graph.mobileAppAssignment","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"},"intent":"Required","settings":null}]}
-'@
+'@
}
'AllDevices' {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1
index 13e945aa16ed..0aa432beff14 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListApplicationQueue {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1
index aca3cafdcd2f..d5c13112058f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1
@@ -1,35 +1,37 @@
using namespace System.Net
Function Invoke-ListApps {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- try {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?`$top=999&`$filter=(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&`$orderby=displayName&" -tenantid $TenantFilter
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ try {
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?`$top=999&`$filter=(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&`$orderby=displayName&" -tenantid $TenantFilter
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = $ErrorMessage
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1
index e85a43e1740b..4f9d60aa52df 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAppsRepository {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -39,7 +41,7 @@ Function Invoke-ListAppsRepository {
description = $RepoPackage.summary.'#text'
customRepo = $Repository
created = Get-Date -Date $RepoPackage.properties.Created.'#text' -Format 'MM/dd/yyyy HH:mm:ss'
- }
+ }
}
} else {
$IsError = $true
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1
index 262bb17f79bc..b9ff114c5ffd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddAPDevice {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,25 +18,32 @@ Function Invoke-AddAPDevice {
Write-Host 'PowerShell HTTP trigger function processed a request.'
$TenantFilter = (Get-Tenants | Where-Object { $_.defaultDomainName -eq $Request.body.TenantFilter }).customerId
$GroupName = if ($Request.body.Groupname) { $Request.body.Groupname } else { (New-Guid).GUID }
+ Write-Host $GroupName
$rawDevices = $request.body.autopilotData
$Devices = ConvertTo-Json @($rawDevices)
- Write-Host $Devices
$Result = try {
$CurrentStatus = (New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation')
- if ($groupname -in $CurrentStatus.items.id) { throw 'This device batch name already exists. Please try with another name.' }
+ if ($groupname -in $CurrentStatus.items.id) { throw 'This device batch name already exists. The batch name must be unique.' }
$body = '{"batchId":"' + $($GroupName) + '","devices":' + $Devices + '}'
- $GraphRequest = (New-GraphPostRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$TenantFilter/DeviceBatches" -body $body -scope 'https://api.partnercenter.microsoft.com/user_impersonation')
- Write-Host ($GraphRequest | ConvertTo-Json)
- Start-Sleep 5
- $NewStatus = New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/customers/$tenantfilter/DeviceBatches" -scope 'https://api.partnercenter.microsoft.com/user_impersonation'
- Write-Host $($Newstatus | ConvertTo-Json)
- if ($Newstatus.totalcount -eq $CurrentStatus.totalcount) { throw 'We could not find the new autopilot device. Please check if your input is correct.' }
- Write-Host $CurrentStatus.Items
+ $GraphRequest = (New-GraphPostRequest -returnHeaders $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$TenantFilter/DeviceBatches" -body $body -scope 'https://api.partnercenter.microsoft.com/user_impersonation')
+ $Amount = 0
+ do {
+ Write-Host "Checking status of import job for $GroupName"
+ $amount ++
+ Start-Sleep 1
+ $NewStatus = New-GraphgetRequest -uri "https://api.partnercenter.microsoft.com/v1/$($GraphRequest.Location)" -scope 'https://api.partnercenter.microsoft.com/user_impersonation'
+ } until ($Newstatus.status -eq 'finished' -or $amount -eq 4)
+ if ($NewStatus.status -ne 'finished') { throw 'Could not retrieve status of import - This job might still be running. Check the autopilot device list in 10 minutes for the latest status.' }
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Created Autopilot devices group. Group ID is $GroupName" -Sev 'Info'
- "Created Autopilot devices group for $($Request.body.TenantFilter). Group ID is $GroupName"
- }
- catch {
- "$($Request.body.TenantFilter): Failed to create autopilot devices. $($_.Exception.Message)"
+ [PSCustomObject]@{
+ Status = 'Import Job Completed'
+ Devices = @($NewStatus.devicesStatus)
+ }
+ } catch {
+ [PSCustomObject]@{
+ Status = "$($Request.body.TenantFilter): Failed to create autopilot devices. $($_.Exception.Message)"
+ Devices = @()
+ }
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APIName -tenant $($Request.body.TenantFilter) -message "Failed to create autopilot devices. $($_.Exception.Message)" -Sev 'Error'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1
index 96208b3674f8..a87a2bcb7824 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddAutopilotConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -17,16 +19,29 @@ Function Invoke-AddAutopilotConfig {
# Input bindings are passed in via param block.
$Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value
- $displayname = $request.body.Displayname
- $description = $request.body.Description
$AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto }
- $Profbod = $Request.body
+ $Profbod = [pscustomobject]$Request.body
$usertype = if ($Profbod.NotLocalAdmin -eq 'true') { 'standard' } else { 'administrator' }
$DeploymentMode = if ($profbod.DeploymentMode -eq 'true') { 'shared' } else { 'singleUser' }
+ $profileParams = @{
+ displayname = $request.body.Displayname
+ description = $request.body.Description
+ usertype = $usertype
+ DeploymentMode = $DeploymentMode
+ assignto = $AssignTo
+ devicenameTemplate = $Profbod.deviceNameTemplate
+ allowWhiteGlove = $Profbod.allowWhiteGlove
+ CollectHash = $Profbod.collectHash
+ hideChangeAccount = $Profbod.hideChangeAccount
+ hidePrivacy = $Profbod.hidePrivacy
+ hideTerms = $Profbod.hideTerms
+ Autokeyboard = $Profbod.Autokeyboard
+ Language = $ProfBod.languages.value
+ }
$results = foreach ($Tenant in $tenants) {
- Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $displayname -description $description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $AssignTo -devicenameTemplate $Profbod.deviceNameTemplate -allowWhiteGlove $Profbod.allowWhiteGlove -CollectHash $Profbod.collectHash -hideChangeAccount $Profbod.hideChangeAccount -hidePrivacy $Profbod.hidePrivacy -hideTerms $Profbod.hideTerms -Autokeyboard $Profbod.Autokeyboard
+ $profileParams['tenantFilter'] = $Tenant
+ Set-CIPPDefaultAPDeploymentProfile @profileParams
}
-
$body = [pscustomobject]@{'Results' = $results }
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1
index f74ce07857d1..eaed0e5aba15 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddEnrollment {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecAssignAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecAssignAPDevice.ps1
index 450e93ef642b..0ae4d1f13cb0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecAssignAPDevice.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecAssignAPDevice.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAssignAPDevice {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -15,7 +17,7 @@ Function Invoke-ExecAssignAPDevice {
UserPrincipalName = $Request.body.UserPrincipalName
addressableUserName = $Request.body.addressableUserName
} | ConvertTo-Json
- New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$($request.body.Device)/UpdateDeviceProperties" -tenantid $TenantFilter -body $body -method POST
+ New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$($request.body.Device)/UpdateDeviceProperties" -tenantid $TenantFilter -body $body -method POST
$Results = "Successfully assigned device to $($Request.body.UserPrincipalName) for $($tenantfilter)"
} catch {
$Results = "Could not $($Request.body.UserPrincipalName) to $($Request.body.device) for $($tenantfilter) Error: $($_.Exception.Message)"
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1
index c2ec2c1f497b..ab840b320596 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAPDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,7 +20,7 @@ Function Invoke-ListAPDevices {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
try {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities?`$top=999" -tenantid $TenantFilter
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities?`$top=999" -tenantid $TenantFilter
$StatusCode = [HttpStatusCode]::OK
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1
index e38a8fd67769..7bb3f446bd11 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddDefenderDeployment {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -38,7 +40,7 @@ Function Invoke-AddDefenderDeployment {
$Settings = switch ($PolicySettings) {
{ $_.ScanArchives } {
- @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_1'; settingValueTemplateReference = @{settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' } } }
+ @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_1'; settingValueTemplateReference = @{settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' } } }
} { $_.AllowBehavior } {
@{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'; settingInstance = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring_1'; settingValueTemplateReference = @{settingValueTemplateId = '905921da-95e2-4a10-9e30-fe5540002ce1' } }; settingInstanceTemplateReference = @{settingInstanceTemplateId = '8eef615a-1aa0-46f4-a25a-12cbe65de5ab' } } }
} { $_.AllowCloudProtection } {
@@ -87,7 +89,7 @@ Function Invoke-AddDefenderDeployment {
roleScopeTagIds = @('0')
templateReference = @{templateId = '804339ad-1553-4478-a742-138fb5807418_1' }
settings = $Settings
- }
+ }
$PolicyRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $PolBody
if ($PolicySettings.AssignTo -ne 'None') {
$AssignBody = if ($PolicySettings.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($PolicySettings.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' }
@@ -150,7 +152,7 @@ Function Invoke-AddDefenderDeployment {
}
$EDRSettings = switch ($EDR) {
- { $_.SampleSharing } {
+ { $_.SampleSharing } {
@{
'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'
settingInstance = @{
@@ -163,9 +165,9 @@ Function Invoke-AddDefenderDeployment {
}
settingInstanceTemplateReference = @{settingInstanceTemplateId = '6998c81e-2814-4f5e-b492-a6159128a97b' }
}
- }
+ }
}
- { $_.Telemetry } {
+ { $_.Telemetry } {
@{
'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'
settingInstance = @{
@@ -178,10 +180,10 @@ Function Invoke-AddDefenderDeployment {
}
settingInstanceTemplateReference = @{settingInstanceTemplateId = '03de6095-07c4-4f35-be38-c1cd3bae4484' }
}
- }
-
+ }
+
}
- { $_.Config } {
+ { $_.Config } {
@{
'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting'
settingInstance = @{
@@ -193,11 +195,11 @@ Function Invoke-AddDefenderDeployment {
settingValueTemplateReference = @{settingValueTemplateId = 'e5c7c98c-c854-4140-836e-bd22db59d651' }
children = @(@{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' ; settingDefinitionId = 'device_vendor_msft_windowsadvancedthreatprotection_onboarding_fromconnector' ; simpleSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationSecretSettingValue' ; value = 'Microsoft ATP connector enabled'; valueState = 'NotEncrypted' } } )
}
-
+
settingInstanceTemplateReference = @{settingInstanceTemplateId = '23ab0ea3-1b12-429a-8ed0-7390cf699160' }
}
- }
-
+ }
+
}
}
$EDRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1
index b4c3471b4fca..60d86236ca22 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddIntuneTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -44,28 +46,35 @@ Function Invoke-AddIntuneTemplate {
$Type = 'deviceCompliancePolicies'
$Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)?`$expand=scheduledActionsForRule(`$expand=scheduledActionConfigurations)" -tenantid $tenantfilter
$DisplayName = $Template.displayName
- $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 10 -Compress
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
}
'managedAppPolicies' {
$Type = 'AppProtection'
$Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$($urlname)('$($ID)')" -tenantid $tenantfilter
$DisplayName = $Template.displayName
- $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 10 -Compress
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
}
'configurationPolicies' {
$Type = 'Catalog'
$Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$($ID)')?`$expand=settings" -tenantid $tenantfilter | Select-Object name, description, settings, platforms, technologies, templateReference
- $TemplateJson = $Template | ConvertTo-Json -Depth 10
+ $TemplateJson = $Template | ConvertTo-Json -Depth 100
$DisplayName = $Template.name
+ }
+ 'windowsDriverUpdateProfiles' {
+ $Type = 'windowsDriverUpdateProfiles'
+ $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime'
+ Write-Host ($Template | ConvertTo-Json)
+ $DisplayName = $Template.displayName
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
}
'deviceConfigurations' {
$Type = 'Device'
$Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime'
Write-Host ($Template | ConvertTo-Json)
$DisplayName = $Template.displayName
- $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 10 -Compress
+ $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress
}
'groupPolicyConfigurations' {
$Type = 'Admin'
@@ -100,7 +109,7 @@ Function Invoke-AddIntuneTemplate {
}
- $TemplateJson = (ConvertTo-Json -InputObject $inputvar -Depth 15 -Compress)
+ $TemplateJson = (ConvertTo-Json -InputObject $inputvar -Depth 100 -Compress)
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1
index ac6648f814dc..aca7c04ca269 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -25,6 +27,7 @@ Function Invoke-AddPolicy {
try {
switch ($Request.Body.TemplateType) {
'AppProtection' {
+ $PlatformType = 'deviceAppManagement'
$TemplateType = ($RawJSON | ConvertFrom-Json).'@odata.type' -replace '#microsoft.graph.', ''
$TemplateTypeURL = "$($TemplateType)s"
$CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenant
@@ -79,11 +82,24 @@ Function Invoke-AddPolicy {
}
$CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON
}
+ 'windowsDriverUpdateProfiles' {
+ $TemplateTypeURL = 'windowsDriverUpdateProfiles'
+ $PolicyName = ($RawJSON | ConvertFrom-Json).Name
+ $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant
+ if ($PolicyName -in $CheckExististing.name) {
+ $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON
+
+ } else {
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info'
+ }
+ }
}
Write-LogMessage -user $Request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname)" -Sev 'Info'
if ($AssignTo) {
- Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenant
+ Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenant -PlatformType $PlatformType
}
"Successfully added policy for $($Tenant)"
} catch {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1
index e30d3971cb00..066e83cf11df 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-EditPolicy {
$displayname = $request.body.Displayname
$description = $request.body.Description
$AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto }
-
+
$results = try {
$CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}'
$Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations('$ID')" -tenantid $tenant -type PATCH -body $CreateBody
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1
index ae866ed3f485..8000d6f46d2f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAssignPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -15,7 +17,7 @@ Function Invoke-ExecAssignPolicy {
$ID = $request.query.id
$displayname = $request.query.Displayname
$AssignTo = if ($request.query.Assignto -ne 'on') { $request.query.Assignto }
-
+
$results = try {
if ($AssignTo) {
$assign = Set-CIPPAssignedPolicy -PolicyId $ID -TenantFilter $tenant -GroupName $AssignTo -Type $Request.query.Type
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1
index 90f9e86d4c6d..ca788cb979da 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecDeviceAction {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,10 +16,10 @@ Function Invoke-ExecDeviceAction {
# Interact with query parameters or the body of the request.
- try {
+ try {
if ($Request.Query.Action -eq 'setDeviceName') {
$ActionBody = @{ deviceName = $Request.Body.input } | ConvertTo-Json -Compress
- }
+ }
$ActionResult = New-CIPPDeviceAction -Action $Request.Query.Action -ActionBody $ActionBody -DeviceFilter $Request.Query.GUID -TenantFilter $Request.Query.TenantFilter -ExecutingUser $request.headers.'x-ms-client-principal' -APINAME $APINAME
$body = [pscustomobject]@{'Results' = "$ActionResult" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetLocalAdminPassword.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetLocalAdminPassword.ps1
index c58267717c20..f2850548e8c2 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetLocalAdminPassword.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetLocalAdminPassword.ps1
@@ -1,30 +1,31 @@
- using namespace System.Net
+using namespace System.Net
- Function Invoke-ExecGetLocalAdminPassword {
+Function Invoke-ExecGetLocalAdminPassword {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Device.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
+ $APIName = $TriggerMetadata.FunctionName
-try {
- $GraphRequest = Get-CIPPLapsPassword -device $($request.query.guid) -tenantFilter $Request.Query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
- $Body = [pscustomobject]@{"Results" = $GraphRequest }
+ try {
+ $GraphRequest = Get-CIPPLapsPassword -device $($request.query.guid) -tenantFilter $Request.Query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ $Body = [pscustomobject]@{'Results' = $GraphRequest }
-}
-catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $Body = [pscustomobject]@{"Results" = "Failed. $ErrorMessage" }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $Body = [pscustomobject]@{'Results' = "Failed. $ErrorMessage" }
-}
+ }
-# Associate values to output bindings by calling 'Push-OutputBinding'.
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Body
- })
+ # 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/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1
index 7190225450a5..46df4d780496 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGetRecoveryKey {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Device.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1
index 8587a32155e3..d4ed67595239 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Device.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,7 +20,7 @@ Function Invoke-ListDevices {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
try {
- $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/managedDevices' -Tenantid $tenantfilter
+ $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/managedDevices' -Tenantid $tenantfilter
$StatusCode = [HttpStatusCode]::OK
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Devices/Invoke-ExecDeviceDelete.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Devices/Invoke-ExecDeviceDelete.ps1
index 25e64be478b3..14101947635f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Devices/Invoke-ExecDeviceDelete.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Devices/Invoke-ExecDeviceDelete.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecDeviceDelete {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Device.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroup.ps1
index 2a9d176a365e..f4dda9d8f50a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroup.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddGroup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -46,14 +48,14 @@ Function Invoke-AddGroup {
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose
} else {
if ($groupobj.groupType -eq 'dynamicdistribution') {
- $Params = @{
+ $Params = @{
Name = $groupobj.Displayname
RecipientFilter = $groupobj.membershipRules
PrimarySmtpAddress = $email
}
$GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DynamicDistributionGroup' -cmdParams $params
} else {
- $Params = @{
+ $Params = @{
Name = $groupobj.Displayname
Alias = $groupobj.username
Description = $groupobj.Description
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1
index 85d10812a9c8..83d8e9a64743 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddGroupTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,7 +14,7 @@ Function Invoke-AddGroupTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$GUID = (New-Guid).GUID
- try {
+ try {
if (!$Request.body.displayname) { throw 'You must enter a displayname' }
$object = [PSCustomObject]@{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1
index 6990f6baa46f..122c4f118739 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditGroup {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -23,13 +25,13 @@ Function Invoke-EditGroup {
$AddMembers | ForEach-Object {
try {
$member = $_
-
+
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 $Userobj.tenantid).id
+ $MemberIDs = 'https://graph.microsoft.com/v1.0/directoryObjects/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($member)" -tenantid $Userobj.tenantid).id
$addmemberbody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }"
if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') {
$Params = @{ Identity = $userobj.groupid; Member = $member; BypassSecurityGroupManagerCheck = $true }
- New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
+ New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
} else {
New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)" -tenantid $Userobj.tenantid -type patch -body $addmemberbody -Verbose
}
@@ -67,7 +69,7 @@ Function Invoke-EditGroup {
$RemoveMembers = ($userobj.Removemember).value
try {
if ($RemoveMembers) {
- $RemoveMembers | ForEach-Object {
+ $RemoveMembers | ForEach-Object {
$member = $_
if ($member -like '*#EXT#*') { $member = [System.Web.HttpUtility]::UrlEncode($member) }
if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') {
@@ -75,11 +77,11 @@ Function Invoke-EditGroup {
New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Remove-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true
} else {
$MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid)
- New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/members/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE
+ New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/members/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE
}
Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $member from $($userobj.groupName) group" -Sev 'Info'
$null = $results.add("Success. Member $member has been removed from $($userobj.groupName)")
- }
+ }
}
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to remove $RemoveMembers from $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error'
@@ -89,7 +91,7 @@ Function Invoke-EditGroup {
$AddOwners = $userobj.Addowner.value
try {
if ($AddOwners) {
- $AddOwners | ForEach-Object {
+ $AddOwners | ForEach-Object {
try {
$ID = 'https://graph.microsoft.com/beta/users/' + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid).id
Write-Host $ID
@@ -110,16 +112,16 @@ Function Invoke-EditGroup {
$RemoveOwners = ($userobj.RemoveOwner).value
try {
if ($RemoveOwners) {
- $RemoveOwners | ForEach-Object {
+ $RemoveOwners | ForEach-Object {
try {
$MemberInfo = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($_)" -tenantid $Userobj.tenantid)
- New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE
+ New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($userobj.groupid)/owners/$($MemberInfo.id)/`$ref" -tenantid $Userobj.tenantid -type DELETE
Write-LogMessage -API $APINAME -tenant $Userobj.tenantid -user $request.headers.'x-ms-client-principal' -message "Removed $($MemberInfo.UserPrincipalname) from $($userobj.displayname) group" -Sev 'Info'
$null = $results.add("Success. Member $_ has been removed from $($userobj.groupName)")
} catch {
$null = $results.add("Failed to remove $_ from $($userobj.groupName): $($_.Exception.Message)")
}
- }
+ }
}
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to remove $RemoveMembers from $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error'
@@ -157,7 +159,7 @@ Function Invoke-EditGroup {
$subscriberParams = @{ Identity = $userobj.Groupid; LinkType = 'subscribers'; Links = @($MemberSmtpAddresses) }
New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Add-UnifiedGrouplinks' -cmdParams $subscriberParams -Anchor $userobj.mail
-
+
$body = $results.add("Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled.")
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Send Copies of team emails and events to team members inboxes for $($userobj.mail) enabled." -Sev 'Info'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1
index 462ba7df0545..43e1dc49d393 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddGuest {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -22,7 +24,7 @@ Function Invoke-AddGuest {
'InvitedUserEmailAddress' = $($userobj.mail)
'inviteRedirectUrl' = $($userobj.RedirectURL)
'sendInvitationMessage' = [boolean]$userobj.SendInvite
- }
+ }
}
else {
$BodyToship = [pscustomobject] @{
@@ -31,14 +33,14 @@ Function Invoke-AddGuest {
'sendInvitationMessage' = [boolean]$userobj.SendInvite
'inviteRedirectUrl' = 'https://myapps.microsoft.com'
}
- }
+ }
$bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/invitations' -tenantid $Userobj.tenantid -type POST -body $BodyToship -verbose
- if ($Userobj.sendInvite -eq 'true') {
+ if ($Userobj.sendInvite -eq 'true') {
$results.add('Invited Guest. Invite Email sent')
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with Email Invite " -Sev 'Info'
}
- else {
+ else {
$results.add('Invited Guest. No Invite Email was sent')
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($userobj.tenantid) -message "Invited Guest $($userobj.displayname) with no Email Invite " -Sev 'Info'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUser.ps1
index 861ea01e85c4..d554111c480c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUser.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddUser {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -53,6 +55,12 @@ Function Invoke-AddUser {
$bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/users' -tenantid $UserObj.tenantID -type POST -body $BodyToship -verbose
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($UserObj.tenantID) -message "Created user $($UserObj.displayname) with id $($GraphRequest.id) " -Sev 'Info'
+
+ #PWPush
+ $PasswordLink = New-PwPushLink -Payload $password
+ if ($PasswordLink) {
+ $password = $PasswordLink
+ }
$results.add('Created user.')
$results.add("Username: $($UserprincipalName)")
$results.add("Password: $password")
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1
index 31c3fbbaa687..2d33113d1ffb 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddUserBulk {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,8 +13,7 @@ Function Invoke-AddUserBulk {
$APIName = 'AddUserBulk'
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$TenantFilter = $Request.body.TenantFilter
- $Results = [System.Collections.ArrayList]@()
- foreach ($userobj in $request.body.BulkUser) {
+ $Body = foreach ($userobj in $request.body.BulkUser) {
Write-Host 'PowerShell HTTP trigger function processed a request.'
try {
$password = if ($userobj.password) { $userobj.password } else { New-passwordString }
@@ -30,24 +31,29 @@ Function Invoke-AddUserBulk {
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/users' -tenantid $TenantFilter -type POST -body $BodyToship
Write-Host "Graph request is $GraphRequest"
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($TenantFilter) -message "Created user $($userobj.displayname) with id $($GraphRequest.id) " -Sev 'Info'
- $results.add("Created user $($UserprincipalName). Password is $password") | Out-Null
+
+ #PWPush
+ $PasswordLink = New-PwPushLink -Payload $password
+ if ($PasswordLink) {
+ $password = $PasswordLink
+ }
+ $results = "Created user $($UserprincipalName). Password is $password"
+
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($TenantFilter) -message "Failed to create user. Error:$($_.Exception.Message)" -Sev 'Error'
- $body = $results.add("Failed to create user. $($_.Exception.Message)" )
+ $results = "Failed to create user. $($_.Exception.Message)"
+ }
+ [PSCustomObject]@{
+ 'Results' = $results
+ 'Username' = $UserprincipalName
+ 'Password' = $password
}
}
- $body = [pscustomobject] @{
- 'Results' = @($results)
- 'Username' = $UserprincipalName
- 'Password' = $password
- 'CopyFrom' = $copyFromResults
- }
-
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
- Body = $Body
+ Body = @($Body)
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1
index cb925b1cda70..39e018d223df 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditUser {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECCheck.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECCheck.ps1
index 7413636f7061..52aab6d770f5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECCheck.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECCheck.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecBECCheck {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1
index b863aeac8f06..cfbf2078aa27 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecBECRemediate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -24,9 +26,9 @@ Function Invoke-ExecBECRemediate {
$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 {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecClrImmId.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecClrImmId.ps1
index 3506522f2c8c..9241f5feae7d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecClrImmId.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecClrImmId.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecClrImmId {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1
index 9919b0564510..3ae22c37ffa7 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1
@@ -1,28 +1,30 @@
using namespace System.Net
Function Invoke-ExecCreateTAP {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Interact with query parameters or the body of the request.
- try {
- $TAP = New-CIPPTAP -userid $Request.query.ID -TenantFilter $Request.query.tenantfilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
- $Results = [pscustomobject]@{'Results' = "$TAP" }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ # Interact with query parameters or the body of the request.
+ try {
+ $TAP = New-CIPPTAP -userid $Request.query.ID -TenantFilter $Request.query.tenantfilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ $Results = [pscustomobject]@{'Results' = "$TAP" }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1
index 3e32878e726d..69ac4dd83ec8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1
@@ -1,26 +1,28 @@
using namespace System.Net
Function Invoke-ExecDisableUser {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- try {
+ $APIName = $TriggerMetadata.FunctionName
+ try {
([System.Convert]::ToBoolean($Request.Query.Enable))
- $State = Set-CIPPSignInState -userid $Request.query.ID -TenantFilter $Request.Query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' -AccountEnabled ([System.Convert]::ToBoolean($Request.Query.Enable))
- $Results = [pscustomobject]@{'Results' = "$State" }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ $State = Set-CIPPSignInState -userid $Request.query.ID -TenantFilter $Request.Query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' -AccountEnabled ([System.Convert]::ToBoolean($Request.Query.Enable))
+ $Results = [pscustomobject]@{'Results' = "$State" }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1
new file mode 100644
index 000000000000..1c1c575a598f
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1
@@ -0,0 +1,153 @@
+using namespace System.Net
+
+Function Invoke-ExecJITAdmin {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Identity.Role.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = 'ExecJITAdmin'
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+
+ if ($Request.Query.Action -eq 'List') {
+ $Schema = Get-CIPPSchemaExtensions | Where-Object { $_.id -match '_cippUser' }
+ #Write-Information "Schema: $($Schema)"
+ $Query = @{
+ TenantFilter = $Request.Query.TenantFilter
+ Endpoint = 'users'
+ Parameters = @{
+ '$count' = 'true'
+ '$select' = "id,displayName,userPrincipalName,$($Schema.id)"
+ '$filter' = "$($Schema.id)/jitAdminEnabled eq true or $($Schema.id)/jitAdminEnabled eq false"
+ }
+ }
+ $Users = Get-GraphRequestList @Query | Where-Object { $_.id }
+ $BulkRequests = $Users | ForEach-Object { @(
+ @{
+ id = $_.id
+ method = 'GET'
+ url = "users/$($_.id)/memberOf/microsoft.graph.directoryRole/?`$select=id,displayName"
+ }
+ )
+ }
+ $RoleResults = New-GraphBulkRequest -tenantid $Request.Query.TenantFilter -Requests @($BulkRequests)
+ #Write-Information ($RoleResults | ConvertTo-Json -Depth 10 )
+ $Results = $Users | ForEach-Object {
+ $MemberOf = ($RoleResults | Where-Object -Property id -EQ $_.id).body.value | Select-Object displayName, id
+ [PSCustomObject]@{
+ id = $_.id
+ displayName = $_.displayName
+ userPrincipalName = $_.userPrincipalName
+ jitAdminEnabled = $_.($Schema.id).jitAdminEnabled
+ jitAdminExpiration = $_.($Schema.id).jitAdminExpiration
+ memberOf = $MemberOf
+ }
+ }
+
+ #Write-Information ($Results | ConvertTo-Json -Depth 10)
+ $Body = @{
+ Results = @($Results)
+ Metadata = @{
+ Parameters = $Query.Parameters
+ }
+ }
+ } else {
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Executing JIT Admin for $($Request.Body.UserPrincipalName)" -Sev 'Info'
+ if ($Request.Body.UserId -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') {
+ $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($Request.Body.UserId)" -tenantid $Request.Body.TenantFilter).userPrincipalName
+ }
+
+ $Start = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.StartDate)).DateTime.ToLocalTime()
+ $Expiration = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.EndDate)).DateTime.ToLocalTime()
+ $Results = [System.Collections.Generic.List[string]]::new()
+
+ if ($Request.Body.useraction -eq 'create') {
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Creating JIT Admin user $($Request.Body.UserPrincipalName)" -Sev 'Info'
+ Write-Information "Creating JIT Admin user $($Request.Body.UserPrincipalName)"
+ $JITAdmin = @{
+ User = @{
+ 'FirstName' = $Request.Body.FirstName
+ 'LastName' = $Request.Body.LastName
+ 'UserPrincipalName' = $Request.Body.UserPrincipalName
+ }
+ Expiration = $Expiration
+ Action = 'Create'
+ TenantFilter = $Request.Body.TenantFilter
+ }
+ $CreateResult = Set-CIPPUserJITAdmin @JITAdmin
+ $Username = $CreateResult.userPrincipalName
+ $Results.Add("Created User: $($CreateResult.userPrincipalName)")
+ $Results.Add("Password: $($CreateResult.password)")
+ Start-Sleep -Seconds 1
+ }
+ $Parameters = @{
+ TenantFilter = $Request.Body.TenantFilter
+ User = @{
+ 'UserPrincipalName' = $Username
+ }
+ Roles = $Request.Body.AdminRoles
+ Action = 'AddRoles'
+ Expiration = $Expiration
+ }
+ if ($Start -gt (Get-Date)) {
+ $TaskBody = @{
+ TenantFilter = $Request.Body.TenantFilter
+ Name = "JIT Admin (enable): $Username"
+ Command = @{
+ value = 'Set-CIPPUserJITAdmin'
+ label = 'Set-CIPPUserJITAdmin'
+ }
+ Parameters = $Parameters
+ ScheduledTime = $Request.Body.StartDate
+ PostExecution = @{
+ Webhook = [bool]$Request.Body.PostExecution.Webhook
+ Email = [bool]$Request.Body.PostExecution.Email
+ PSA = [bool]$Request.Body.PostExecution.PSA
+ }
+ }
+ Add-CIPPScheduledTask -Task $TaskBody -hidden $false
+ Set-CIPPUserJITAdminProperties -TenantFilter $Request.Body.TenantFilter -UserId $Request.Body.UserId -Expiration $Expiration
+ $Results.Add("Scheduling JIT Admin enable task for $Username")
+ } else {
+ $Results.Add("Executing JIT Admin enable task for $Username")
+ Set-CIPPUserJITAdmin @Parameters
+ }
+
+ $DisableTaskBody = @{
+ TenantFilter = $Request.Body.TenantFilter
+ Name = "JIT Admin (disable): $Username"
+ Command = @{
+ value = 'Set-CIPPUserJITAdmin'
+ label = 'Set-CIPPUserJITAdmin'
+ }
+ Parameters = @{
+ TenantFilter = $Request.Body.TenantFilter
+ User = @{
+ 'UserPrincipalName' = $Username
+ }
+ Roles = $Request.Body.AdminRoles
+ Action = $Request.Body.ExpireAction
+ }
+ PostExecution = @{
+ Webhook = [bool]$Request.Body.PostExecution.Webhook
+ Email = [bool]$Request.Body.PostExecution.Email
+ PSA = [bool]$Request.Body.PostExecution.PSA
+ }
+ ScheduledTime = $Request.Body.EndDate
+ }
+ Add-CIPPScheduledTask -Task $DisableTaskBody -hidden $false
+ $Results.Add("Scheduling JIT Admin disable task for $Username")
+ $Body = @{
+ Results = @($Results)
+ }
+ }
+
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Body
+ })
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1
index 02516f3148bf..0bf9feaf3dff 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecOffboardUser {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -22,9 +24,10 @@ Function Invoke-ExecOffboardUser {
value = 'Invoke-CIPPOffboardingJob'
}
Parameters = @{
- Username = $Username
- APIName = 'Scheduled Offboarding'
- options = $request.body
+ Username = $Username
+ APIName = 'Scheduled Offboarding'
+ options = $request.body
+ RunScheduled = $true
}
ScheduledTime = $Request.body.scheduled.date
PostExecution = @{
@@ -38,7 +41,7 @@ Function Invoke-ExecOffboardUser {
Invoke-CIPPOffboardingJob -Username $Username -TenantFilter $Tenantfilter -Options $Request.body -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal'
}
$StatusCode = [HttpStatusCode]::OK
-
+
} catch {
$StatusCode = [HttpStatusCode]::Forbidden
$body = $_.Exception.message
@@ -48,6 +51,6 @@ Function Invoke-ExecOffboardUser {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = $Body
- })
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboard_Mailboxpermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboard_Mailboxpermissions.ps1
index 18e70672635d..02e60ca462d0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboard_Mailboxpermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboard_Mailboxpermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecOffboard_Mailboxpermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1
index 2f820ab4a068..ddc282908b68 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecOneDriveShortCut {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecPerUserMFA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecPerUserMFA.ps1
new file mode 100644
index 000000000000..b52a1595f513
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecPerUserMFA.ps1
@@ -0,0 +1,28 @@
+function Invoke-ExecPerUserMFA {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+
+ .ROLE
+ Identity.User.ReadWrite
+ #>
+ Param(
+ $Request,
+ $TriggerMetadata
+ )
+
+ $Request = @{
+ userId = $Request.Body.userId
+ TenantFilter = $Request.Body.TenantFilter
+ State = $Request.Body.State
+ executingUser = $Request.Headers.'x-ms-client-principal'
+ }
+ $Result = Set-CIPPPerUserMFA @Request
+ $Body = @{
+ Results = @($Result)
+ }
+ 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/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1
index 457e8abcba1c..1667958aa7a1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecResetMFA {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -29,7 +31,7 @@ Function Invoke-ExecResetMFA {
http://provisioning.microsoftonline.com/IProvisioningWebService/SetUserurn:uuid:$TrackingGuidhttp://www.w3.org/2005/08/addressing/anonymous$($AADGraphtoken['Authorization'])$($DataBlob)9450afce61-c917-435b-8c6d-60aa5a8b8aa71.2.183.57Version47$TrackingGuidhttps://provisioningapi.microsoftonline.com/provisioningwebservice.svcVersion16$($tenantid)$($Request.query.id)*0001-01-01T00:00:00Enabled
"@
$SetMFA = (Invoke-RestMethod -Uri 'https://provisioningapi.microsoftonline.com/provisioningwebservice.svc' -Method post -Body $MSOLXML -ContentType 'application/soap+xml; charset=utf-8')
-
+
$Results = [pscustomobject]@{'Results' = 'Successfully completed request. User must supply MFA at next logon' }
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Reset Multi factor authentication settings for $($Request.query.id)" -Sev 'Info'
} catch {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1
index 0d16795f9104..c9be1da38759 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecResetPass {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1
index bab48ef09239..5c5c56fe568f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1
@@ -1,29 +1,31 @@
using namespace System.Net
Function Invoke-ExecRevokeSessions {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- try {
- $RevokeSessions = Revoke-CIPPSessions -userid $Request.Query.id -tenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
- $Results = [pscustomobject]@{'Results' = $RevokeSessions }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ try {
+ $RevokeSessions = Revoke-CIPPSessions -userid $Request.Query.id -tenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal'
+ $Results = [pscustomobject]@{'Results' = $RevokeSessions }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1
index aeeb61d4f9c8..3970db4890e6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSendPush {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -46,7 +48,7 @@ Function Invoke-ExecSendPush {
# Create a serivce principal if needed
if (!$SPID) {
-
+
$SPBody = [pscustomobject]@{
appId = $MFAAppID
}
@@ -107,7 +109,7 @@ Function Invoke-ExecSendPush {
$Body = "Authentication Failed! Does the user have Push/Phone call MFA configured? Errorcode: $($obj.BeginTwoWayAuthenticationResponse.result.value | Out-String)"
$colour = 'danger'
}
-
+
}
$Results = [pscustomobject]@{'Results' = $Body; colour = $colour }
@@ -117,6 +119,6 @@ Function Invoke-ExecSendPush {
StatusCode = [HttpStatusCode]::OK
Body = $Results
})
-
+
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1
index 1557184a8bb6..c717f77589f1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserConditionalAccessPolicies {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,20 +22,24 @@ Function Invoke-ListUserConditionalAccessPolicies {
$UserID = $Request.Query.UserID
try {
- $json = '{"conditions":{"users":{"allUsers":2,"included":{"userIds":["' + $UserID + '"],"groupIds":[]},"excluded":{"userIds":[],"groupIds":[]}},"servicePrincipals":{"allServicePrincipals":1,"includeAllMicrosoftApps":false,"excludeAllMicrosoftApps":false,"userActions":[],"stepUpTags":[]},"conditions":{"minUserRisk":{"noRisk":false,"lowRisk":false,"mediumRisk":false,"highRisk":false,"applyCondition":false},"minSigninRisk":{"noRisk":false,"lowRisk":false,"mediumRisk":false,"highRisk":false,"applyCondition":false},"servicePrincipalRiskLevels":{"noRisk":false,"lowRisk":false,"mediumRisk":false,"highRisk":false,"applyCondition":false},"devicePlatforms":{"all":2,"included":{"android":false,"ios":false,"windowsPhone":false,"windows":false,"macOs":false,"linux":false},"excluded":null,"applyCondition":false},"locations":{"applyCondition":true,"includeLocationType":2,"excludeAllTrusted":false},"clientApps":{"applyCondition":false,"specificClientApps":false,"webBrowsers":false,"exchangeActiveSync":false,"onlyAllowSupportedPlatforms":false,"mobileDesktop":false},"clientAppsV2":{"applyCondition":false,"webBrowsers":false,"mobileDesktop":false,"modernAuth":false,"exchangeActiveSync":false,"onlyAllowSupportedPlatforms":false,"otherClients":false},"deviceState":{"includeDeviceStateType":1,"excludeDomainJoionedDevice":false,"excludeCompliantDevice":false,"applyCondition":true}}},"country":"","device":{}}'
- $ConditionalAccessPolicyOutput = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $tenantfilter
- } catch {
- $ConditionalAccessPolicyOutput = @{}
- }
-
- $GraphRequest = foreach ($cap in $ConditionalAccessPolicyOutput) {
- if ($cap.id -in $UserPolicies.policyId) {
- $temp = [PSCustomObject]@{
- id = $cap.id
- displayName = $cap.displayName
+ $IncludeApplications = '67ad5377-2d78-4ac2-a867-6300cda00e85'
+ $CAContext = @{
+ '@odata.type' = '#microsoft.graph.whatIfApplicationContext'
+ 'includeApplications' = @($IncludeApplications)
+ }
+ $ConditionalAccessWhatIfDefinition = @{
+ 'conditionalAccessWhatIfSubject' = @{
+ '@odata.type' = '#microsoft.graph.userSubject'
+ 'userId' = "$userId"
}
- $temp
+ 'conditionalAccessContext' = $CAContext
+ 'conditionalAccessWhatIfConditions' = @{}
}
+ $JSONBody = $ConditionalAccessWhatIfDefinition | ConvertTo-Json -Depth 10
+
+ $GraphRequest = (New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/evaluate' -tenantid $tenantFilter -type POST -body $JsonBody -AsApp $true).value
+ } catch {
+ $GraphRequest = @{}
}
Write-Host $GraphRequest
@@ -41,7 +47,7 @@ Function Invoke-ListUserConditionalAccessPolicies {
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
- Body = @($GraphRequest)
+ Body = @($GraphRequest)
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1
index 137a9c8cc902..d67251b461e0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1
@@ -1,45 +1,47 @@
using namespace System.Net
Function Invoke-ListUserCounts {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- if ($Request.Query.TenantFilter -eq 'AllTenants') {
- $users = 'Not Supported'
- $LicUsers = 'Not Supported'
- $GAs = 'Not Supported'
- $Guests = 'Not Supported'
- } else {
- try { $Users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Users = 'Not available' }
- try { $LicUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=assignedLicenses/`$count ne 0" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Licusers = 'Not available' }
- try { $GAs = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190-012177145e10/members?`$count=true" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Gas = 'Not available' }
- try { $guests = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=userType eq 'Guest'" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Guests = 'Not available' }
- }
- $StatusCode = [HttpStatusCode]::OK
- $Counts = @{
- Users = $users
- LicUsers = $LicUsers
- Gas = $Gas
- Guests = $guests
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ if ($Request.Query.TenantFilter -eq 'AllTenants') {
+ $users = 'Not Supported'
+ $LicUsers = 'Not Supported'
+ $GAs = 'Not Supported'
+ $Guests = 'Not Supported'
+ } else {
+ try { $Users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Users = 'Not available' }
+ try { $LicUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=assignedLicenses/`$count ne 0" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Licusers = 'Not available' }
+ try { $GAs = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/roleTemplateId=62e90394-69f5-4237-9190-012177145e10/members?`$count=true" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Gas = 'Not available' }
+ try { $guests = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$count=true&`$top=1&`$filter=userType eq 'Guest'" -CountOnly -ComplexFilter -tenantid $TenantFilter } catch { $Guests = 'Not available' }
+ }
+ $StatusCode = [HttpStatusCode]::OK
+ $Counts = @{
+ Users = $users
+ LicUsers = $LicUsers
+ Gas = $Gas
+ Guests = $guests
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = $Counts
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = $Counts
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1
index 0bbcb27b4422..0c36e75712fd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1
index fff7eb222d9c..26676aec5623 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserGroups {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,7 +22,7 @@ Function Invoke-ListUserGroups {
$UserID = $Request.Query.UserID
- $URI = "https://graph.microsoft.com/beta/users/$UserID/memberOf/$/microsoft.graph.group?`$select=id,displayName,mailEnabled,securityEnabled,groupTypes,onPremisesSyncEnabled,mail,isAssignableToRole`&$orderby=displayName asc"
+ $URI = "https://graph.microsoft.com/beta/users/$UserID/memberOf/$/microsoft.graph.group?`$select=id,displayName,mailEnabled,securityEnabled,groupTypes,onPremisesSyncEnabled,mail,isAssignableToRole`&$orderby=displayName asc"
Write-Host $URI
$GraphRequest = New-GraphGetRequest -uri $URI -tenantid $TenantFilter -noPagination $true -verbose | Select-Object id,
@{ Name = 'DisplayName'; Expression = { $_.displayName } },
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 22f5665696c4..152323e21b4e 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserMailboxDetails {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -23,7 +25,7 @@ Function Invoke-ListUserMailboxDetails {
$TenantFilter = $Request.Query.TenantFilter
try {
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($Request.Query.UserID)
- $base64IdentityParam = [Convert]::ToBase64String($Bytes)
+ $base64IdentityParam = [Convert]::ToBase64String($Bytes)
$CASRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/CasMailbox('$UserID')" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true
$MailRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$UserID')" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true
$FetchParam = @{
@@ -32,7 +34,7 @@ Function Invoke-ListUserMailboxDetails {
$MailboxDetailedRequest = New-ExoRequest -TenantID $TenantFilter -cmdlet 'Get-Mailbox' -cmdParams $FetchParam
try {
if ($MailboxDetailedRequest.ArchiveStatus -eq 'Active') {
- $ArchiveEnabled = $True
+ $ArchiveEnabled = $True
} else {
$ArchiveEnabled = $False
}
@@ -68,7 +70,7 @@ Function Invoke-ListUserMailboxDetails {
}
$StatsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($MailRequest.PrimarySmtpAddress)')/Exchange.GetMailboxStatistics()" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true
$PermsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($MailRequest.PrimarySmtpAddress)')/MailboxPermission" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true
- $PermsRequest2 = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Recipient('$base64IdentityParam')?`$expand=RecipientPermission&isEncoded=true" -Tenantid $tenantfilter -scope ExchangeOnline
+ $PermsRequest2 = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Recipient('$base64IdentityParam')?`$expand=RecipientPermission&isEncoded=true" -Tenantid $tenantfilter -scope ExchangeOnline
} catch {
Write-Error "Failed Fetching Data $($_.Exception.message): $($_.InvocationInfo.ScriptLineNumber)"
@@ -79,16 +81,16 @@ Function Invoke-ListUserMailboxDetails {
if ($perm.Trustee) {
$perm | Where-Object Trustee | ForEach-Object { [PSCustomObject]@{
User = $_.Trustee
- AccessRights = $_.accessRights -join ', '
+ AccessRights = $_.accessRights -join ', '
}
}
-
+
}
if ($perm.PermissionList) {
$perm | Where-Object User | ForEach-Object { [PSCustomObject]@{
User = $_.User
AccessRights = $_.PermissionList.accessRights -join ', '
- }
+ }
}
}
}
@@ -98,10 +100,10 @@ Function Invoke-ListUserMailboxDetails {
} elseif ($MailboxDetailedRequest.ForwardingSmtpAddress -and $MailboxDetailedRequest.ForwardingAddress) {
$MailboxDetailedRequest.ForwardingAddress + ' ' + $MailboxDetailedRequest.ForwardingSmtpAddress
} else {
- $MailboxDetailedRequest.ForwardingSmtpAddress
+ $MailboxDetailedRequest.ForwardingSmtpAddress
}
- if ($ArchiveSize) {
+ if ($ArchiveSize) {
$GraphRequest = [ordered]@{
ForwardAndDeliver = $MailboxDetailedRequest.DeliverToMailboxAndForward
ForwardingAddress = $ForwardingAddress
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1
index 4a0a433fc1d4..eade83ccee64 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserMailboxRules {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserPhoto.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserPhoto.ps1
index bd596e0a379a..757784ad320d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserPhoto.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserPhoto.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserPhoto {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1
index 50781d922e7b..85b59ec479fd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
function Invoke-ListUserSettings {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1
index d421b79441d5..32c2cc24f28a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUserSigninLogs {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -19,7 +21,7 @@ Function Invoke-ListUserSigninLogs {
$TenantFilter = $Request.Query.TenantFilter
$UserID = $Request.Query.UserID
try {
- $URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$UserID')&`$top=50&`$orderby=createdDateTime desc"
+ $URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$UserID')&`$top=50&`$orderby=createdDateTime desc"
Write-Host $URI
$GraphRequest = New-GraphGetRequest -uri $URI -tenantid $TenantFilter -noPagination $true -verbose | Select-Object @{ Name = 'Date'; Expression = { $(($_.createdDateTime | Out-String) -replace '\r\n') } },
id,
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1
index 8431d441a320..b85dde08e21f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListUsers {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -72,11 +74,11 @@ Function Invoke-ListUsers {
Id = $AuditlogsLogon.errorNumber
Status = $AuditlogsLogon.ResultStatus
}
- $GraphRequest = $GraphRequest | Select-Object *,
+ $GraphRequest = $GraphRequest | Select-Object *,
@{ Name = 'LastSigninApplication'; Expression = { $LastSignIn.AppDisplayName } },
@{ Name = 'LastSigninDate'; Expression = { $($LastSignIn.CreatedDateTime | Out-String) } },
@{ Name = 'LastSigninStatus'; Expression = { $AuditlogsLogon.operation } },
- @{ Name = 'LastSigninResult'; Expression = { $LastSignIn.status } },
+ @{ Name = 'LastSigninResult'; Expression = { $LastSignIn.status } },
@{ Name = 'LastSigninFailureReason'; Expression = { if ($LastSignIn.Id -eq 0) { 'Sucessfully signed in' } else { $LastSignIn.Id } } }
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuth.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuth.ps1
index bf831b65cc9b..9cdbce1b86c8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuth.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuth.ps1
@@ -3,12 +3,14 @@ using namespace System.Net
Function Invoke-ListBasicAuth {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.AuditLog.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
+
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
@@ -25,7 +27,7 @@ Function Invoke-ListBasicAuth {
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/auditLogs/signIns?api-version=beta&filter=$($filters)" -tenantid $TenantFilter -erroraction stop | Select-Object userPrincipalName, clientAppUsed, Status | Sort-Object -Unique -Property userPrincipalName
$response = $GraphRequest
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Retrieved basic authentication report' -Sev 'Debug' -tenant $TenantFilter
-
+
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuthAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuthAllTenants.ps1
index e4be4bafbb02..26d93e02b387 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuthAllTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListBasicAuthAllTenants.ps1
@@ -3,13 +3,15 @@ using namespace System.Net
Function Invoke-ListBasicAuthAllTenants {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.AuditLog.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
- Get-Tenants | ForEach-Object -Parallel {
+
+ Get-Tenants | ForEach-Object -Parallel {
$domainName = $_.defaultDomainName
Import-Module '.\Modules\AzBobbyTables'
Import-Module '.\Modules\CIPPCore'
@@ -36,7 +38,7 @@ Function Invoke-ListBasicAuthAllTenants {
RowKey = $domainName
PartitionKey = 'basicauth'
}
- }
+ }
$Table = Get-CIPPTable -TableName cachebasicauth
Add-CIPPAzDataTableEntity @Table -Entity $GraphRequest -Force | Out-Null
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-Z_CIPPHttpTrigger.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-Z_CIPPHttpTrigger.ps1
deleted file mode 100644
index 9f0083676d1e..000000000000
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-Z_CIPPHttpTrigger.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-function Invoke-Z_CIPPHttpTrigger {
- <#
- .FUNCTIONALITY
- Entrypoint
- #>
- Param(
- $Request,
- $TriggerMetadata
- )
-
- $FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint
-
- Write-Host "Function: $($Request.Params.CIPPEndpoint)"
-
- $HttpTrigger = @{
- Request = $Request
- TriggerMetadata = $TriggerMetadata
- }
-
- if (Get-Command -Name $FunctionName -ErrorAction SilentlyContinue) {
- & $FunctionName @HttpTrigger
- } else {
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::NotFound
- Body = 'Endpoint not found'
- })
- }
-}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ExecAlertsList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1
similarity index 97%
rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ExecAlertsList.ps1
rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1
index 1b6141e1fcda..f3580ec3fc19 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ExecAlertsList.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAlertsList {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Alert.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -26,7 +28,7 @@ Function Invoke-ExecAlertsList {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
$GraphRequest = if ($TenantFilter -ne 'AllTenants') {
- $Alerts = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/alerts' -tenantid $TenantFilter
+ $Alerts = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/alerts' -tenantid $TenantFilter
$AlertsObj = foreach ($Alert In $alerts) {
@{
Tenant = $TenantFilter
@@ -42,7 +44,7 @@ Function Invoke-ExecAlertsList {
}
}
- $DisplayableAlerts = New-FlatArray $AlertsObj | Where-Object { $_.Id -ne $null } | Sort-Object -Property EventDateTime -Descending
+ $DisplayableAlerts = New-FlatArray $AlertsObj | Where-Object { $_.Id -ne $null } | Sort-Object -Property EventDateTime -Descending
[PSCustomObject]@{
NewAlertsCount = $DisplayableAlerts | Where-Object { $_.Status -eq 'newAlert' } | Measure-Object | Select-Object -ExpandProperty Count
@@ -79,7 +81,7 @@ Function Invoke-ExecAlertsList {
InvolvedUsers = $AlertInfo.userStates
}
}
- $DisplayableAlerts = New-FlatArray $AlertsObj | Where-Object { $_.Id -ne $null } | Sort-Object -Property EventDateTime -Descending
+ $DisplayableAlerts = New-FlatArray $AlertsObj | Where-Object { $_.Id -ne $null } | Sort-Object -Property EventDateTime -Descending
[PSCustomObject]@{
NewAlertsCount = $DisplayableAlerts | Where-Object { $_.Status -eq 'newAlert' } | Measure-Object | Select-Object -ExpandProperty Count
InProgressAlertsCount = $DisplayableAlerts | Where-Object { $_.Status -eq 'inProgress' } | Measure-Object | Select-Object -ExpandProperty Count
@@ -103,6 +105,6 @@ Function Invoke-ExecAlertsList {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = $Body
- })
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsListAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsListAllTenants.ps1
index fc14d337dc28..cbab4f74d8ad 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsListAllTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsListAllTenants.ps1
@@ -3,20 +3,22 @@ using namespace System.Net
Function Invoke-ExecAlertsListAllTenants {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Alert.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
- Get-Tenants | ForEach-Object -Parallel {
+
+ Get-Tenants | ForEach-Object -Parallel {
$domainName = $_.defaultDomainName
Import-Module '.\Modules\AzBobbyTables'
Import-Module '.\Modules\CIPPCore'
$Table = Get-CIPPTable -TableName 'cachealertsandincidents'
try {
- $Alerts = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/alerts' -tenantid $domainName
+ $Alerts = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/alerts' -tenantid $domainName
foreach ($Alert in $Alerts) {
$GUID = (New-Guid).Guid
$alertJson = $Alert | ConvertTo-Json
@@ -33,7 +35,7 @@ Function Invoke-ExecAlertsListAllTenants {
} catch {
$GUID = (New-Guid).Guid
$AlertText = ConvertTo-Json -InputObject @{
- Title = "Could not connect to tenant to retrieve data: $($_.Exception.Message)"
+ Title = "Could not connect to tenant to retrieve data: $($_.Exception.Message)"
Id = ''
Category = ''
EventDateTime = ''
@@ -46,7 +48,7 @@ Function Invoke-ExecAlertsListAllTenants {
}
}
$GraphRequest = @{
- Alert = [string]$AlertText
+ Alert = [string]$AlertText
RowKey = [string]$GUID
PartitionKey = 'alert'
Tenant = $domainName
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsList.ps1
index e3bb573809ef..184f629f2b2c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsList.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsList.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecIncidentsList {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Incident.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-ExecIncidentsList {
$GraphRequest = if ($TenantFilter -ne 'AllTenants') {
$incidents = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/incidents' -tenantid $Request.Query.TenantFilter -AsApp $true
- foreach ($incident in $incidents) {
+ foreach ($incident in $incidents) {
[PSCustomObject]@{
Tenant = $Request.Query.TenantFilter
Id = $incident.id
@@ -33,7 +35,7 @@ Function Invoke-ExecIncidentsList {
Tags = ($IncidentObj.tags -join ', ')
Comments = $incident.comments
}
- }
+ }
} else {
$Table = Get-CIPPTable -TableName cachealertsandincidents
$Filter = "PartitionKey eq 'Incident'"
@@ -45,8 +47,8 @@ Function Invoke-ExecIncidentsList {
}
} else {
$incidents = $Rows
- foreach ($incident in $incidents) {
- $IncidentObj = $incident.Incident | ConvertFrom-Json
+ foreach ($incident in $incidents) {
+ $IncidentObj = $incident.Incident | ConvertFrom-Json
[PSCustomObject]@{
Tenant = $incident.Tenant
Id = $IncidentObj.id
@@ -63,7 +65,7 @@ Function Invoke-ExecIncidentsList {
Tags = ($IncidentObj.tags -join ', ')
Comments = @($IncidentObj.comments)
}
- }
+ }
}
}
} catch {
@@ -79,6 +81,6 @@ Function Invoke-ExecIncidentsList {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = $Body
- })
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsListAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsListAllTenants.ps1
index 25e24aa519ec..73421bb577fd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsListAllTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecIncidentsListAllTenants.ps1
@@ -3,13 +3,15 @@ using namespace System.Net
Function Invoke-ExecIncidentsListAllTenants {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Incident.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
- Get-Tenants | ForEach-Object -Parallel {
+
+ Get-Tenants | ForEach-Object -Parallel {
$domainName = $_.defaultDomainName
Import-Module '.\Modules\AzBobbyTables'
Import-Module '.\Modules\CIPPCore'
@@ -17,7 +19,7 @@ Function Invoke-ExecIncidentsListAllTenants {
try {
$incidents = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/incidents' -tenantid $domainName -AsApp $true
- $GraphRequest = foreach ($incident in $incidents) {
+ $GraphRequest = foreach ($incident in $incidents) {
$GUID = (New-Guid).Guid
$GraphRequest = @{
Incident = [string]($incident | ConvertTo-Json -Depth 10)
@@ -26,7 +28,7 @@ Function Invoke-ExecIncidentsListAllTenants {
Tenant = [string]$domainName
}
Add-CIPPAzDataTableEntity @Table -Entity $GraphRequest -Force | Out-Null
- }
+ }
} catch {
$GUID = (New-Guid).Guid
@@ -43,7 +45,7 @@ Function Invoke-ExecIncidentsListAllTenants {
severity = 'CIPP'
}
$GraphRequest = @{
- Incident = [string]$AlertText
+ Incident = [string]$AlertText
RowKey = [string]$GUID
PartitionKey = 'Incident'
Tenant = [string]$domainName
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityAlert.ps1
index 1a13261e7c03..da3bc31ab858 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityAlert.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSetSecurityAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Alert.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-ExecSetSecurityAlert {
$AlertFilter = $Request.Query.GUID
$Status = $Request.Query.Status
$AssignBody = '{"status":"' + $Status + '","vendorInformation":{"provider":"' + $Request.query.provider + '","vendor":"' + $Request.query.vendor + '"}}'
- try {
+ try {
$GraphRequest = New-Graphpostrequest -uri "https://graph.microsoft.com/beta/security/alerts/$AlertFilter" -type PATCH -tenantid $TenantFilter -body $Assignbody
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Set alert $AlertFilter to status $Status" -Sev 'Info'
$body = [pscustomobject]@{'Results' = "Set status for alert to $Status" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityIncident.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityIncident.ps1
index 64b2ad0b6bcf..b1065f721a29 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityIncident.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecSetSecurityIncident.ps1
@@ -1,79 +1,81 @@
using namespace System.Net
Function Invoke-ExecSetSecurityIncident {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Security.Incident.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $first = ''
- # Interact with query parameters or the body of the request.
- $tenantfilter = $Request.Query.TenantFilter
- $IncidentFilter = $Request.Query.GUID
- $Status = $Request.Query.Status
- $Assigned = $Request.Query.Assigned
- $Classification = $Request.Query.Classification
- $Determination = $Request.Query.Determination
- $Redirected = $Request.Query.Redirected -as [int]
- $BodyBuild
- $AssignBody = '{'
+ $first = ''
+ # Interact with query parameters or the body of the request.
+ $tenantfilter = $Request.Query.TenantFilter
+ $IncidentFilter = $Request.Query.GUID
+ $Status = $Request.Query.Status
+ $Assigned = $Request.Query.Assigned
+ $Classification = $Request.Query.Classification
+ $Determination = $Request.Query.Determination
+ $Redirected = $Request.Query.Redirected -as [int]
+ $BodyBuild
+ $AssignBody = '{'
- try {
- # We won't update redirected incidents because the incident it is redirected to should instead be updated
- if ($Redirected -lt 1) {
- # Set received status
- if ($null -ne $Status) {
- $AssignBody += $first + '"status":"' + $Status + '"'
- $BodyBuild += $first + 'Set status for incident to ' + $Status
- $first = ', '
- }
+ try {
+ # We won't update redirected incidents because the incident it is redirected to should instead be updated
+ if ($Redirected -lt 1) {
+ # Set received status
+ if ($null -ne $Status) {
+ $AssignBody += $first + '"status":"' + $Status + '"'
+ $BodyBuild += $first + 'Set status for incident to ' + $Status
+ $first = ', '
+ }
- # Set received classification and determination
- if ($null -ne $Classification) {
- if ($null -eq $Determination) {
- # Maybe some poindexter tries to send a classification without a determination
- throw
- }
+ # Set received classification and determination
+ if ($null -ne $Classification) {
+ if ($null -eq $Determination) {
+ # Maybe some poindexter tries to send a classification without a determination
+ throw
+ }
- $AssignBody += $first + '"classification":"' + $Classification + '", "determination":"' + $Determination + '"'
- $BodyBuild += $first + 'Set classification & determination for incident to ' + $Classification + ' ' + $Determination
- $first = ', '
- }
+ $AssignBody += $first + '"classification":"' + $Classification + '", "determination":"' + $Determination + '"'
+ $BodyBuild += $first + 'Set classification & determination for incident to ' + $Classification + ' ' + $Determination
+ $first = ', '
+ }
- # Set received asignee
- if ($null -ne $Assigned) {
- $AssignBody += $first + '"assignedTo":"' + $Assigned + '"'
- if ($null -eq $Status) {
- $BodyBuild += $first + 'Set assigned for incident to ' + $Assigned
- }
- $first = ', '
- }
+ # Set received asignee
+ if ($null -ne $Assigned) {
+ $AssignBody += $first + '"assignedTo":"' + $Assigned + '"'
+ if ($null -eq $Status) {
+ $BodyBuild += $first + 'Set assigned for incident to ' + $Assigned
+ }
+ $first = ', '
+ }
- $AssignBody += '}'
+ $AssignBody += '}'
- $ResponseBody = [pscustomobject]@{'Results' = $BodyBuild }
- New-Graphpostrequest -uri "https://graph.microsoft.com/beta/security/incidents/$IncidentFilter" -type PATCH -tenantid $TenantFilter -body $Assignbody -asApp $true
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Update incident $IncidentFilter with values $Assignbody" -Sev 'Info'
- } else {
- $ResponseBody = [pscustomobject]@{'Results' = 'Cannot update redirected incident' }
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Refuse to pdate incident $IncidentFilter with values $Assignbody because it is redirected to another incident" -Sev 'Info'
- }
+ $ResponseBody = [pscustomobject]@{'Results' = $BodyBuild }
+ New-Graphpostrequest -uri "https://graph.microsoft.com/beta/security/incidents/$IncidentFilter" -type PATCH -tenantid $TenantFilter -body $Assignbody -asApp $true
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Update incident $IncidentFilter with values $Assignbody" -Sev 'Info'
+ } else {
+ $ResponseBody = [pscustomobject]@{'Results' = 'Cannot update redirected incident' }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Refuse to pdate incident $IncidentFilter with values $Assignbody because it is redirected to another incident" -Sev 'Info'
+ }
- $body = $ResponseBody
- } catch {
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Failed to update alert $($AlertFilter): $($_.Exception.Message)" -Sev 'Error'
- $body = [pscustomobject]@{'Results' = "Failed to update incident: $($_.Exception.Message)" }
- }
+ $body = $ResponseBody
+ } catch {
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($tenantfilter) -message "Failed to update alert $($AlertFilter): $($_.Exception.Message)" -Sev 'Error'
+ $body = [pscustomobject]@{'Results' = "Failed to update incident: $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $body
- })
+ # 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/Teams-Sharepoint/Invoke-AddTeam.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1
index 34b9bda58208..ea3412dd22b4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddTeam {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Teams.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,7 +20,7 @@ Function Invoke-AddTeam {
$Owners = ($userobj.owner).Split([Environment]::NewLine) | Where-Object { $_ -ne $null -or $_ -ne '' }
try {
-
+
$Owners = $Owners | ForEach-Object {
$OwnerID = "https://graph.microsoft.com/beta/users('" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$_" -tenantid $Userobj.tenantid).id + "')"
@{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1
index 0a031a0af5d3..c52f4c1b1409 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSetSharePointMember {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Sharepoint.Site.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1
index 398f070db9ee..542dfb665b9f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1
@@ -1,26 +1,28 @@
using namespace System.Net
Function Invoke-ExecSharePointOwner {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Sharepoint.Site.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- $tenantFilter = $Request.Body.TenantFilter
- try {
- $State = Set-CIPPSharePointOwner -tenantFilter $tenantFilter -userid $request.body.UPN -OnedriveAccessUser $request.body.input -ExecutingUser $ExecutingUser -APIName $APIName -RemovePermission $request.body.RemovePermission -URL $Request.Body.URL
- $Results = [pscustomobject]@{'Results' = "$State" }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ $APIName = $TriggerMetadata.FunctionName
+ $tenantFilter = $Request.Body.TenantFilter
+ try {
+ $State = Set-CIPPSharePointOwner -tenantFilter $tenantFilter -userid $request.body.UPN -OnedriveAccessUser $request.body.input -ExecutingUser $ExecutingUser -APIName $APIName -RemovePermission $request.body.RemovePermission -URL $Request.Body.URL
+ $Results = [pscustomobject]@{'Results' = "$State" }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1
index e769c7ee9879..2b04807cd4e1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSharepointSettings {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Sharepoint.Admin.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -21,7 +23,7 @@ Function Invoke-ListSharepointSettings {
$USERToGet = $Request.query.usertoGet
$body = '{"isResharingByExternalUsersEnabled": "False"}'
$Request = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -Type patch -Body $body -ContentType 'application/json'
-
+
Write-LogMessage -API 'Standards' -tenant $tenantFilter -message 'Disabled Password Expiration' -sev Info
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
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 48f3f8badb80..7b5ac0cd37b7 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSites {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Sharepoint.Site.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,7 +22,7 @@ Function Invoke-ListSites {
$type = $request.query.Type
$UserUPN = $request.query.UserUPN
try {
- $Result = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/get$($type)Detail(period='D7')" -tenantid $TenantFilter | ConvertFrom-Csv
+ $Result = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/get$($type)Detail(period='D7')" -tenantid $TenantFilter | ConvertFrom-Csv
if ($UserUPN) {
$ParsedRequest = $Result | Where-Object { $_.'Owner Principal Name' -eq $UserUPN }
@@ -37,7 +39,7 @@ Function Invoke-ListSites {
@{ Name = 'Template'; Expression = { $_.'Root Web Template' } },
@{ Name = 'siteid'; Expression = { $_.'site Id' } }
- #Temporary workaround for url as report is broken.
+ #Temporary workaround for url as report is broken.
#This API is so stupid its great.
$URLs = (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/sites/getAllSites?$select=SharePointIds' -asapp $true -tenantid $TenantFilter).SharePointIds
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 c5969ad1d8ae..743568fe8bed 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTeams {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Teams.Group.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -37,7 +39,7 @@ Function Invoke-ListTeams {
Members = @($Members)
Owners = @($owners)
InstalledApps = @($AppsList)
- }
+ }
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1
index 944fb90c7bf7..426131cc047d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1
@@ -3,12 +3,14 @@ using namespace System.Net
Function Invoke-ListTeamsActivity {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Teams.Activity.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
+
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1
index ef5e1ca9d3d2..ec33ee67e86e 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTeamsVoice {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Teams.Voice.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -24,11 +26,11 @@ Function Invoke-ListTeamsVoice {
$CompleteRequest = $_ | Select-Object *, 'AssignedTo'
$CompleteRequest.AcquisitionDate = $CompleteRequest.AcquisitionDate -split 'T' | Select-Object -First 1
- if ($CompleteRequest.TargetId -eq '00000000-0000-0000-0000-000000000000') {
+ if ($CompleteRequest.TargetId -eq '00000000-0000-0000-0000-000000000000') {
$CompleteRequest.AssignedTo = 'Unassigned'
} else {
$CompleteRequest.AssignedTo = ($users | Where-Object -Property Id -EQ $CompleteRequest.TargetId).userPrincipalName
-
+
}
$CompleteRequest
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1
index ab279d752d81..2cbba9b5fa42 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1
index 4cbcff576e97..9b0e5aab48bb 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAlertsQueue {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -15,29 +17,42 @@ Function Invoke-ListAlertsQueue {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
$WebhookTable = Get-CIPPTable -TableName 'WebhookRules'
- $WebhookRules = Get-CIPPAzDataTableEntity @WebhookTable
+ $WebhookRules = Get-CIPPAzDataTableEntity @WebhookTable
$ScheduledTasks = Get-CIPPTable -TableName 'ScheduledTasks'
$ScheduledTasks = Get-CIPPAzDataTableEntity @ScheduledTasks | Where-Object { $_.hidden -eq $true }
+ $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
+ $TenantList = Get-Tenants -IncludeErrors
$AllTasksArrayList = [system.collections.generic.list[object]]::new()
foreach ($Task in $WebhookRules) {
$Conditions = $Task.Conditions | ConvertFrom-Json -ErrorAction SilentlyContinue
$TranslatedConditions = ($Conditions | ForEach-Object { "When $($_.Property.label) is $($_.Operator.label) $($_.input.value)" }) -join ' and '
$TranslatedActions = ($Task.Actions | ConvertFrom-Json -ErrorAction SilentlyContinue).label -join ','
+ $Tenants = ($Task.Tenants | ConvertFrom-Json -ErrorAction SilentlyContinue).fullValue
$TaskEntry = [PSCustomObject]@{
- Tenants = ($Task.Tenants | ConvertFrom-Json -ErrorAction SilentlyContinue).fullValue.defaultDomainName -join ','
+ Tenants = $Tenants.defaultDomainName -join ','
Conditions = $TranslatedConditions
- Actions = $TranslatedActions
+ Actions = $TranslatedActions
LogType = $Task.type
EventType = 'Audit log Alert'
RowKey = $Task.RowKey
PartitionKey = $Task.PartitionKey
RepeatsEvery = 'When received'
}
- $AllTasksArrayList.Add($TaskEntry)
- }
+
+ if ($AllowedTenants -notcontains 'AllTenants') {
+ foreach ($Tenant in $Tenants) {
+ if ($AllowedTenants -contains $Tenant.customerId) {
+ $AllTasksArrayList.Add($TaskEntry)
+ break
+ }
+ }
+ } else {
+ $AllTasksArrayList.Add($TaskEntry)
+ }
+ }
foreach ($Task in $ScheduledTasks) {
$TaskEntry = [PSCustomObject]@{
@@ -50,7 +65,14 @@ Function Invoke-ListAlertsQueue {
EventType = 'Scheduled Task'
RepeatsEvery = $Task.Recurrence
}
- $AllTasksArrayList.Add($TaskEntry)
+ if ($AllowedTenants -notcontains 'AllTenants') {
+ $Tenant = $TenantList | Where-Object -Property defaultDomainName -EQ $Task.Tenant
+ if ($AllowedTenants -contains $Tenant.customerId) {
+ $AllTasksArrayList.Add($TaskEntry)
+ }
+ } else {
+ $AllTasksArrayList.Add($TaskEntry)
+ }
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1
index d585504f4254..1741ed98fcaf 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListWebhookAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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 a65084e28bdc..78cded90ff19 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
@@ -12,6 +12,7 @@ function Invoke-PublicWebhooks {
$Webhooks = Get-CIPPAzDataTableEntity @WebhookTable
Write-Host 'Received request'
$url = ($request.headers.'x-ms-original-url').split('/API') | Select-Object -First 1
+ $CIPPURL = [string]$url
Write-Host $url
if ($Webhooks.Resource -eq 'M365AuditLogs') {
Write-Host "Found M365AuditLogs - This is an old entry, we'll deny so Microsoft stops sending it."
@@ -73,13 +74,13 @@ function Invoke-PublicWebhooks {
$TenantFilter = (Get-Tenants | Where-Object -Property customerId -EQ $ReceivedItem.TenantId).defaultDomainName
Write-Host "Webhook TenantFilter: $TenantFilter"
$ConfigTable = get-cipptable -TableName 'WebhookRules'
- $Configuration = (Get-CIPPAzDataTableEntity @ConfigTable) | Where-Object { $_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants' } | ForEach-Object {
+ $Configuration = (Get-CIPPAzDataTableEntity @ConfigTable) | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') -and $_.Type -eq $ReceivedItem.ContentType } | ForEach-Object {
[pscustomobject]@{
Tenants = ($_.Tenants | ConvertFrom-Json).fullValue
Conditions = $_.Conditions
Actions = $_.Actions
LogType = $_.Type
- }
+ }
}
if (!$Configuration.Tenants) {
Write-Host 'No tenants found for this webhook, probably an old entry. Skipping.'
@@ -93,28 +94,27 @@ function Invoke-PublicWebhooks {
continue
}
-
$PreProccessedData = $Data | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties -ErrorAction SilentlyContinue
$LocationTable = Get-CIPPTable -TableName 'knownlocationdb'
$ProcessedData = foreach ($Data in $PreProccessedData) {
if ($Data.ExtendedProperties) {
$Data.CIPPExtendedProperties = ($Data.ExtendedProperties | ConvertTo-Json)
- $Data.ExtendedProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
+ $Data.ExtendedProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
}
- if ($Data.DeviceProperties) {
+ if ($Data.DeviceProperties) {
$Data.CIPPDeviceProperties = ($Data.DeviceProperties | ConvertTo-Json)
- $Data.DeviceProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
+ $Data.DeviceProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
}
- if ($Data.parameters) {
+ if ($Data.parameters) {
$Data.CIPPParameters = ($Data.parameters | ConvertTo-Json)
- $Data.parameters | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
+ $Data.parameters | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue }
}
- if ($Data.ModifiedProperties) {
+ if ($Data.ModifiedProperties) {
$Data.CIPPModifiedProperties = ($Data.ModifiedProperties | ConvertTo-Json)
- $Data.ModifiedProperties | ForEach-Object { $data | Add-Member -NotePropertyName "$($_.Name)" -NotePropertyValue "$($_.NewValue)" -Force -ErrorAction SilentlyContinue }
+ $Data.ModifiedProperties | ForEach-Object { $data | Add-Member -NotePropertyName "$($_.Name)" -NotePropertyValue "$($_.NewValue)" -Force -ErrorAction SilentlyContinue }
}
if ($Data.ModifiedProperties) { $Data.ModifiedProperties | ForEach-Object { $data | Add-Member -NotePropertyName $("Previous_Value_$($_.Name)") -NotePropertyValue "$($_.OldValue)" -Force -ErrorAction SilentlyContinue } }
-
+
if ($data.clientip) {
if ($data.clientip -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$') {
$data.clientip = $data.clientip -replace ':\d+$', '' # Remove the port number if present
@@ -150,7 +150,7 @@ function Invoke-PublicWebhooks {
$null = Add-CIPPAzDataTableEntity @LocationTable -Entity $LocationInfo -Force
} catch {
Write-Host "Webhook: Failed to add location info for $($data.clientip) to cache: $($_.Exception.Message)"
-
+
}
}
$Data.CIPPGeoLocation = $Country
@@ -165,28 +165,30 @@ function Invoke-PublicWebhooks {
#Filter data based on conditions.
$Where = $Configuration | ForEach-Object {
$conditions = $_.Conditions | ConvertFrom-Json | Where-Object { $_.Input.value -ne '' }
- $actions = $_.Actions
- $conditionStrings = foreach ($condition in $conditions) {
- $value = if ($condition.Input.value -is [array]) {
+ $actions = $_.Actions
+ $conditionStrings = [System.Collections.Generic.List[string]]::new()
+ $CIPPClause = [System.Collections.Generic.List[string]]::new()
+ foreach ($condition in $conditions) {
+ $value = if ($condition.Input.value -is [array]) {
$arrayAsString = $condition.Input.value | ForEach-Object {
- "'$_'"
- }
+ "'$_'"
+ }
"@($($arrayAsString -join ', '))"
} else { "'$($condition.Input.value)'" }
- "`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value"
- }
- if ($conditionStrings.Count -gt 1) {
- $finalCondition = $conditionStrings -join ' -AND '
- } else {
- $finalCondition = $conditionStrings
+
+ $conditionStrings.Add("`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value")
+ $CIPPClause.Add("$($condition.Property.label) is $($condition.Operator.label) $value")
}
+ $finalCondition = $conditionStrings -join ' -AND '
+
[PSCustomObject]@{
clause = $finalCondition
expectedAction = $actions
+ CIPPClause = $CIPPClause
}
-
+
}
- Write-Host "Webhook: The list of operations in the data are $($ProcessedData.operation -join ', ')"
+ Write-Host "Webhook: The list of operations in the data are $($ProcessedData.operation -join ', ')"
$DataToProcess = foreach ($clause in $Where) {
Write-Host "Webhook: Processing clause: $($clause.clause)"
@@ -195,7 +197,7 @@ function Invoke-PublicWebhooks {
if ($ReturnedData) {
$ReturnedData = foreach ($item in $ReturnedData) {
$item.CIPPAction = $clause.expectedAction
- $item.CIPPClause = ($clause.clause | ForEach-Object { "When $($_.Property.label) is $($_.Operator.label) $($_.input.value)" }) -join ' and '
+ $item.CIPPClause = $clause.CIPPClause -join ' and '
$item
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1
index 7552c2afe222..3a52f5dacdfd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveQueuedAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -24,7 +26,7 @@ Function Invoke-RemoveQueuedAlert {
$Alert = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey
Remove-AzDataTableEntity @Table -Entity $Alert
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed application queue for $ID." -Sev 'Info'
-
+
$body = [pscustomobject]@{'Results' = 'Successfully removed from queue.' }
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove from queue $ID. $($_.Exception.Message)" -Sev 'Error'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1
index ef76692431bb..08124ad41683 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1
@@ -4,6 +4,8 @@ function Invoke-ExecAddMultiTenantApp {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ Tenant.Application.ReadWrite
#>
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1
index 561d060eb99b..b79ef41afb72 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecAppApproval {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Application.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-ExecAppApproval {
Write-Host "$($Request.query.ID)"
# Interact with query parameters or the body of the request.
- $applicationid = if ($request.query.applicationid) { $request.query.applicationid } else { $env:ApplicationID }
+ $applicationid = if ($request.query.applicationid) { $request.query.applicationid } else { $env:ApplicationID }
$Results = get-tenants | ForEach-Object {
[PSCustomObject]@{
defaultDomainName = $_.defaultDomainName
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1
index de779bfe083d..b52867e7f0da 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1
@@ -1,29 +1,31 @@
using namespace System.Net
Function Invoke-ExecAddSPN {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Administration.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Interact with query parameters or the body of the request.
- $Body = if ($Request.Query.Enable) { '{"accountEnabled":"true"}' } else { '{"accountEnabled":"false"}' }
- try {
- $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $ENV:TenantID -type POST -Body "{ `"appId`": `"2832473f-ec63-45fb-976f-5d45a7d4bb91`" }" -NoAuthCheck $true
- $Results = [pscustomobject]@{'Results' = "Successfully completed request. Add your GDAP migration permissions to your SAM application here: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$($ENV:ApplicationID)/isMSAApp/ " }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed to add SPN. Please manually execute 'New-AzureADServicePrincipal -AppId 2832473f-ec63-45fb-976f-5d45a7d4bb91' The error was $($_.Exception.Message)" }
- }
+ # Interact with query parameters or the body of the request.
+ $Body = if ($Request.Query.Enable) { '{"accountEnabled":"true"}' } else { '{"accountEnabled":"false"}' }
+ try {
+ $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $ENV:TenantID -type POST -Body "{ `"appId`": `"2832473f-ec63-45fb-976f-5d45a7d4bb91`" }" -NoAuthCheck $true
+ $Results = [pscustomobject]@{'Results' = "Successfully completed request. Add your GDAP migration permissions to your SAM application here: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$($ENV:ApplicationID)/isMSAApp/ " }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed to add SPN. Please manually execute 'New-AzureADServicePrincipal -AppId 2832473f-ec63-45fb-976f-5d45a7d4bb91' The error was $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1
index 7b02b9aa1f74..adcb580e45cf 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecOffboardTenant {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Administration.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -23,7 +25,7 @@ Function Invoke-ExecOffboardTenant {
try {
try {
$domains = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/domains?`$select=id" -tenantid $env:TenantID -NoAuthCheck:$true).id
- $CSPGuestUsers = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/users?`$select=id,mail&`$filter=userType eq 'Guest' and $(($domains | ForEach-Object { "endswith(mail, '$_')" }) -join ' or ')&`$count=true" -tenantid $Tenantfilter -ComplexFilter)
+ $CSPGuestUsers = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/users?`$select=id,mail&`$filter=userType eq 'Guest' and $(($domains | ForEach-Object { "endswith(mail, '$_')" }) -join ' or ')&`$count=true" -tenantid $Tenantfilter -ComplexFilter)
} catch {
$errors.Add("Failed to retrieve guest users: $($_.Exception.message)")
}
@@ -57,28 +59,28 @@ Function Invoke-ExecOffboardTenant {
} catch {
throw "Failed to retrieve CSP domains: $($_.Exception.message)"
}
-
+
try {
# Get /organization data
$orgContacts = New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/organization?`$select=id,marketingNotificationEmails,securityComplianceNotificationMails,technicalNotificationMails" -tenantid $TenantFilter
-
+
} catch {
throw "Failed to retrieve CSP domains: $($_.Exception.message)"
}
} catch {
$errors.Add("$($_.Exception.message)")
}
-
+
# foreach through the properties we want to check/update
@('marketingNotificationEmails','securityComplianceNotificationMails','technicalNotificationMails') | ForEach-Object {
$property = $_
$propertyContacts = $orgContacts.($($property))
-
+
if ($propertyContacts -AND ($domains -notcontains ($propertyContacts | ForEach-Object { $_.Split("@")[1] }))) {
$newPropertyContent = [System.Collections.Generic.List[object]]($propertyContacts | Where-Object { $domains -notcontains $_.Split("@")[1] })
-
+
$patchContactBody = if (!($newPropertyContent)) { "{ `"$($property)`" : [] }" } else { [pscustomobject]@{ $property = $newPropertyContent } | ConvertTo-Json }
-
+
try {
New-GraphPostRequest -type PATCH -body $patchContactBody -Uri "https://graph.microsoft.com/v1.0/organization/$($orgContacts.id)" -tenantid $Tenantfilter -ContentType "application/json"
$results.Add("Succesfully removed notification contacts from $($property): $(($propertyContacts | Where-Object { $domains -contains $_.Split("@")[1] }))")
@@ -91,9 +93,9 @@ Function Invoke-ExecOffboardTenant {
}
}
# Add logic for privacyProfile later - rvdwegen
-
+
}
-
+
if ($request.body.RemoveVendorApps) {
$request.body.RemoveVendorApps | ForEach-Object {
try {
@@ -104,7 +106,7 @@ Function Invoke-ExecOffboardTenant {
#$results.Add("Failed to removed app $($_.displayName)")
$errors.Add("Failed to removed app $($_.label)")
}
- }
+ }
}
# All customer tenant specific actions ALWAYS have to be completed before this action!
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOnboardTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOnboardTenant.ps1
index 84492fe68a70..10c11f90575a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOnboardTenant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOnboardTenant.ps1
@@ -4,6 +4,8 @@ function Invoke-ExecOnboardTenant {
<#
.FUNCTIONALITY
Entrypoint
+ .ROLE
+ Tenant.Administration.ReadWrite
#>
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1
new file mode 100644
index 000000000000..26bc7332a928
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1
@@ -0,0 +1,35 @@
+using namespace System.Net
+
+Function Invoke-ExecUpdateSecureScore {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Tenant.Administration.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+
+ # Interact with query parameters or the body of the request.
+ $Body = @{
+ comment = $request.body.reason
+ state = $request.body.resolutionType
+ vendorInformation = $request.body.vendorInformation
+ }
+ try {
+ $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/security/secureScoreControlProfiles/$($Request.body.ControlName)" -tenantid $Request.body.TenantFilter -type PATCH -Body $($Body | ConvertTo-Json -Compress)
+ $Results = [pscustomobject]@{'Results' = "Succesfully set control to $($body.state) " }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed to set Control to $($body.state) $($_.Exception.Message)" }
+ }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1
index 9cfc10853e23..7e8a8603896d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1
@@ -3,14 +3,16 @@ using namespace System.Net
function Invoke-ListAppConsentRequests {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Administration.Read
#>
param($Request, $TriggerMetadata)
$APIName = $TriggerMetadata.FunctionName
$TenantFilter = $Request.Query.TenantFilter
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
-
+
try {
if ($Request.Query.TenantFilter -eq 'AllTenants') {
throw 'AllTenants is not yet supported'
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1
index c3fbd33947af..f8821c051a8a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1
@@ -1,4 +1,10 @@
function Invoke-ListTenantOnboarding {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Tenant.Administration.Read
+ #>
Param(
$Request,
$TriggerMetadata
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-UpdateSecureScore.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-UpdateSecureScore.ps1
deleted file mode 100644
index b1ffb9bee098..000000000000
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-UpdateSecureScore.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-using namespace System.Net
-
-Function Invoke-ExecUpdateSecureScore {
- <#
- .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'
-
- # Interact with query parameters or the body of the request.
- $Body = @{
- comment = $request.body.reason
- state = $request.body.resolutionType
- vendorInformation = $request.body.vendorInformation
- }
- try {
- $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/security/secureScoreControlProfiles/$($Request.body.ControlName)" -tenantid $Request.body.TenantFilter -type PATCH -Body $($Body | ConvertTo-Json -Compress)
- $Results = [pscustomobject]@{'Results' = "Succesfully set control to $($body.state) " }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed to set Control to $($body.state) $($_.Exception.Message)" }
- }
-
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
-
-}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1
index 77db47a5ff51..fe98eae2eee1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditTenant {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -30,11 +32,11 @@ Function Invoke-EditTenant {
if ($tenantObjectId) {
try {
$bodyToPatch = '{"displayName":"' + $tenantDisplayName + '","defaultDomainName":"' + $tenantDefaultDomainName + '"}'
- $patchTenant = (Invoke-RestMethod -Method PATCH -Uri "https://graph.windows.net/myorganization/contracts/$($tenantObjectId.objectId)?api-version=1.6" -Body $bodyToPatch -ContentType 'application/json' -Headers $AADGraphtoken -ErrorAction Stop)
+ $patchTenant = (Invoke-RestMethod -Method PATCH -Uri "https://graph.windows.net/myorganization/contracts/$($tenantObjectId.objectId)?api-version=1.6" -Body $bodyToPatch -ContentType 'application/json' -Headers $AADGraphtoken -ErrorAction Stop)
$Filter = "PartitionKey eq 'Tenants' and defaultDomainName eq '{0}'" -f $tenantDefaultDomainName
try {
$TenantsTable = Get-CippTable -tablename Tenants
- $Tenant = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter
+ $Tenant = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter
$Tenant.displayName = $tenantDisplayName
Update-AzDataTableEntity @TenantsTable -Entity $Tenant
}
@@ -44,7 +46,7 @@ Function Invoke-EditTenant {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantDisplayName -message "Edited tenant $tenantDisplayName" -Sev 'Info'
$results = "Successfully amended details for $($Tenant.displayName) $AddedText"
}
- catch {
+ catch {
$results = "Failed to amend details for $tenantDisplayName : $($_.Exception.Message)"
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenantDisplayName -message "Failed amending details $tenantDisplayName. Error:$($_.Exception.Message)" -Sev 'Error'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenantDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenantDetails.ps1
index 9aa191e2e44f..001c8ac2cbcd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenantDetails.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenantDetails.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTenantDetails {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -44,6 +46,6 @@ Function Invoke-ListTenantDetails {
StatusCode = [HttpStatusCode]::OK
Body = $Body
})
-
+
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1
index 3c183a98af86..7e3d3da4e22c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1
@@ -3,37 +3,60 @@ using namespace System.Net
Function Invoke-ListTenants {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $TenantAccess = Test-CIPPAccess -Request $Request -TenantList
+ if ($TenantAccess -notcontains 'AllTenants') {
+ $AllTenantSelector = $false
+ } else {
+ $AllTenantSelector = $Request.Query.AllTenantSelector
+ }
# Clear Cache
- if ($request.Query.ClearCache -eq 'true') {
- Remove-CIPPCache -tenantsOnly $request.query.TenantsOnly
- $GraphRequest = [pscustomobject]@{'Results' = 'Successfully completed request.' }
+ if ($Request.Query.ClearCache -eq $true) {
+ Remove-CIPPCache -tenantsOnly $Request.Query.TenantsOnly
+
+ $InputObject = [PSCustomObject]@{
+ Batch = @(
+ @{
+ FunctionName = 'UpdateTenants'
+ }
+ )
+ OrchestratorName = 'UpdateTenants'
+ SkipLog = $true
+ }
+ Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Compress -Depth 5)
+
+ $GraphRequest = [pscustomobject]@{'Results' = 'Cache has been cleared and a tenant refresh is queued.' }
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $GraphRequest
})
- Get-Tenants -IncludeAll -TriggerRefresh
-
+ #Get-Tenants -IncludeAll -TriggerRefresh
+ return
}
- if ($Request.query.TriggerRefresh) {
+ if ($Request.Query.TriggerRefresh) {
Get-Tenants -IncludeAll -TriggerRefresh
}
try {
$tenantfilter = $Request.Query.TenantFilter
$Tenants = Get-Tenants -IncludeErrors -SkipDomains
+ if ($TenantAccess -notcontains 'AllTenants') {
+ $Tenants = $Tenants | Where-Object -Property customerId -In $TenantAccess
+ }
if ($null -eq $TenantFilter -or $TenantFilter -eq 'null') {
$TenantList = [system.collections.generic.list[object]]::new()
- if ($Request.Query.AllTenantSelector -eq $true) {
+ if ($AllTenantSelector -eq $true) {
$TenantList.Add(@{
customerId = 'AllTenants'
defaultDomainName = 'AllTenants'
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 547828a337f4..7ced88078c10 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddCAPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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 b6de2ac40ed3..b0f64582c5c4 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddCATemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,14 +14,14 @@ Function Invoke-AddCATemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$TenantFilter = $Request.Query.TenantFilter
- try {
+ try {
$GUID = (New-Guid).GUID
$JSON = if ($request.body.rawjson) {
ConvertFrom-Json -InputObject ([pscustomobject]$request.body.rawjson)
} else {
([pscustomobject]$Request.body) | ForEach-Object {
$NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name
- $_ | Select-Object -Property $NonEmptyProperties
+ $_ | Select-Object -Property $NonEmptyProperties
}
}
@@ -85,7 +87,7 @@ Function Invoke-AddCATemplate {
}
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' }
-
+
} catch {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create CA Template: $($_.Exception.Message)" -Sev 'Error'
$body = [pscustomobject]@{'Results' = "Intune Template Deployment failed: $($_.Exception.Message)" }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1
index 578b196ed014..47dd98aa75dd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddNamedLocation {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1
index fb804f8fbfe1..e3baf6e4a607 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-EditCAPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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
index 137c55a9c28b..9bdd61686269 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecCaCheck {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -42,7 +44,7 @@ Function Invoke-ExecCaCheck {
$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
+ $Request
} catch {
"Failed to execute check: $($_.Exception.Message)"
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1
index 4dafed5af25a..86d06bf95796 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecCAExclusion {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -46,6 +48,6 @@ Function Invoke-ExecCAExclusion {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $Body
- })
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1
index 14ec616c0616..7f4be467dd3a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListCAtemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -29,11 +31,11 @@ Function Invoke-ListCAtemplates {
#List new policies
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'CATemplate'"
+ $Filter = "PartitionKey eq 'CATemplate'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
$data = $_.JSON | ConvertFrom-Json -Depth 100
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force
- $data
+ $data
} | Sort-Object -Property displayName
if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property GUID -EQ $Request.query.id }
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1
index c093a8c4f009..9c46ceae1ec4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1
@@ -1,458 +1,455 @@
- using namespace System.Net
+using namespace System.Net
- Function Invoke-ListConditionalAccessPolicies {
+Function Invoke-ListConditionalAccessPolicies {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
-Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug"
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
-function Get-LocationNameFromId {
- [CmdletBinding()]
- param (
- [Parameter()]
- $ID,
-
- [Parameter(Mandatory = $true)]
- $Locations
- )
- if ($id -eq 'All') {
- return 'All'
- }
- $DisplayName = $Locations | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
- if ([string]::IsNullOrEmpty($displayName)) {
- return $ID
- }
- else {
- return $DisplayName
- }
-}
-
-function Get-RoleNameFromId {
- [CmdletBinding()]
- param (
- [Parameter()]
- $ID,
-
- [Parameter(Mandatory = $true)]
- $RoleDefinitions
- )
- if ($id -eq 'All') {
- return 'All'
- }
- $DisplayName = $RoleDefinitions | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
- if ([string]::IsNullOrEmpty($displayName)) {
- return $ID
- }
- else {
- return $DisplayName
- }
-}
+ function Get-LocationNameFromId {
+ [CmdletBinding()]
+ param (
+ [Parameter()]
+ $ID,
-function Get-UserNameFromId {
- [CmdletBinding()]
- param (
- [Parameter()]
- $ID,
-
- [Parameter(Mandatory = $true)]
- $Users
- )
- if ($id -eq 'All') {
- return 'All'
- }
- $DisplayName = $Users | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
- if ([string]::IsNullOrEmpty($displayName)) {
- return $ID
- }
- else {
- return $DisplayName
+ [Parameter(Mandatory = $true)]
+ $Locations
+ )
+ if ($id -eq 'All') {
+ return 'All'
+ }
+ $DisplayName = $Locations | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
+ if ([string]::IsNullOrEmpty($displayName)) {
+ return $ID
+ } else {
+ return $DisplayName
+ }
}
-}
-function Get-GroupNameFromId {
- param (
- [Parameter()]
- $ID,
+ function Get-RoleNameFromId {
+ [CmdletBinding()]
+ param (
+ [Parameter()]
+ $ID,
- [Parameter(Mandatory = $true)]
- $Groups
- )
- if ($id -eq 'All') {
- return 'All'
- }
- $DisplayName = $Groups | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
- if ([string]::IsNullOrEmpty($displayName)) {
- return "No Data"
- }
- else {
- return $DisplayName
+ [Parameter(Mandatory = $true)]
+ $RoleDefinitions
+ )
+ if ($id -eq 'All') {
+ return 'All'
+ }
+ $DisplayName = $RoleDefinitions | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
+ if ([string]::IsNullOrEmpty($displayName)) {
+ return $ID
+ } else {
+ return $DisplayName
+ }
}
-}
-function Get-ApplicationNameFromId {
- [CmdletBinding()]
- param (
- [Parameter()]
- $ID,
-
- [Parameter(Mandatory = $true)]
- $Applications
- )
- if ($id -eq 'All') {
- return 'All'
- }
- switch ($id) {
- 00000004-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Lync' }
- 00000006-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Office365Portal' }
- 00000003-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.SharePoint ' }
- 00000005-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.Workflow' }
- 00000009-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.AnalysisServices' }
- 00000002-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Exchange' }
- 00000007-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.ExchangeOnlineProtection' }
- 00000002-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.ActiveDirectory' }
- 8fca0a66-c008-4564-a876-ab3ae0fd5cff { $return = 'Microsoft.SMIT' }
- 0000000b-0000-0000-c000-000000000000 { $return = 'Microsoft.SellerDashboard' }
- 0000000f-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.GraphExplorer' }
- 0000000c-0000-0000-c000-000000000000 { $return = 'Microsoft App Access Panel' }
- 00000013-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.Portal' }
- 00000010-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.GraphStore' }
- 93ee9413-cf4c-4d4e-814b-a91ff20a01bd { $return = 'Workflow' }
- aa9ecb1e-fd53-4aaa-a8fe-7a54de2c1334 { $return = 'Microsoft.Office365.Configure' }
- 797f4846-ba00-4fd7-ba43-dac1f8f63013 { $return = 'Windows Azure Service Management API' }
- 00000005-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.YammerEnterprise' }
- 601d4e27-7bb3-4dee-8199-90d47d527e1c { $return = 'Microsoft.Office365.ChangeManagement' }
- 6f82282e-0070-4e78-bc23-e6320c5fa7de { $return = 'Microsoft.DiscoveryService' }
- 0f698dd4-f011-4d23-a33e-b36416dcb1e6 { $return = 'Microsoft.OfficeClientService' }
- 67e3df25-268a-4324-a550-0de1c7f97287 { $return = 'Microsoft.OfficeWebAppsService' }
- ab27a73e-a3ba-4e43-8360-8bcc717114d8 { $return = 'Microsoft.OfficeModernCalendar' }
- aedca418-a84d-430d-ab84-0b1ef06f318f { $return = 'Workflow' }
- 595d87a1-277b-4c0a-aa7f-44f8a068eafc { $return = 'Microsoft.SupportTicketSubmission' }
- e3583ad2-c781-4224-9b91-ad15a8179ba0 { $return = 'Microsoft.ExtensibleRealUserMonitoring' }
- b645896d-566e-447e-8f7f-e2e663b5d182 { $return = 'OpsDashSharePointApp' }
- 48229a4a-9f1d-413a-8b96-4c02462c0360 { $return = 'OpsDashSharePointApp' }
- 48717084-a59c-4306-9dc4-3f618dbecdf9 { $return = '"Napa" Office 365 Development Tools' }
- c859ff33-eb41-4ba6-8093-a2c5153bbd7c { $return = 'Workflow' }
- 67cad61c-3411-48d7-ab73-561c64f11ed6 { $return = 'Workflow' }
- 914ed757-9257-4200-b68e-a2bed2f12c5a { $return = 'RbacBackfill' }
- 499b84ac-1321-427f-aa17-267ca6975798 { $return = 'Microsoft.VisualStudio.Online' }
- b2590339-0887-4e94-93aa-13357eb510d7 { $return = 'Workflow' }
- 0000001b-0000-0000-c000-000000000000 { $return = 'Microsoft Power BI Information Service' }
- 89f80565-bfac-4c01-9535-9f0eba332ffe { $return = 'Power BI' }
- 433895fb-4ec7-45c3-a53c-c44d10f80d5b { $return = 'Compromised Account Service' }
- d7c17728-4f1e-4a1e-86cf-7e0adf3fe903 { $return = 'Workflow' }
- 17ef6d31-381f-4783-b186-7b440a3c85c1 { $return = 'Workflow' }
- 00000012-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.RMS' }
- 81ce94d4-9422-4c0d-a4b9-3250659366ce { $return = 'Workflow' }
- 8d3a7d3c-c034-4f19-a2ef-8412952a9671 { $return = 'MicrosoftOffice' }
- 0469d4cd-df37-4d93-8a61-f8c75b809164 { $return = 'Microsoft Policy Administration Service' }
- 31d3f3f5-7267-45a8-9549-affb00110054 { $return = 'Windows Azure RemoteApp Service' }
- 4e004241-32db-46c2-a86f-aaaba29bea9c { $return = 'Workflow' }
- 748d098e-7a3b-436d-8b0a-006a58b29647 { $return = 'Workflow' }
- dbf08535-1d3b-4f89-bf54-1d48dd613a61 { $return = 'Workflow' }
- ed9fe1ef-25a4-482f-9981-2b60f91e2448 { $return = 'Workflow' }
- 8ad28d50-ee26-42fc-8a29-e41ea38461f2 { $return = 'Office365RESTAPIExplorer.Office365App' }
- 38285dce-a13d-4107-9b04-3016b941bb3a { $return = 'BasicDataOperationsREST' }
- 92bb96c8-321c-47f9-bcc5-8849490c2b07 { $return = 'BasicSelfHostedAppREST' }
- 488a57a0-00e2-4817-8c8d-cf8a15a994d2 { $return = 'WindowsFormsApplication2.Office365App' }
- 11c174dc-1945-4a9a-a36b-c79a0f246b9b { $return = 'AzureApplicationInsights' }
- e6acb561-0d94-4287-bd3a-3169f421b112 { $return = 'Tutum' }
- 7b77b3a2-8490-49e1-8842-207cd0899af9 { $return = 'Nearpod' }
- 0000000a-0000-0000-c000-000000000000 { $return = 'Microsoft.Intune' }
- 93625bc8-bfe2-437a-97e0-3d0060024faa { $return = 'SelfServicePasswordReset' }
- dee7ba80-6a55-4f3b-a86c-746a9231ae49 { $return = 'MicrosoftAppPlatEMA' }
- 803ee9ca-3f7f-4824-bd6e-0b99d720c35c { $return = 'Azure Media Service' }
- 2d4d3d8e-2be3-4bef-9f87-7875a61c29de { $return = 'OneNote' }
- 8d40666e-5abf-45f6-a5e7-b7192d6d56ed { $return = 'Workflow' }
- 262044b1-e2ce-469f-a196-69ab7ada62d3 { $return = 'Backup Management Service' }
- 087a2c70-c89e-463f-8dd3-e3959eabb1a9 { $return = 'Microsoft Profile Service Platform Service' }
- 7cd684f4-8a78-49b0-91ec-6a35d38739ba { $return = 'Azure Logic Apps' }
- c5393580-f805-4401-95e8-94b7a6ef2fc2 { $return = 'Office 365 Management APIs' }
- 96231a05-34ce-4eb4-aa6a-70759cbb5e83 { $return = 'MicrosoftAzureRedisCache' }
- b8340c3b-9267-498f-b21a-15d5547fd85e { $return = 'Hyper-V Recovery Manager' }
- abfa0a7c-a6b6-4736-8310-5855508787cd { $return = 'Microsoft.Azure.WebSites' }
- c44b4083-3bb0-49c1-b47d-974e53cbdf3c { $return = 'IbizaPortal' }
- 905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba { $return = 'Sway' }
- b10686fd-6ba8-49f2-a3cd-67e4d2f52ac8 { $return = 'NovoEd' }
- c606301c-f764-4e6b-aa45-7caaaea93c9a { $return = 'OfficeStore' }
- 569e8598-685b-4ba2-8bff-5bced483ac46 { $return = 'Evercontact' }
- 20a23a2f-8c32-4de7-8063-8c8f909602c0 { $return = 'Workflow' }
- aaf214cc-8013-4b95-975f-13203ae36039 { $return = 'Power BI Tiles' }
- d88a361a-d488-4271-a13f-a83df7dd99c2 { $return = 'IDML Graph Resolver Service and CAD' }
- dff9b531-6290-4620-afce-26826a62a4e7 { $return = 'DocuSign' }
- 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9 { $return = 'Device Registration Service' }
- 3290e3f7-d3ac-4165-bcef-cf4874fc4270 { $return = 'Smartsheet' }
- a4ee6867-8640-4495-b1fd-8b26037a5bd3 { $return = 'Workflow' }
- aa0e3dd4-df02-478d-869e-fc61dd71b6e8 { $return = 'Workflow' }
- 0f6edad5-48f2-4585-a609-d252b1c52770 { $return = 'AIGraphClient' }
- 0c8139b5-d545-4448-8d2b-2121bb242680 { $return = 'BillingExtension' }
- 475226c6-020e-4fb2-8a90-7a972cbfc1d4 { $return = 'KratosAppsService' }
- 39624784-6cbe-4a60-afbe-9f46d10fdb27 { $return = 'SkypeForBusinessRemotePowershell' }
- 8bdebf23-c0fe-4187-a378-717ad86f6a53 { $return = 'ResourceHealthRP' }
- c161e42e-d4df-4a3d-9b42-e7a3c31f59d4 { $return = 'MicrosoftIntuneAPI' }
- 9cb77803-d937-493e-9a3b-4b49de3f5a74 { $return = 'MicrosoftIntuneServiceDiscovery' }
- ddbf3205-c6bd-46ae-8127-60eb93363864 { $return = 'Microsoft Azure Batch' }
- 80ccca67-54bd-44ab-8625-4b79c4dc7775 { $return = 'ComplianceCenter' }
- 0a5f63c0-b750-4f38-a71c-4fc0d58b89e2 { $return = 'Microsoft Mobile Application Management' }
- e1335bb1-2aec-4f92-8140-0e6e61ae77e5 { $return = 'CIWebService' }
- 75018fbe-21fe-4a57-b63c-83252b5eaf16 { $return = 'TeamImprover - Team Organization Chart' }
- a393296b-5695-4463-97cb-9fa8638a494a { $return = 'My SharePoint Sites' }
- fe217466-5583-431c-9531-14ff7268b7b3 { $return = 'Microsoft Education' }
- 5bfe8a29-054e-4348-9e7a-3981b26b125f { $return = 'Bing Places for Business' }
- eaf8a961-f56e-47eb-9ffd-936e22a554ef { $return = 'DevilFish' }
- 4b4b1d56-1f03-47d9-a0a3-87d4afc913c9 { $return = 'Wunderlist' }
- 00000003-0000-0000-c000-000000000000 { $return = 'Microsoft Graph' }
- 60e6cd67-9c8c-4951-9b3c-23c25a2169af { $return = 'Compute Resource Provider' }
- 507bc9da-c4e2-40cb-96a7-ac90df92685c { $return = 'Office365Reports' }
- 09abbdfd-ed23-44ee-a2d9-a627aa1c90f3 { $return = 'ProjectWorkManagement' }
- 28ec9756-deaf-48b2-84d5-a623b99af263 { $return = 'Office Personal Assistant at Work Service' }
- 9e4a5442-a5c9-4f6f-b03f-5b9fcaaf24b1 { $return = 'OfficeServicesManager' }
- 3138fe80-4087-4b04-80a6-8866c738028a { $return = 'SharePoint Notification Service' }
- d2a0a418-0aac-4541-82b2-b3142c89da77 { $return = 'MicrosoftAzureOperationalInsights' }
- 2cf9eb86-36b5-49dc-86ae-9a63135dfa8c { $return = 'AzureTrafficManagerandDNS' }
- 32613fc5-e7ac-4894-ac94-fbc39c9f3e4a { $return = 'OAuth Sandbox' }
- 925eb0d0-da50-4604-a19f-bd8de9147958 { $return = 'Groupies Web Service' }
- e4ab13ed-33cb-41b4-9140-6e264582cf85 { $return = 'Azure SQL Database Backup To Azure Backup Vault' }
- ad230543-afbe-4bb4-ac4f-d94d101704f8 { $return = 'Apiary for Power BI' }
- 11cd3e2e-fccb-42ad-ad00-878b93575e07 { $return = 'Automated Call Distribution' }
- de17788e-c765-4d31-aba4-fb837cfff174 { $return = 'Skype for Business Management Reporting and Analytics' }
- 65d91a3d-ab74-42e6-8a2f-0add61688c74 { $return = 'Microsoft Approval Management' }
- 5225545c-3ebd-400f-b668-c8d78550d776 { $return = 'Office Agent Service' }
- 1cda9b54-9852-4a5a-96d4-c2ab174f9edf { $return = 'O365Account' }
- 4747d38e-36c5-4bc3-979b-b0ef74df54d1 { $return = 'PushChannel' }
- b97b6bd4-a49f-4a0c-af18-af507d1da76c { $return = 'Office Shredding Service' }
- d4ebce55-015a-49b5-a083-c84d1797ae8c { $return = 'Microsoft Intune Enrollment' }
- 5b20c633-9a48-4a5f-95f6-dae91879051f { $return = 'Azure Information Protection' }
- 441509e5-a165-4363-8ee7-bcf0b7d26739 { $return = 'EnterpriseAgentPlatform' }
- e691bce4-6612-4025-b94c-81372a99f77e { $return = 'Boomerang' }
- 8edd93e1-2103-40b4-bd70-6e34e586362d { $return = 'Windows Azure Security Resource Provider' }
- 94c63fef-13a3-47bc-8074-75af8c65887a { $return = 'Office Delve' }
- e95d8bee-4725-4f59-910d-94d415da51b9 { $return = 'Skype for Business Name Dictionary Service' }
- e3c5dbcd-bb5f-4bda-b943-adc7a5bbc65e { $return = 'Workflow' }
- 8602e328-9b72-4f2d-a4ae-1387d013a2b3 { $return = 'Azure API Management' }
- 8b3391f4-af01-4ee8-b4ea-9871b2499735 { $return = 'O365 Secure Score' }
- c26550d6-bc82-4484-82ca-ac1c75308ca3 { $return = 'Office 365 YammerOnOls' }
- 33be1cef-03fb-444b-8fd3-08ca1b4d803f { $return = 'OneDrive Web' }
- dcad865d-9257-4521-ad4d-bae3e137b345 { $return = 'Microsoft SharePoint Online - SharePoint Home' }
- b2cc270f-563e-4d8a-af47-f00963a71dcd { $return = 'OneProfile Service' }
- 4660504c-45b3-4674-a709-71951a6b0763 { $return = 'Microsoft Invitation Acceptance Portal' }
- ba23cd2a-306c-48f2-9d62-d3ecd372dfe4 { $return = 'OfficeGraph' }
- d52485ee-4609-4f6b-b3a3-68b6f841fa23 { $return = 'On-Premises Data Gateway Connector' }
- 996def3d-b36c-4153-8607-a6fd3c01b89f { $return = 's 365 for Financials' }
- b6b84568-6c01-4981-a80f-09da9a20bbed { $return = 'Microsoft Invoicing' }
- 9d3e55ba-79e0-4b7c-af50-dc460b81dca1 { $return = 'Microsoft Azure Data Catalog' }
- 4345a7b9-9a63-4910-a426-35363201d503 { $return = 'O365 Suite UX' }
- ac815d4a-573b-4174-b38e-46490d19f894 { $return = 'Workflow' }
- bb8f18b0-9c38-48c9-a847-e1ef3af0602d { $return = 'Microsoft.Azure.ActiveDirectoryIUX' }
- cc15fd57-2c6c-4117-a88c-83b1d56b4bbe { $return = 'Microsoft Teams Services' }
- 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 { $return = 'Skype Teams' }
- 1fec8e78-bce4-4aaf-ab1b-5451cc387264 { $return = 'Microsoft Teams' }
- 6d32b7f8-782e-43e0-ac47-aaad9f4eb839 { $return = 'Permission Service O365' }
- cdccd920-384b-4a25-897d-75161a4b74c1 { $return = 'Skype Teams Firehose' }
- 1c0ae35a-e2ec-4592-8e08-c40884656fa5 { $return = 'Skype Team Substrate connector' }
- cf6c77f8-914f-4078-baef-e39a5181158b { $return = 'Skype Teams Settings Store' }
- 64f79cb9-9c82-4199-b85b-77e35b7dcbcb { $return = 'Microsoft Teams Bots' }
- b7912db9-aa33-4820-9d4f-709830fdd78f { $return = 'ConnectionsService' }
- 82f77645-8a66-4745-bcdf-9706824f9ad0 { $return = 'PowerApps Runtime Service' }
- 6204c1d1-4712-4c46-a7d9-3ed63d992682 { $return = 'Microsoft Flow Portal' }
- 7df0a125-d3be-4c96-aa54-591f83ff541c { $return = 'Microsoft Flow Service' }
- 331cc017-5973-4173-b270-f0042fddfd75 { $return = 'PowerAppsService' }
- 0a0e9e37-25e3-47d4-964c-5b8237cad19a { $return = 'CloudSponge' }
- df09ff61-2178-45d8-888c-4210c1c7b0b2 { $return = 'O365 UAP Processor' }
- 8338dec2-e1b3-48f7-8438-20c30a534458 { $return = 'ViewPoint' }
- 00000001-0000-0000-c000-000000000000 { $return = 'Azure ESTS Service' }
- 394866fc-eedb-4f01-8536-3ff84b16be2a { $return = 'Microsoft People Cards Service' }
- 0a0a29f9-0a25-49c7-94bf-c53c3f8fa69d { $return = 'Cortana Experience with O365' }
- bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4 { $return = 'CPIM Service' }
- 0004c632-673b-4105-9bb6-f3bbd2a927fe { $return = 'PowerApps and Flow' }
- d3ce4cf8-6810-442d-b42e-375e14710095 { $return = 'Graph Explorer' }
- 3aa5c166-136f-40eb-9066-33ac63099211 { $return = 'O365 Customer Monitoring' }
- d6fdaa33-e821-4211-83d0-cf74736489e1 { $return = 'Microsoft Service Trust' }
- ef4a2a24-4b4e-4abf-93ba-cc11c5bd442c { $return = 'Edmodo' }
- b692184e-b47f-4706-b352-84b288d2d9ee { $return = 'Microsoft.MileIQ.RESTService' }
- a25dbca8-4e60-48e5-80a2-0664fdb5c9b6 { $return = 'Microsoft.MileIQ' }
- f7069a8d-9edc-4300-b365-ae53c9627fc4 { $return = 'Microsoft.MileIQ.Dashboard' }
- 02e3ae74-c151-4bda-b8f0-55fbf341de08 { $return = 'Application Registration Portal' }
- 1f5530b3-261a-47a9-b357-ded261e17918 { $return = 'Azure Multi-Factor Auth Connector' }
- 981f26a1-7f43-403b-a875-f8b09b8cd720 { $return = 'Azure Multi-Factor Auth Client' }
- 6ea8091b-151d-447a-9013-6845b83ba57b { $return = 'AD Hybrid Health' }
- fc68d9e5-1f76-45ef-99aa-214805418498 { $return = 'Azure AD Identity Protection' }
- 01fc33a7-78ba-4d2f-a4b7-768e336e890e { $return = 'MS-PIM' }
- a6aa9161-5291-40bb-8c5c-923b567bee3b { $return = 'Storage Resource Provider' }
- 4e9b8b9a-1001-4017-8dd1-6e8f25e19d13 { $return = 'Adobe Acrobat' }
- 159b90bb-bb28-4568-ad7c-adad6b814a2f { $return = 'LastPass' }
- b4bddae8-ab25-483e-8670-df09b9f1d0ea { $return = 'Signup' }
- aa580612-c342-4ace-9055-8edee43ccb89 { $return = 'Microsoft StaffHub' }
- 51133ff5-8e0d-4078-bcca-84fb7f905b64 { $return = 'Microsoft Teams Mailhook' }
- ab3be6b7-f5df-413d-ac2d-abf1e3fd9c0b { $return = 'Microsoft Teams Graph Service' }
- b1379a75-ce5e-4fa3-80c6-89bb39bf646c { $return = 'Microsoft Teams Chat Aggregator' }
- 48af08dc-f6d2-435f-b2a7-069abd99c086 { $return = 'Connectors' }
- d676e816-a17b-416b-ac1a-05ad96f43686 { $return = 'Workflow' }
- cfa8b339-82a2-471a-a3c9-0fc0be7a4093 { $return = 'Azure Key Vault' }
- c2f89f53-3971-4e09-8656-18eed74aee10 { $return = 'calendly' }
- 6da466b6-1d13-4a2c-97bd-51a99e8d4d74 { $return = 'Exchange Office Graph Client for AAD - Interactive' }
- 0eda3b13-ddc9-4c25-b7dd-2f6ea073d6b7 { $return = 'Microsoft Flow CDS Integration Service' }
- eacba838-453c-4d3e-8c6a-eb815d3469a3 { $return = 'Microsoft Flow CDS Integration Service TIP1' }
- 4ac7d521-0382-477b-b0f8-7e1d95f85ca2 { $return = 'SQL Server Analysis Services Azure' }
- b4114287-89e4-4209-bd99-b7d4919bcf64 { $return = 'OfficeDelve' }
- 4580fd1d-e5a3-4f56-9ad1-aab0e3bf8f76 { $return = 'Call Recorder' }
- a855a166-fd92-4c76-b60d-a791e0762432 { $return = 'Microsoft Teams VSTS' }
- c37c294f-eec8-47d2-b3e2-fc3daa8f77d3 { $return = 'Workflow' }
- fc75330b-179d-49af-87dd-3b1acf6827fa { $return = 'AzureAutomationAADPatchS2S' }
- 766d89a4-d6a6-444d-8a5e-e1a18622288a { $return = 'OneDrive' }
- f16c4a38-5aff-4549-8199-ee7d3c5bd8dc { $return = 'Workflow' }
- 4c4f550b-42b2-4a16-93f9-fdb9e01bb6ed { $return = 'Targeted Messaging Service' }
- 765fe668-04e7-42ba-aec0-2c96f1d8b652 { $return = 'Exchange Office Graph Client for AAD - Noninteractive' }
- 0130cc9f-7ac5-4026-bd5f-80a08a54e6d9 { $return = 'Azure Data Warehouse Polybase' }
- a1cf9e0a-fe14-487c-beb9-dd3360921173 { $return = 'Meetup' }
- 76cd24bf-a9fc-4344-b1dc-908275de6d6d { $return = 'Azure SQL Virtual Network to Network Resource Provider' }
- 9f505dbd-a32c-4685-b1c6-72e4ef704cb0 { $return = 'Amazon Alexa' }
- 1e2ca66a-c176-45ea-a877-e87f7231e0ee { $return = 'Microsoft B2B Admin Worker' }
- 2634dd23-5e5a-431c-81ca-11710d9079f4 { $return = 'Microsoft Stream Service' }
- cf53fce8-def6-4aeb-8d30-b158e7b1cf83 { $return = 'Microsoft Stream Portal' }
- c9a559d2-7aab-4f13-a6ed-e7e9c52aec87 { $return = 'Microsoft Forms' }
- 978877ea-b2d6-458b-80c7-05df932f3723 { $return = 'Microsoft Teams AuditService' }
- dbc36ae1-c097-4df9-8d94-343c3d091a76 { $return = 'Service Encryption' }
- fa7ff576-8e31-4a58-a5e5-780c1cd57caa { $return = 'OneNote' }
- cb4dc29f-0bf4-402a-8b30-7511498ed654 { $return = 'Power BI Premium' }
- f5aeb603-2a64-4f37-b9a8-b544f3542865 { $return = 'Microsoft Teams RetentionHook Service' }
- da109bdd-abda-4c06-8808-4655199420f8 { $return = 'Glip Contacts' }
- 76c7f279-7959-468f-8943-3954880e0d8c { $return = 'Azure SQL Managed Instance to Microsoft.Network' }
- 3a9ddf38-83f3-4ea1-a33a-ecf934644e2d { $return = 'Protected Message Viewer' }
- 5635d99c-c364-4411-90eb-764a511b5fdf { $return = 'Responsive Banner Slider' }
- a43e5392-f48b-46a4-a0f1-098b5eeb4757 { $return = 'Cloudsponge' }
- d73f4b35-55c9-48c7-8b10-651f6f2acb2e { $return = 'MCAPI Authorization Prod' }
- 166f1b03-5b19-416f-a94b-1d7aa2d247dc { $return = 'Office Hive' }
- b815ce1c-748f-4b1e-9270-a42c1fa4485a { $return = 'Workflow' }
- bd7b778b-4aa8-4cde-8d90-8aeb821c0bd2 { $return = 'Workflow' }
- 9d06afd9-66c9-49a6-b385-ea7509332b0b { $return = 'O365SBRM Service' }
- 9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7 { $return = 'Bing' }
- 57fb890c-0dab-4253-a5e0-7188c88b2bb4 { $return = 'SharePoint Online Client' }
- 45c10911-200f-4e27-a666-9e9fca147395 { $return = 'drawio' }
- b73f62d0-210b-4396-a4c5-ea50c4fab79b { $return = 'Skype Business Voice Fraud Detection and Prevention' }
- bc59ab01-8403-45c6-8796-ac3ef710b3e3 { $return = 'Outlook Online Add-in App' }
- 035f9e1d-4f00-4419-bf50-bf2d87eb4878 { $return = 'Azure Monitor Restricted' }
- 7c33bfcb-8d33-48d6-8e60-dc6404003489 { $return = 'Network Watcher' }
- a0be0c72-870e-46f0-9c49-c98333a996f7 { $return = 'AzureDnsFrontendApp' }
- 1e3e4475-288f-4018-a376-df66fd7fac5f { $return = 'NetworkTrafficAnalyticsService' }
- 7557eb47-c689-4224-abcf-aef9bd7573df { $return = 'Skype for Business' }
- c39c9bac-9d1f-4dfb-aa29-27f6365e5cb7 { $return = 'Azure Advisor' }
- 2087bd82-7206-4c0a-b305-1321a39e5926 { $return = 'Microsoft To-Do' }
- f8d98a96-0999-43f5-8af3-69971c7bb423 { $return = 'iOS Accounts' }
- c27373d3-335f-4b45-8af9-fe81c240d377 { $return = 'P2P Server' }
- 5c2ffddc-f1d7-4dc3-926e-3c1bd98e32bd { $return = 'RITS Dev' }
- 982bda36-4632-4165-a46a-9863b1bbcf7d { $return = 'O365 Demeter' }
- 98c8388a-4e86-424f-a176-d1288462816f { $return = 'OfficeFeedProcessors' }
- bf9fc203-c1ff-4fd4-878b-323642e462ec { $return = 'Jarvis Transaction Service' }
- 257601fd-462f-4a21-b623-7f719f0f90f4 { $return = 'Centralized Deployment' }
- 2a486b53-dbd2-49c0-a2bc-278bdfc30833 { $return = 'Cortana at Work Service' }
- 22d7579f-06c2-4baa-89d2-e844486adb9d { $return = 'Cortana at Work Bing Services' }
- 4c8f074c-e32b-4ba7-b072-0f39d71daf51 { $return = 'IPSubstrate' }
- a164aee5-7d0a-46bb-9404-37421d58bdf7 { $return = 'Microsoft Teams AuthSvc' }
- 354b5b6d-abd6-4736-9f51-1be80049b91f { $return = 'Microsoft Mobile Application Management Backend' }
- 82b293b2-d54d-4d59-9a95-39c1c97954a7 { $return = 'Tasks in a Box' }
- fdc83783-b652-4258-a622-66bc85f1a871 { $return = 'FedExPackageTracking' }
- d0597157-f0ae-4e23-b06c-9e65de434c4f { $return = 'Microsoft Teams Task Service' }
- f5c26e74-f226-4ae8-85f0-b4af0080ac9e { $return = 'Application Insights API' }
- 57c0fc58-a83a-41d0-8ae9-08952659bdfd { $return = 'Azure Cosmos DB Virtual Network To Network Resource Provider' }
- 744e50be-c4ff-4e90-8061-cd7f1fabac0b { $return = 'LinkedIn Microsoft Graph Connector' }
- 823dfde0-1b9a-415a-a35a-1ad34e16dd44 { $return = 'Microsoft Teams Wiki Images Migration' }
- 3ab9b3bc-762f-4d62-82f7-7e1d653ce29f { $return = 'Microsoft Volume Licensing' }
- 44eb7794-0e11-42b6-800b-dc31874f9f60 { $return = 'Alignable' }
- c58637bb-e2e1-4312-8a00-04b5ffcd3403 { $return = 'SharePoint Online Client Extensibility' }
- 62b732f7-fc71-40bc-b27d-35efcb0509de { $return = 'Microsoft Teams AadSync' }
- 07978fee-621a-42df-82bb-3eabc6511c26 { $return = 'SurveyMonkey' }
- 47ee738b-3f1a-4fc7-ab11-37e4822b007e { $return = 'Azure AD Application Proxy' }
- 00000007-0000-0000-c000-000000000000 { $return = 'Dynamics CRM Online' }
- 913c6de4-2a4a-4a61-a9ce-945d2b2ce2e0 { $return = 'Dynamics Lifecycle services' }
- f217ad13-46b8-4c5b-b661-876ccdf37302 { $return = 'Attach OneDrive files to Asana' }
- 00000008-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.DataMarket' }
- 9b06ebd4-9068-486b-bdd2-dac26b8a5a7a { $return = 'Microsoft.DynamicsMarketing' }
- e8ab36af-d4be-4833-a38b-4d6cf1cfd525 { $return = 'Microsoft Social Engagement' }
- 8909aac3-be91-470c-8a0b-ff09d669af91 { $return = 'Microsoft Parature Dynamics CRM' }
- 71234da4-b92f-429d-b8ec-6e62652e50d7 { $return = 'Microsoft Customer Engagement Portal' }
- b861dbcc-a7ef-4219-a005-0e4de4ea7dcf { $return = 'Data Export Service for Microsoft Dynamics 365' }
- 2db8cb1d-fb6c-450b-ab09-49b6ae35186b { $return = 'Microsoft Dynamics CRM Learning Path' }
- 2e49aa60-1bd3-43b6-8ab6-03ada3d9f08b { $return = 'Dynamics Data Integration' }
- }
+ function Get-UserNameFromId {
+ [CmdletBinding()]
+ param (
+ [Parameter()]
+ $ID,
- if ([string]::IsNullOrEmpty($return)) {
- $return = $Applications | Where-Object { $_.Appid -eq $ID } | Select-Object -ExpandProperty DisplayName
+ [Parameter(Mandatory = $true)]
+ $Users
+ )
+ if ($id -eq 'All') {
+ return 'All'
+ }
+ $DisplayName = $Users | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
+ if ([string]::IsNullOrEmpty($displayName)) {
+ return $ID
+ } else {
+ return $DisplayName
+ }
}
- if ([string]::IsNullOrEmpty($return)) {
- $return = $Applications | Where-Object { $_.ID -eq $ID } | Select-Object -ExpandProperty DisplayName
- }
+ function Get-GroupNameFromId {
+ param (
+ [Parameter()]
+ $ID,
- if ([string]::IsNullOrEmpty($return)) {
- $return = ''
+ [Parameter(Mandatory = $true)]
+ $Groups
+ )
+ if ($id -eq 'All') {
+ return 'All'
+ }
+ $DisplayName = $Groups | Where-Object { $_.id -eq $ID } | Select-Object -ExpandProperty DisplayName
+ if ([string]::IsNullOrEmpty($displayName)) {
+ return 'No Data'
+ } else {
+ return $DisplayName
+ }
}
- return $return
-}
+ function Get-ApplicationNameFromId {
+ [CmdletBinding()]
+ param (
+ [Parameter()]
+ $ID,
+
+ [Parameter(Mandatory = $true)]
+ $Applications
+ )
+ if ($id -eq 'All') {
+ return 'All'
+ }
+ switch ($id) {
+ 00000004-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Lync' }
+ 00000006-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Office365Portal' }
+ 00000003-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.SharePoint ' }
+ 00000005-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.Workflow' }
+ 00000009-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.AnalysisServices' }
+ 00000002-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.Exchange' }
+ 00000007-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.ExchangeOnlineProtection' }
+ 00000002-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.ActiveDirectory' }
+ 8fca0a66-c008-4564-a876-ab3ae0fd5cff { $return = 'Microsoft.SMIT' }
+ 0000000b-0000-0000-c000-000000000000 { $return = 'Microsoft.SellerDashboard' }
+ 0000000f-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.GraphExplorer' }
+ 0000000c-0000-0000-c000-000000000000 { $return = 'Microsoft App Access Panel' }
+ 00000013-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.Portal' }
+ 00000010-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.GraphStore' }
+ 93ee9413-cf4c-4d4e-814b-a91ff20a01bd { $return = 'Workflow' }
+ aa9ecb1e-fd53-4aaa-a8fe-7a54de2c1334 { $return = 'Microsoft.Office365.Configure' }
+ 797f4846-ba00-4fd7-ba43-dac1f8f63013 { $return = 'Windows Azure Service Management API' }
+ 00000005-0000-0ff1-ce00-000000000000 { $return = 'Microsoft.YammerEnterprise' }
+ 601d4e27-7bb3-4dee-8199-90d47d527e1c { $return = 'Microsoft.Office365.ChangeManagement' }
+ 6f82282e-0070-4e78-bc23-e6320c5fa7de { $return = 'Microsoft.DiscoveryService' }
+ 0f698dd4-f011-4d23-a33e-b36416dcb1e6 { $return = 'Microsoft.OfficeClientService' }
+ 67e3df25-268a-4324-a550-0de1c7f97287 { $return = 'Microsoft.OfficeWebAppsService' }
+ ab27a73e-a3ba-4e43-8360-8bcc717114d8 { $return = 'Microsoft.OfficeModernCalendar' }
+ aedca418-a84d-430d-ab84-0b1ef06f318f { $return = 'Workflow' }
+ 595d87a1-277b-4c0a-aa7f-44f8a068eafc { $return = 'Microsoft.SupportTicketSubmission' }
+ e3583ad2-c781-4224-9b91-ad15a8179ba0 { $return = 'Microsoft.ExtensibleRealUserMonitoring' }
+ b645896d-566e-447e-8f7f-e2e663b5d182 { $return = 'OpsDashSharePointApp' }
+ 48229a4a-9f1d-413a-8b96-4c02462c0360 { $return = 'OpsDashSharePointApp' }
+ 48717084-a59c-4306-9dc4-3f618dbecdf9 { $return = '"Napa" Office 365 Development Tools' }
+ c859ff33-eb41-4ba6-8093-a2c5153bbd7c { $return = 'Workflow' }
+ 67cad61c-3411-48d7-ab73-561c64f11ed6 { $return = 'Workflow' }
+ 914ed757-9257-4200-b68e-a2bed2f12c5a { $return = 'RbacBackfill' }
+ 499b84ac-1321-427f-aa17-267ca6975798 { $return = 'Microsoft.VisualStudio.Online' }
+ b2590339-0887-4e94-93aa-13357eb510d7 { $return = 'Workflow' }
+ 0000001b-0000-0000-c000-000000000000 { $return = 'Microsoft Power BI Information Service' }
+ 89f80565-bfac-4c01-9535-9f0eba332ffe { $return = 'Power BI' }
+ 433895fb-4ec7-45c3-a53c-c44d10f80d5b { $return = 'Compromised Account Service' }
+ d7c17728-4f1e-4a1e-86cf-7e0adf3fe903 { $return = 'Workflow' }
+ 17ef6d31-381f-4783-b186-7b440a3c85c1 { $return = 'Workflow' }
+ 00000012-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.RMS' }
+ 81ce94d4-9422-4c0d-a4b9-3250659366ce { $return = 'Workflow' }
+ 8d3a7d3c-c034-4f19-a2ef-8412952a9671 { $return = 'MicrosoftOffice' }
+ 0469d4cd-df37-4d93-8a61-f8c75b809164 { $return = 'Microsoft Policy Administration Service' }
+ 31d3f3f5-7267-45a8-9549-affb00110054 { $return = 'Windows Azure RemoteApp Service' }
+ 4e004241-32db-46c2-a86f-aaaba29bea9c { $return = 'Workflow' }
+ 748d098e-7a3b-436d-8b0a-006a58b29647 { $return = 'Workflow' }
+ dbf08535-1d3b-4f89-bf54-1d48dd613a61 { $return = 'Workflow' }
+ ed9fe1ef-25a4-482f-9981-2b60f91e2448 { $return = 'Workflow' }
+ 8ad28d50-ee26-42fc-8a29-e41ea38461f2 { $return = 'Office365RESTAPIExplorer.Office365App' }
+ 38285dce-a13d-4107-9b04-3016b941bb3a { $return = 'BasicDataOperationsREST' }
+ 92bb96c8-321c-47f9-bcc5-8849490c2b07 { $return = 'BasicSelfHostedAppREST' }
+ 488a57a0-00e2-4817-8c8d-cf8a15a994d2 { $return = 'WindowsFormsApplication2.Office365App' }
+ 11c174dc-1945-4a9a-a36b-c79a0f246b9b { $return = 'AzureApplicationInsights' }
+ e6acb561-0d94-4287-bd3a-3169f421b112 { $return = 'Tutum' }
+ 7b77b3a2-8490-49e1-8842-207cd0899af9 { $return = 'Nearpod' }
+ 0000000a-0000-0000-c000-000000000000 { $return = 'Microsoft.Intune' }
+ 93625bc8-bfe2-437a-97e0-3d0060024faa { $return = 'SelfServicePasswordReset' }
+ dee7ba80-6a55-4f3b-a86c-746a9231ae49 { $return = 'MicrosoftAppPlatEMA' }
+ 803ee9ca-3f7f-4824-bd6e-0b99d720c35c { $return = 'Azure Media Service' }
+ 2d4d3d8e-2be3-4bef-9f87-7875a61c29de { $return = 'OneNote' }
+ 8d40666e-5abf-45f6-a5e7-b7192d6d56ed { $return = 'Workflow' }
+ 262044b1-e2ce-469f-a196-69ab7ada62d3 { $return = 'Backup Management Service' }
+ 087a2c70-c89e-463f-8dd3-e3959eabb1a9 { $return = 'Microsoft Profile Service Platform Service' }
+ 7cd684f4-8a78-49b0-91ec-6a35d38739ba { $return = 'Azure Logic Apps' }
+ c5393580-f805-4401-95e8-94b7a6ef2fc2 { $return = 'Office 365 Management APIs' }
+ 96231a05-34ce-4eb4-aa6a-70759cbb5e83 { $return = 'MicrosoftAzureRedisCache' }
+ b8340c3b-9267-498f-b21a-15d5547fd85e { $return = 'Hyper-V Recovery Manager' }
+ abfa0a7c-a6b6-4736-8310-5855508787cd { $return = 'Microsoft.Azure.WebSites' }
+ c44b4083-3bb0-49c1-b47d-974e53cbdf3c { $return = 'IbizaPortal' }
+ 905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba { $return = 'Sway' }
+ b10686fd-6ba8-49f2-a3cd-67e4d2f52ac8 { $return = 'NovoEd' }
+ c606301c-f764-4e6b-aa45-7caaaea93c9a { $return = 'OfficeStore' }
+ 569e8598-685b-4ba2-8bff-5bced483ac46 { $return = 'Evercontact' }
+ 20a23a2f-8c32-4de7-8063-8c8f909602c0 { $return = 'Workflow' }
+ aaf214cc-8013-4b95-975f-13203ae36039 { $return = 'Power BI Tiles' }
+ d88a361a-d488-4271-a13f-a83df7dd99c2 { $return = 'IDML Graph Resolver Service and CAD' }
+ dff9b531-6290-4620-afce-26826a62a4e7 { $return = 'DocuSign' }
+ 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9 { $return = 'Device Registration Service' }
+ 3290e3f7-d3ac-4165-bcef-cf4874fc4270 { $return = 'Smartsheet' }
+ a4ee6867-8640-4495-b1fd-8b26037a5bd3 { $return = 'Workflow' }
+ aa0e3dd4-df02-478d-869e-fc61dd71b6e8 { $return = 'Workflow' }
+ 0f6edad5-48f2-4585-a609-d252b1c52770 { $return = 'AIGraphClient' }
+ 0c8139b5-d545-4448-8d2b-2121bb242680 { $return = 'BillingExtension' }
+ 475226c6-020e-4fb2-8a90-7a972cbfc1d4 { $return = 'KratosAppsService' }
+ 39624784-6cbe-4a60-afbe-9f46d10fdb27 { $return = 'SkypeForBusinessRemotePowershell' }
+ 8bdebf23-c0fe-4187-a378-717ad86f6a53 { $return = 'ResourceHealthRP' }
+ c161e42e-d4df-4a3d-9b42-e7a3c31f59d4 { $return = 'MicrosoftIntuneAPI' }
+ 9cb77803-d937-493e-9a3b-4b49de3f5a74 { $return = 'MicrosoftIntuneServiceDiscovery' }
+ ddbf3205-c6bd-46ae-8127-60eb93363864 { $return = 'Microsoft Azure Batch' }
+ 80ccca67-54bd-44ab-8625-4b79c4dc7775 { $return = 'ComplianceCenter' }
+ 0a5f63c0-b750-4f38-a71c-4fc0d58b89e2 { $return = 'Microsoft Mobile Application Management' }
+ e1335bb1-2aec-4f92-8140-0e6e61ae77e5 { $return = 'CIWebService' }
+ 75018fbe-21fe-4a57-b63c-83252b5eaf16 { $return = 'TeamImprover - Team Organization Chart' }
+ a393296b-5695-4463-97cb-9fa8638a494a { $return = 'My SharePoint Sites' }
+ fe217466-5583-431c-9531-14ff7268b7b3 { $return = 'Microsoft Education' }
+ 5bfe8a29-054e-4348-9e7a-3981b26b125f { $return = 'Bing Places for Business' }
+ eaf8a961-f56e-47eb-9ffd-936e22a554ef { $return = 'DevilFish' }
+ 4b4b1d56-1f03-47d9-a0a3-87d4afc913c9 { $return = 'Wunderlist' }
+ 00000003-0000-0000-c000-000000000000 { $return = 'Microsoft Graph' }
+ 60e6cd67-9c8c-4951-9b3c-23c25a2169af { $return = 'Compute Resource Provider' }
+ 507bc9da-c4e2-40cb-96a7-ac90df92685c { $return = 'Office365Reports' }
+ 09abbdfd-ed23-44ee-a2d9-a627aa1c90f3 { $return = 'ProjectWorkManagement' }
+ 28ec9756-deaf-48b2-84d5-a623b99af263 { $return = 'Office Personal Assistant at Work Service' }
+ 9e4a5442-a5c9-4f6f-b03f-5b9fcaaf24b1 { $return = 'OfficeServicesManager' }
+ 3138fe80-4087-4b04-80a6-8866c738028a { $return = 'SharePoint Notification Service' }
+ d2a0a418-0aac-4541-82b2-b3142c89da77 { $return = 'MicrosoftAzureOperationalInsights' }
+ 2cf9eb86-36b5-49dc-86ae-9a63135dfa8c { $return = 'AzureTrafficManagerandDNS' }
+ 32613fc5-e7ac-4894-ac94-fbc39c9f3e4a { $return = 'OAuth Sandbox' }
+ 925eb0d0-da50-4604-a19f-bd8de9147958 { $return = 'Groupies Web Service' }
+ e4ab13ed-33cb-41b4-9140-6e264582cf85 { $return = 'Azure SQL Database Backup To Azure Backup Vault' }
+ ad230543-afbe-4bb4-ac4f-d94d101704f8 { $return = 'Apiary for Power BI' }
+ 11cd3e2e-fccb-42ad-ad00-878b93575e07 { $return = 'Automated Call Distribution' }
+ de17788e-c765-4d31-aba4-fb837cfff174 { $return = 'Skype for Business Management Reporting and Analytics' }
+ 65d91a3d-ab74-42e6-8a2f-0add61688c74 { $return = 'Microsoft Approval Management' }
+ 5225545c-3ebd-400f-b668-c8d78550d776 { $return = 'Office Agent Service' }
+ 1cda9b54-9852-4a5a-96d4-c2ab174f9edf { $return = 'O365Account' }
+ 4747d38e-36c5-4bc3-979b-b0ef74df54d1 { $return = 'PushChannel' }
+ b97b6bd4-a49f-4a0c-af18-af507d1da76c { $return = 'Office Shredding Service' }
+ d4ebce55-015a-49b5-a083-c84d1797ae8c { $return = 'Microsoft Intune Enrollment' }
+ 5b20c633-9a48-4a5f-95f6-dae91879051f { $return = 'Azure Information Protection' }
+ 441509e5-a165-4363-8ee7-bcf0b7d26739 { $return = 'EnterpriseAgentPlatform' }
+ e691bce4-6612-4025-b94c-81372a99f77e { $return = 'Boomerang' }
+ 8edd93e1-2103-40b4-bd70-6e34e586362d { $return = 'Windows Azure Security Resource Provider' }
+ 94c63fef-13a3-47bc-8074-75af8c65887a { $return = 'Office Delve' }
+ e95d8bee-4725-4f59-910d-94d415da51b9 { $return = 'Skype for Business Name Dictionary Service' }
+ e3c5dbcd-bb5f-4bda-b943-adc7a5bbc65e { $return = 'Workflow' }
+ 8602e328-9b72-4f2d-a4ae-1387d013a2b3 { $return = 'Azure API Management' }
+ 8b3391f4-af01-4ee8-b4ea-9871b2499735 { $return = 'O365 Secure Score' }
+ c26550d6-bc82-4484-82ca-ac1c75308ca3 { $return = 'Office 365 YammerOnOls' }
+ 33be1cef-03fb-444b-8fd3-08ca1b4d803f { $return = 'OneDrive Web' }
+ dcad865d-9257-4521-ad4d-bae3e137b345 { $return = 'Microsoft SharePoint Online - SharePoint Home' }
+ b2cc270f-563e-4d8a-af47-f00963a71dcd { $return = 'OneProfile Service' }
+ 4660504c-45b3-4674-a709-71951a6b0763 { $return = 'Microsoft Invitation Acceptance Portal' }
+ ba23cd2a-306c-48f2-9d62-d3ecd372dfe4 { $return = 'OfficeGraph' }
+ d52485ee-4609-4f6b-b3a3-68b6f841fa23 { $return = 'On-Premises Data Gateway Connector' }
+ 996def3d-b36c-4153-8607-a6fd3c01b89f { $return = 's 365 for Financials' }
+ b6b84568-6c01-4981-a80f-09da9a20bbed { $return = 'Microsoft Invoicing' }
+ 9d3e55ba-79e0-4b7c-af50-dc460b81dca1 { $return = 'Microsoft Azure Data Catalog' }
+ 4345a7b9-9a63-4910-a426-35363201d503 { $return = 'O365 Suite UX' }
+ ac815d4a-573b-4174-b38e-46490d19f894 { $return = 'Workflow' }
+ bb8f18b0-9c38-48c9-a847-e1ef3af0602d { $return = 'Microsoft.Azure.ActiveDirectoryIUX' }
+ cc15fd57-2c6c-4117-a88c-83b1d56b4bbe { $return = 'Microsoft Teams Services' }
+ 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 { $return = 'Skype Teams' }
+ 1fec8e78-bce4-4aaf-ab1b-5451cc387264 { $return = 'Microsoft Teams' }
+ 6d32b7f8-782e-43e0-ac47-aaad9f4eb839 { $return = 'Permission Service O365' }
+ cdccd920-384b-4a25-897d-75161a4b74c1 { $return = 'Skype Teams Firehose' }
+ 1c0ae35a-e2ec-4592-8e08-c40884656fa5 { $return = 'Skype Team Substrate connector' }
+ cf6c77f8-914f-4078-baef-e39a5181158b { $return = 'Skype Teams Settings Store' }
+ 64f79cb9-9c82-4199-b85b-77e35b7dcbcb { $return = 'Microsoft Teams Bots' }
+ b7912db9-aa33-4820-9d4f-709830fdd78f { $return = 'ConnectionsService' }
+ 82f77645-8a66-4745-bcdf-9706824f9ad0 { $return = 'PowerApps Runtime Service' }
+ 6204c1d1-4712-4c46-a7d9-3ed63d992682 { $return = 'Microsoft Flow Portal' }
+ 7df0a125-d3be-4c96-aa54-591f83ff541c { $return = 'Microsoft Flow Service' }
+ 331cc017-5973-4173-b270-f0042fddfd75 { $return = 'PowerAppsService' }
+ 0a0e9e37-25e3-47d4-964c-5b8237cad19a { $return = 'CloudSponge' }
+ df09ff61-2178-45d8-888c-4210c1c7b0b2 { $return = 'O365 UAP Processor' }
+ 8338dec2-e1b3-48f7-8438-20c30a534458 { $return = 'ViewPoint' }
+ 00000001-0000-0000-c000-000000000000 { $return = 'Azure ESTS Service' }
+ 394866fc-eedb-4f01-8536-3ff84b16be2a { $return = 'Microsoft People Cards Service' }
+ 0a0a29f9-0a25-49c7-94bf-c53c3f8fa69d { $return = 'Cortana Experience with O365' }
+ bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4 { $return = 'CPIM Service' }
+ 0004c632-673b-4105-9bb6-f3bbd2a927fe { $return = 'PowerApps and Flow' }
+ d3ce4cf8-6810-442d-b42e-375e14710095 { $return = 'Graph Explorer' }
+ 3aa5c166-136f-40eb-9066-33ac63099211 { $return = 'O365 Customer Monitoring' }
+ d6fdaa33-e821-4211-83d0-cf74736489e1 { $return = 'Microsoft Service Trust' }
+ ef4a2a24-4b4e-4abf-93ba-cc11c5bd442c { $return = 'Edmodo' }
+ b692184e-b47f-4706-b352-84b288d2d9ee { $return = 'Microsoft.MileIQ.RESTService' }
+ a25dbca8-4e60-48e5-80a2-0664fdb5c9b6 { $return = 'Microsoft.MileIQ' }
+ f7069a8d-9edc-4300-b365-ae53c9627fc4 { $return = 'Microsoft.MileIQ.Dashboard' }
+ 02e3ae74-c151-4bda-b8f0-55fbf341de08 { $return = 'Application Registration Portal' }
+ 1f5530b3-261a-47a9-b357-ded261e17918 { $return = 'Azure Multi-Factor Auth Connector' }
+ 981f26a1-7f43-403b-a875-f8b09b8cd720 { $return = 'Azure Multi-Factor Auth Client' }
+ 6ea8091b-151d-447a-9013-6845b83ba57b { $return = 'AD Hybrid Health' }
+ fc68d9e5-1f76-45ef-99aa-214805418498 { $return = 'Azure AD Identity Protection' }
+ 01fc33a7-78ba-4d2f-a4b7-768e336e890e { $return = 'MS-PIM' }
+ a6aa9161-5291-40bb-8c5c-923b567bee3b { $return = 'Storage Resource Provider' }
+ 4e9b8b9a-1001-4017-8dd1-6e8f25e19d13 { $return = 'Adobe Acrobat' }
+ 159b90bb-bb28-4568-ad7c-adad6b814a2f { $return = 'LastPass' }
+ b4bddae8-ab25-483e-8670-df09b9f1d0ea { $return = 'Signup' }
+ aa580612-c342-4ace-9055-8edee43ccb89 { $return = 'Microsoft StaffHub' }
+ 51133ff5-8e0d-4078-bcca-84fb7f905b64 { $return = 'Microsoft Teams Mailhook' }
+ ab3be6b7-f5df-413d-ac2d-abf1e3fd9c0b { $return = 'Microsoft Teams Graph Service' }
+ b1379a75-ce5e-4fa3-80c6-89bb39bf646c { $return = 'Microsoft Teams Chat Aggregator' }
+ 48af08dc-f6d2-435f-b2a7-069abd99c086 { $return = 'Connectors' }
+ d676e816-a17b-416b-ac1a-05ad96f43686 { $return = 'Workflow' }
+ cfa8b339-82a2-471a-a3c9-0fc0be7a4093 { $return = 'Azure Key Vault' }
+ c2f89f53-3971-4e09-8656-18eed74aee10 { $return = 'calendly' }
+ 6da466b6-1d13-4a2c-97bd-51a99e8d4d74 { $return = 'Exchange Office Graph Client for AAD - Interactive' }
+ 0eda3b13-ddc9-4c25-b7dd-2f6ea073d6b7 { $return = 'Microsoft Flow CDS Integration Service' }
+ eacba838-453c-4d3e-8c6a-eb815d3469a3 { $return = 'Microsoft Flow CDS Integration Service TIP1' }
+ 4ac7d521-0382-477b-b0f8-7e1d95f85ca2 { $return = 'SQL Server Analysis Services Azure' }
+ b4114287-89e4-4209-bd99-b7d4919bcf64 { $return = 'OfficeDelve' }
+ 4580fd1d-e5a3-4f56-9ad1-aab0e3bf8f76 { $return = 'Call Recorder' }
+ a855a166-fd92-4c76-b60d-a791e0762432 { $return = 'Microsoft Teams VSTS' }
+ c37c294f-eec8-47d2-b3e2-fc3daa8f77d3 { $return = 'Workflow' }
+ fc75330b-179d-49af-87dd-3b1acf6827fa { $return = 'AzureAutomationAADPatchS2S' }
+ 766d89a4-d6a6-444d-8a5e-e1a18622288a { $return = 'OneDrive' }
+ f16c4a38-5aff-4549-8199-ee7d3c5bd8dc { $return = 'Workflow' }
+ 4c4f550b-42b2-4a16-93f9-fdb9e01bb6ed { $return = 'Targeted Messaging Service' }
+ 765fe668-04e7-42ba-aec0-2c96f1d8b652 { $return = 'Exchange Office Graph Client for AAD - Noninteractive' }
+ 0130cc9f-7ac5-4026-bd5f-80a08a54e6d9 { $return = 'Azure Data Warehouse Polybase' }
+ a1cf9e0a-fe14-487c-beb9-dd3360921173 { $return = 'Meetup' }
+ 76cd24bf-a9fc-4344-b1dc-908275de6d6d { $return = 'Azure SQL Virtual Network to Network Resource Provider' }
+ 9f505dbd-a32c-4685-b1c6-72e4ef704cb0 { $return = 'Amazon Alexa' }
+ 1e2ca66a-c176-45ea-a877-e87f7231e0ee { $return = 'Microsoft B2B Admin Worker' }
+ 2634dd23-5e5a-431c-81ca-11710d9079f4 { $return = 'Microsoft Stream Service' }
+ cf53fce8-def6-4aeb-8d30-b158e7b1cf83 { $return = 'Microsoft Stream Portal' }
+ c9a559d2-7aab-4f13-a6ed-e7e9c52aec87 { $return = 'Microsoft Forms' }
+ 978877ea-b2d6-458b-80c7-05df932f3723 { $return = 'Microsoft Teams AuditService' }
+ dbc36ae1-c097-4df9-8d94-343c3d091a76 { $return = 'Service Encryption' }
+ fa7ff576-8e31-4a58-a5e5-780c1cd57caa { $return = 'OneNote' }
+ cb4dc29f-0bf4-402a-8b30-7511498ed654 { $return = 'Power BI Premium' }
+ f5aeb603-2a64-4f37-b9a8-b544f3542865 { $return = 'Microsoft Teams RetentionHook Service' }
+ da109bdd-abda-4c06-8808-4655199420f8 { $return = 'Glip Contacts' }
+ 76c7f279-7959-468f-8943-3954880e0d8c { $return = 'Azure SQL Managed Instance to Microsoft.Network' }
+ 3a9ddf38-83f3-4ea1-a33a-ecf934644e2d { $return = 'Protected Message Viewer' }
+ 5635d99c-c364-4411-90eb-764a511b5fdf { $return = 'Responsive Banner Slider' }
+ a43e5392-f48b-46a4-a0f1-098b5eeb4757 { $return = 'Cloudsponge' }
+ d73f4b35-55c9-48c7-8b10-651f6f2acb2e { $return = 'MCAPI Authorization Prod' }
+ 166f1b03-5b19-416f-a94b-1d7aa2d247dc { $return = 'Office Hive' }
+ b815ce1c-748f-4b1e-9270-a42c1fa4485a { $return = 'Workflow' }
+ bd7b778b-4aa8-4cde-8d90-8aeb821c0bd2 { $return = 'Workflow' }
+ 9d06afd9-66c9-49a6-b385-ea7509332b0b { $return = 'O365SBRM Service' }
+ 9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7 { $return = 'Bing' }
+ 57fb890c-0dab-4253-a5e0-7188c88b2bb4 { $return = 'SharePoint Online Client' }
+ 45c10911-200f-4e27-a666-9e9fca147395 { $return = 'drawio' }
+ b73f62d0-210b-4396-a4c5-ea50c4fab79b { $return = 'Skype Business Voice Fraud Detection and Prevention' }
+ bc59ab01-8403-45c6-8796-ac3ef710b3e3 { $return = 'Outlook Online Add-in App' }
+ 035f9e1d-4f00-4419-bf50-bf2d87eb4878 { $return = 'Azure Monitor Restricted' }
+ 7c33bfcb-8d33-48d6-8e60-dc6404003489 { $return = 'Network Watcher' }
+ a0be0c72-870e-46f0-9c49-c98333a996f7 { $return = 'AzureDnsFrontendApp' }
+ 1e3e4475-288f-4018-a376-df66fd7fac5f { $return = 'NetworkTrafficAnalyticsService' }
+ 7557eb47-c689-4224-abcf-aef9bd7573df { $return = 'Skype for Business' }
+ c39c9bac-9d1f-4dfb-aa29-27f6365e5cb7 { $return = 'Azure Advisor' }
+ 2087bd82-7206-4c0a-b305-1321a39e5926 { $return = 'Microsoft To-Do' }
+ f8d98a96-0999-43f5-8af3-69971c7bb423 { $return = 'iOS Accounts' }
+ c27373d3-335f-4b45-8af9-fe81c240d377 { $return = 'P2P Server' }
+ 5c2ffddc-f1d7-4dc3-926e-3c1bd98e32bd { $return = 'RITS Dev' }
+ 982bda36-4632-4165-a46a-9863b1bbcf7d { $return = 'O365 Demeter' }
+ 98c8388a-4e86-424f-a176-d1288462816f { $return = 'OfficeFeedProcessors' }
+ bf9fc203-c1ff-4fd4-878b-323642e462ec { $return = 'Jarvis Transaction Service' }
+ 257601fd-462f-4a21-b623-7f719f0f90f4 { $return = 'Centralized Deployment' }
+ 2a486b53-dbd2-49c0-a2bc-278bdfc30833 { $return = 'Cortana at Work Service' }
+ 22d7579f-06c2-4baa-89d2-e844486adb9d { $return = 'Cortana at Work Bing Services' }
+ 4c8f074c-e32b-4ba7-b072-0f39d71daf51 { $return = 'IPSubstrate' }
+ a164aee5-7d0a-46bb-9404-37421d58bdf7 { $return = 'Microsoft Teams AuthSvc' }
+ 354b5b6d-abd6-4736-9f51-1be80049b91f { $return = 'Microsoft Mobile Application Management Backend' }
+ 82b293b2-d54d-4d59-9a95-39c1c97954a7 { $return = 'Tasks in a Box' }
+ fdc83783-b652-4258-a622-66bc85f1a871 { $return = 'FedExPackageTracking' }
+ d0597157-f0ae-4e23-b06c-9e65de434c4f { $return = 'Microsoft Teams Task Service' }
+ f5c26e74-f226-4ae8-85f0-b4af0080ac9e { $return = 'Application Insights API' }
+ 57c0fc58-a83a-41d0-8ae9-08952659bdfd { $return = 'Azure Cosmos DB Virtual Network To Network Resource Provider' }
+ 744e50be-c4ff-4e90-8061-cd7f1fabac0b { $return = 'LinkedIn Microsoft Graph Connector' }
+ 823dfde0-1b9a-415a-a35a-1ad34e16dd44 { $return = 'Microsoft Teams Wiki Images Migration' }
+ 3ab9b3bc-762f-4d62-82f7-7e1d653ce29f { $return = 'Microsoft Volume Licensing' }
+ 44eb7794-0e11-42b6-800b-dc31874f9f60 { $return = 'Alignable' }
+ c58637bb-e2e1-4312-8a00-04b5ffcd3403 { $return = 'SharePoint Online Client Extensibility' }
+ 62b732f7-fc71-40bc-b27d-35efcb0509de { $return = 'Microsoft Teams AadSync' }
+ 07978fee-621a-42df-82bb-3eabc6511c26 { $return = 'SurveyMonkey' }
+ 47ee738b-3f1a-4fc7-ab11-37e4822b007e { $return = 'Azure AD Application Proxy' }
+ 00000007-0000-0000-c000-000000000000 { $return = 'Dynamics CRM Online' }
+ 913c6de4-2a4a-4a61-a9ce-945d2b2ce2e0 { $return = 'Dynamics Lifecycle services' }
+ f217ad13-46b8-4c5b-b661-876ccdf37302 { $return = 'Attach OneDrive files to Asana' }
+ 00000008-0000-0000-c000-000000000000 { $return = 'Microsoft.Azure.DataMarket' }
+ 9b06ebd4-9068-486b-bdd2-dac26b8a5a7a { $return = 'Microsoft.DynamicsMarketing' }
+ e8ab36af-d4be-4833-a38b-4d6cf1cfd525 { $return = 'Microsoft Social Engagement' }
+ 8909aac3-be91-470c-8a0b-ff09d669af91 { $return = 'Microsoft Parature Dynamics CRM' }
+ 71234da4-b92f-429d-b8ec-6e62652e50d7 { $return = 'Microsoft Customer Engagement Portal' }
+ b861dbcc-a7ef-4219-a005-0e4de4ea7dcf { $return = 'Data Export Service for Microsoft Dynamics 365' }
+ 2db8cb1d-fb6c-450b-ab09-49b6ae35186b { $return = 'Microsoft Dynamics CRM Learning Path' }
+ 2e49aa60-1bd3-43b6-8ab6-03ada3d9f08b { $return = 'Dynamics Data Integration' }
+ }
-# Write to the Azure Functions log stream.
-Write-Host "PowerShell HTTP trigger function processed a request."
+ if ([string]::IsNullOrEmpty($return)) {
+ $return = $Applications | Where-Object { $_.Appid -eq $ID } | Select-Object -ExpandProperty DisplayName
+ }
-# Interact with query parameters or the body of the request.
-$TenantFilter = $Request.Query.TenantFilter
-try {
- $ConditionalAccessPolicyOutput = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies" -tenantid $tenantfilter
- $AllNamedLocations = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations" -tenantid $tenantfilter
- $AllApplications = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/applications" -tenantid $tenantfilter
- $AllRoleDefinitions = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions" -tenantid $tenantfilter
- $GroupListOutput = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $tenantfilter
- $UserListOutput = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users" -tenantid $tenantfilter | Select-Object * -ExcludeProperty *extensionAttribute*
+ if ([string]::IsNullOrEmpty($return)) {
+ $return = $Applications | Where-Object { $_.ID -eq $ID } | Select-Object -ExpandProperty DisplayName
+ }
- $GraphRequest = foreach ($cap in $ConditionalAccessPolicyOutput) {
- $temp = [PSCustomObject]@{
- id = $cap.id
- displayName = $cap.displayName
- customer = $cap.Customer
- tenantID = $cap.TenantID
- createdDateTime = $(if (![string]::IsNullOrEmpty($cap.createdDateTime)) { [datetime]$cap.createdDateTime | Get-Date -Format "yyyy-MM-dd HH:mm" }else { "" })
- modifiedDateTime = $(if (![string]::IsNullOrEmpty($cap.modifiedDateTime)) { [datetime]$cap.modifiedDateTime | Get-Date -Format "yyyy-MM-dd HH:mm" }else { "" })
- state = $cap.state
- clientAppTypes = ($cap.conditions.clientAppTypes) -join ","
- includePlatforms = ($cap.conditions.platforms.includePlatforms) -join ","
- excludePlatforms = ($cap.conditions.platforms.excludePlatforms) -join ","
- includeLocations = (Get-LocationNameFromId -Locations $AllNamedLocations -id $cap.conditions.locations.includeLocations) -join ","
- excludeLocations = (Get-LocationNameFromId -Locations $AllNamedLocations -id $cap.conditions.locations.excludeLocations) -join ","
- includeApplications = ($cap.conditions.applications.includeApplications | ForEach-Object { Get-ApplicationNameFromId -Applications $AllApplications -id $_ }) -join ","
- excludeApplications = ($cap.conditions.applications.excludeApplications | ForEach-Object { Get-ApplicationNameFromId -Applications $AllApplications -id $_ }) -join ","
- includeUserActions = ($cap.conditions.applications.includeUserActions | Out-String)
- includeAuthenticationContextClassReferences = ($cap.conditions.applications.includeAuthenticationContextClassReferences | Out-String)
- includeUsers = ($cap.conditions.users.includeUsers | ForEach-Object { Get-UserNameFromId -Users $UserListOutput -id $_ }) | Out-String
- excludeUsers = ($cap.conditions.users.excludeUsers | ForEach-Object { Get-UserNameFromId -Users $UserListOutput -id $_ }) | Out-String
- includeGroups = ($cap.conditions.users.includeGroups | ForEach-Object { Get-GroupNameFromId -Groups $GroupListOutput -id $_ }) | Out-String
- excludeGroups = ($cap.conditions.users.excludeGroups | ForEach-Object { Get-GroupNameFromId -Groups $GroupListOutput -id $_ }) | Out-String
- includeRoles = ($cap.conditions.users.includeRoles | ForEach-Object { Get-RoleNameFromId -RoleDefinitions $AllRoleDefinitions -id $_ }) | Out-String
- excludeRoles = ($cap.conditions.users.excludeRoles | ForEach-Object { Get-RoleNameFromId -RoleDefinitions $AllRoleDefinitions -id $_ }) | Out-String
- grantControlsOperator = ($cap.grantControls.operator) -join ","
- builtInControls = ($cap.grantControls.builtInControls) -join ","
- customAuthenticationFactors = ($cap.grantControls.customAuthenticationFactors) -join ","
- termsOfUse = ($cap.grantControls.termsOfUse) -join ","
- rawjson = ($cap | ConvertTo-Json -Depth 100)
+ if ([string]::IsNullOrEmpty($return)) {
+ $return = ''
}
- $temp
+
+ return $return
}
- $StatusCode = [HttpStatusCode]::OK
-}
-catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
-}
-# Associate values to output bindings by calling 'Push-OutputBinding'.
-Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ try {
+ $ConditionalAccessPolicyOutput = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $tenantfilter
+ $AllNamedLocations = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -tenantid $tenantfilter
+ $AllApplications = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/applications' -tenantid $tenantfilter
+ $AllRoleDefinitions = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions' -tenantid $tenantfilter
+ $GroupListOutput = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$top=999' -tenantid $tenantfilter
+ $UserListOutput = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$top=999' -tenantid $tenantfilter | Select-Object * -ExcludeProperty *extensionAttribute*
+
+ $GraphRequest = foreach ($cap in $ConditionalAccessPolicyOutput) {
+ $temp = [PSCustomObject]@{
+ id = $cap.id
+ displayName = $cap.displayName
+ customer = $cap.Customer
+ tenantID = $cap.TenantID
+ createdDateTime = $(if (![string]::IsNullOrEmpty($cap.createdDateTime)) { [datetime]$cap.createdDateTime | Get-Date -Format 'yyyy-MM-dd HH:mm' }else { '' })
+ modifiedDateTime = $(if (![string]::IsNullOrEmpty($cap.modifiedDateTime)) { [datetime]$cap.modifiedDateTime | Get-Date -Format 'yyyy-MM-dd HH:mm' }else { '' })
+ state = $cap.state
+ clientAppTypes = ($cap.conditions.clientAppTypes) -join ','
+ includePlatforms = ($cap.conditions.platforms.includePlatforms) -join ','
+ excludePlatforms = ($cap.conditions.platforms.excludePlatforms) -join ','
+ includeLocations = (Get-LocationNameFromId -Locations $AllNamedLocations -id $cap.conditions.locations.includeLocations) -join ','
+ excludeLocations = (Get-LocationNameFromId -Locations $AllNamedLocations -id $cap.conditions.locations.excludeLocations) -join ','
+ includeApplications = ($cap.conditions.applications.includeApplications | ForEach-Object { Get-ApplicationNameFromId -Applications $AllApplications -id $_ }) -join ','
+ excludeApplications = ($cap.conditions.applications.excludeApplications | ForEach-Object { Get-ApplicationNameFromId -Applications $AllApplications -id $_ }) -join ','
+ includeUserActions = ($cap.conditions.applications.includeUserActions | Out-String)
+ includeAuthenticationContextClassReferences = ($cap.conditions.applications.includeAuthenticationContextClassReferences | Out-String)
+ includeUsers = ($cap.conditions.users.includeUsers | ForEach-Object { Get-UserNameFromId -Users $UserListOutput -id $_ }) | Out-String
+ excludeUsers = ($cap.conditions.users.excludeUsers | ForEach-Object { Get-UserNameFromId -Users $UserListOutput -id $_ }) | Out-String
+ includeGroups = ($cap.conditions.users.includeGroups | ForEach-Object { Get-GroupNameFromId -Groups $GroupListOutput -id $_ }) | Out-String
+ excludeGroups = ($cap.conditions.users.excludeGroups | ForEach-Object { Get-GroupNameFromId -Groups $GroupListOutput -id $_ }) | Out-String
+ includeRoles = ($cap.conditions.users.includeRoles | ForEach-Object { Get-RoleNameFromId -RoleDefinitions $AllRoleDefinitions -id $_ }) | Out-String
+ excludeRoles = ($cap.conditions.users.excludeRoles | ForEach-Object { Get-RoleNameFromId -RoleDefinitions $AllRoleDefinitions -id $_ }) | Out-String
+ grantControlsOperator = ($cap.grantControls.operator) -join ','
+ builtInControls = ($cap.grantControls.builtInControls) -join ','
+ customAuthenticationFactors = ($cap.grantControls.customAuthenticationFactors) -join ','
+ termsOfUse = ($cap.grantControls.termsOfUse) -join ','
+ rawjson = ($cap | ConvertTo-Json -Depth 100)
+ }
+ $temp
+ }
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = $ErrorMessage
}
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
+
+}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1
index 89e2ecfb2bff..22f708cfb080 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListConditionalAccessPolicyChanges {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1
index 61701c1d51a9..946eaddafaf0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1
@@ -1,66 +1,68 @@
using namespace System.Net
Function Invoke-ExecAddGDAPRole {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $Groups = $Request.body.gdapRoles
- $CustomSuffix = $Request.body.customSuffix
- $Table = Get-CIPPTable -TableName 'GDAPRoles'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $Groups = $Request.body.gdapRoles
+ $CustomSuffix = $Request.body.customSuffix
+ $Table = Get-CIPPTable -TableName 'GDAPRoles'
- $Results = [System.Collections.Generic.List[string]]::new()
- $ExistingGroups = New-GraphGetRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/groups' -tenantid $env:TenantID
+ $Results = [System.Collections.Generic.List[string]]::new()
+ $ExistingGroups = New-GraphGetRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/groups' -tenantid $env:TenantID
- $RoleMappings = foreach ($group in $Groups) {
- if ($CustomSuffix) {
- $GroupName = "M365 GDAP $($Group.Name) - $CustomSuffix"
- $MailNickname = "M365GDAP$(($Group.Name).replace(' ',''))$($CustomSuffix)"
+ $RoleMappings = foreach ($group in $Groups) {
+ if ($CustomSuffix) {
+ $GroupName = "M365 GDAP $($Group.Name) - $CustomSuffix"
+ $MailNickname = "M365GDAP$(($Group.Name).replace(' ',''))$($CustomSuffix)"
+ } else {
+ $GroupName = "M365 GDAP $($Group.Name)"
+ $MailNickname = "M365GDAP$(($Group.Name).replace(' ',''))"
+ }
+ try {
+ if ($GroupName -in $ExistingGroups.displayName) {
+ @{
+ PartitionKey = 'Roles'
+ RowKey = ($ExistingGroups | Where-Object -Property displayName -EQ $GroupName).id
+ RoleName = $Group.Name
+ GroupName = $GroupName
+ GroupId = ($ExistingGroups | Where-Object -Property displayName -EQ $GroupName).id
+ roleDefinitionId = $group.ObjectId
+ }
+ $Results.Add("M365 GDAP $($Group.Name) already exists")
} else {
- $GroupName = "M365 GDAP $($Group.Name)"
- $MailNickname = "M365GDAP$(($Group.Name).replace(' ',''))"
+ $BodyToship = [pscustomobject] @{'displayName' = $GroupName; 'description' = "This group is used to manage M365 partner tenants at the $($group.name) level."; securityEnabled = $true; mailEnabled = $false; mailNickname = $MailNickname } | ConvertTo-Json
+ $GraphRequest = New-GraphPostRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/groups' -tenantid $env:TenantID -type POST -body $BodyToship -verbose
+ @{
+ PartitionKey = 'Roles'
+ RowKey = $GraphRequest.Id
+ RoleName = $Group.Name
+ GroupName = $GroupName
+ GroupId = $GraphRequest.Id
+ roleDefinitionId = $group.ObjectId
+ }
+ $Results.Add("$GroupName added successfully")
}
- try {
- if ($GroupName -in $ExistingGroups.displayName) {
- @{
- PartitionKey = 'Roles'
- RowKey = ($ExistingGroups | Where-Object -Property displayName -EQ $GroupName).id
- RoleName = $Group.Name
- GroupName = $GroupName
- GroupId = ($ExistingGroups | Where-Object -Property displayName -EQ $GroupName).id
- roleDefinitionId = $group.ObjectId
- }
- $Results.Add("M365 GDAP $($Group.Name) already exists")
- } else {
- $BodyToship = [pscustomobject] @{'displayName' = $GroupName; 'description' = "This group is used to manage M365 partner tenants at the $($group.name) level."; securityEnabled = $true; mailEnabled = $false; mailNickname = $MailNickname } | ConvertTo-Json
- $GraphRequest = New-GraphPostRequest -NoAuthCheck $True -uri 'https://graph.microsoft.com/beta/groups' -tenantid $env:TenantID -type POST -body $BodyToship -verbose
- @{
- PartitionKey = 'Roles'
- RowKey = $GraphRequest.Id
- RoleName = $Group.Name
- GroupName = $GroupName
- GroupId = $GraphRequest.Id
- roleDefinitionId = $group.ObjectId
- }
- $Results.Add("$GroupName added successfully")
- }
- } catch {
- $Results.Add("Could not create GDAP group $($GroupName): $($_.Exception.Message)")
- }
- }
+ } catch {
+ $Results.Add("Could not create GDAP group $($GroupName): $($_.Exception.Message)")
+ }
+ }
- Add-CIPPAzDataTableEntity @Table -Entity $RoleMappings -Force
+ Add-CIPPAzDataTableEntity @Table -Entity $RoleMappings -Force
- $body = @{Results = @($Results) }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $body
- })
+ $body = @{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-ExecAutoExtendGDAP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1
index d0f1b5385e0c..f57c65330f6f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1
@@ -1,23 +1,25 @@
using namespace System.Net
Function Invoke-ExecAutoExtendGDAP {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Interact with query parameters or the body of the request.
- $Results = Set-CIPPGDAPAutoExtend -RelationShipid $Request.query.ID
+ # Interact with query parameters or the body of the request.
+ $Results = Set-CIPPGDAPAutoExtend -RelationShipid $Request.query.ID
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = @{ Results = $Results }
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = @{ Results = $Results }
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1
index bdfe01455cd4..61164e8968be 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecDeleteGDAPRelationship {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1
index 729c327b3528..23426c6f1a14 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1
@@ -1,33 +1,35 @@
using namespace System.Net
Function Invoke-ExecDeleteGDAPRoleMapping {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $Table = Get-CIPPTable -TableName 'GDAPRoles'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $Table = Get-CIPPTable -TableName 'GDAPRoles'
- Write-Host $Table
- try {
- $Filter = "PartitionKey eq 'Roles' and RowKey eq '{0}'" -f $Request.Query.GroupId
- $Entity = Get-CIPPAzDataTableEntity @Table -Filter $Filter
- Remove-AzDataTableEntity @Table -Entity $Entity
- $Results = [pscustomobject]@{'Results' = 'Success. GDAP relationship mapping deleted' }
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "GDAP relationship mapping deleted for $($Request.Query.GroupId)" -Sev 'Info'
+ Write-Host $Table
+ try {
+ $Filter = "PartitionKey eq 'Roles' and RowKey eq '{0}'" -f $Request.Query.GroupId
+ $Entity = Get-CIPPAzDataTableEntity @Table -Filter $Filter
+ Remove-AzDataTableEntity @Table -Entity $Entity
+ $Results = [pscustomobject]@{'Results' = 'Success. GDAP relationship mapping deleted' }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "GDAP relationship mapping deleted for $($Request.Query.GroupId)" -Sev 'Info'
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
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 4739df9c2df1..91cfa3388bb2 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
@@ -2,12 +2,14 @@ using namespace System.Net
Function Invoke-ExecGDAPInvite {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
+ $APIName = 'ExecGDAPInvite'
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$RoleMappings = $Request.body.gdapRoles
@@ -47,7 +49,7 @@ Function Invoke-ExecGDAPInvite {
if ($NewRelationshipRequest.action -eq 'lockForApproval') {
$InviteUrl = "https://admin.microsoft.com/AdminPortal/Home#/partners/invitation/granularAdminRelationships/$($NewRelationship.id)"
- $Uri = ([System.Uri]$TriggerMetadata.Headers.referer)
+ $Uri = ([System.Uri]$TriggerMetadata.Headers.Referer)
$TableFilter = [System.Web.HttpUtility]::UrlEncode(('Complex: id eq {0}' -f $NewRelationship.id))
$OnboardingUrl = $Uri.AbsoluteUri.Replace($Uri.PathAndQuery, "/tenant/administration/tenant-onboarding-wizard?tableFilter=$TableFilter")
@@ -69,8 +71,8 @@ Function Invoke-ExecGDAPInvite {
}
} catch {
$Message = 'Error creating GDAP relationship'
- Write-Host "GDAP ERROR: $($_.Exception.Message)"
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $env:TenantID -message "$($Message): $($_.Exception.Message)" -Sev 'Error'
+ Write-Host "GDAP ERROR: $($_.InvocationInfo.PositionMessage)"
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $env:TenantID -message "$($Message): $($_.Exception.Message)" -Sev 'Error' -LogData (Get-CippException -Exception $_)
}
$body = @{
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1
index 23565a19602e..7430ff9e1ce5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGDAPInviteApproved {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1
index 319118877545..c6a60971f1c6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1
@@ -2,7 +2,9 @@ using namespace System.Net
Function Invoke-ExecGDAPRemoveGArole {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1
index afc2bacfc630..218f0248f2cc 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGDAPInvite {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1
index 94f43d623abe..d3110cadd8ad 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGDAPQueue {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,7 +16,7 @@ Function Invoke-ListGDAPQueue {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
- $Table = Get-CIPPTable -TableName 'GDAPMigration'
+ $Table = Get-CIPPTable -TableName 'GDAPMigration'
$QueuedApps = Get-CIPPAzDataTableEntity @Table
$CurrentStandards = foreach ($QueueFile in $QueuedApps) {
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1
index 0102748cb4f8..f39e16ebd1fc 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGDAPRoles {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,7 +16,7 @@ Function Invoke-ListGDAPRoles {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
- $Table = Get-CIPPTable -TableName 'GDAPRoles'
+ $Table = Get-CIPPTable -TableName 'GDAPRoles'
$Groups = Get-CIPPAzDataTableEntity @Table
$MappedGroups = foreach ($Group in $Groups) {
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 4a43292deba6..091d903054b7 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddStandardsDeploy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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
index 27c8774bae3c..8e5186727b8f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddStandardsTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -22,7 +24,7 @@ Function Invoke-AddStandardsTemplate {
}
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
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1
index e1930a1cbc04..5bf7c40a6741 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-BestPracticeAnalyser_List {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.BestPracticeAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -13,7 +15,7 @@ Function Invoke-BestPracticeAnalyser_List {
$Tenants = Get-Tenants
$Table = get-cipptable 'cachebpa'
- $Results = (Get-CIPPAzDataTableEntity @Table) | ForEach-Object {
+ $Results = (Get-CIPPAzDataTableEntity @Table) | ForEach-Object {
$_.UnusedLicenseList = @(ConvertFrom-Json -ErrorAction silentlycontinue -InputObject $_.UnusedLicenseList)
$_
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1
index c205bf24d57b..f200e4729272 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecStandardsRun {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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 0e632d4fba35..22e078617475 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListBPA {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.BestPracticeAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,14 +20,18 @@ Function Invoke-ListBPA {
# Get all possible JSON files for reports, find the correct one, select the Columns
$JSONFields = @()
$Columns = $null
-(Get-ChildItem -Path 'Config\*.BPATemplate.json' -Recurse | Select-Object -ExpandProperty FullName | ForEach-Object {
- $Template = $(Get-Content $_) | ConvertFrom-Json
+ $BPATemplateTable = Get-CippTable -tablename 'templates'
+ $Filter = "PartitionKey eq 'BPATemplate'"
+ $Templates = (Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json
+
+ $Templates | ForEach-Object {
+ $Template = $_
if ($Template.Name -eq $NAME) {
$JSONFields = $Template.Fields | Where-Object { $_.StoreAs -eq 'JSON' } | ForEach-Object { $_.name }
$Columns = $Template.fields.FrontendFields | Where-Object -Property name -NE $null
$Style = $Template.Style
}
- })
+ }
if ($Request.query.tenantFilter -ne 'AllTenants' -and $Style -eq 'Tenant') {
@@ -46,7 +52,12 @@ Function Invoke-ListBPA {
$Data = $mergedObject
} else {
+ $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
$Tenants = Get-Tenants -IncludeErrors
+ if ($AllowedTenants -notcontains 'AllTenants') {
+ $Tenants = $Tenants | Where-Object -Property customerId -In $AllowedTenants
+ }
+ Write-Information ($tenants.defaultDomainName | ConvertTo-Json)
$Data = (Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$NAME'") | ForEach-Object {
$row = $_
$JSONFields | ForEach-Object {
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 2185772864cd..376a1f4e592b 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListBPATemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.BestPracticeAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,17 +14,27 @@ Function Invoke-ListBPATemplates {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
Write-Host 'PowerShell HTTP trigger function processed a request.'
- Write-Host $Request.query.id
+
+ $Table = Get-CippTable -tablename 'templates'
- $Templates = Get-ChildItem 'Config\*.BPATemplate.json'
+ $Templates = Get-ChildItem 'Config\*.BPATemplate.json' | ForEach-Object {
+ $Entity = @{
+ JSON = "$(Get-Content $_)"
+ RowKey = "$($_.name)"
+ PartitionKey = 'BPATemplate'
+ GUID = "$($_.name)"
+ }
+ Add-CIPPAzDataTableEntity @Table -Entity $Entity -Force
+ }
+
+ $Filter = "PartitionKey eq 'BPATemplate'"
+ $Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json
if ($Request.Query.RawJson) {
- $Templates = $Templates | ForEach-Object {
- $(Get-Content $_) | ConvertFrom-Json
- }
+ $Templates
} else {
$Templates = $Templates | ForEach-Object {
- $Template = $(Get-Content $_) | ConvertFrom-Json
+ $Template = $_
@{
Data = $Template.fields
Name = $Template.Name
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1
index 76fe08536529..95077930211f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1
@@ -4,7 +4,9 @@ using namespace System.Net
Function Invoke-ListDomainAnalyser {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.DomainAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1
index dfbd46514448..fb04e3d547ca 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDomainHealth {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.DomainAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
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
index acc984d6e0ab..1b17d33131a2 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-listStandardTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,11 +13,11 @@ Function Invoke-listStandardTemplates {
$APIName = $TriggerMetadata.FunctionName
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'StandardsTemplate'"
+ $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
+ $data
} | Sort-Object -Property displayName
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/invoke-DomainAnalyser_List.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/invoke-DomainAnalyser_List.ps1
index e1c7c345e511..1682b8b30cd1 100644
--- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/invoke-DomainAnalyser_List.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/invoke-DomainAnalyser_List.ps1
@@ -4,7 +4,9 @@ using namespace System.Net
Function Invoke-DomainAnalyser_List {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.DomainAnalyser.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -19,7 +21,7 @@ Function Invoke-DomainAnalyser_List {
try {
# Extract json from table results
$Results = foreach ($DomainAnalyserResult in (Get-CIPPAzDataTableEntity @DomainTable).DomainAnalyser) {
- try {
+ try {
if (![string]::IsNullOrEmpty($DomainAnalyserResult)) {
$Object = $DomainAnalyserResult | ConvertFrom-Json -ErrorAction SilentlyContinue
$Object
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
new file mode 100644
index 000000000000..15c2d49afc0d
--- /dev/null
+++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1
@@ -0,0 +1,41 @@
+using namespace System.Net
+
+Function Invoke-AddBPATemplate {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Tenant.BestPracticeAnalyser.ReadWrite
+ #>
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+
+ try {
+
+ $Table = Get-CippTable -tablename 'templates'
+ $Table.Force = $true
+ Add-CIPPAzDataTableEntity @Table -Entity @{
+ JSON = "$($Request.body | ConvertTo-Json -Depth 10)"
+ RowKey = $Request.body.name
+ PartitionKey = 'BPATemplate'
+ GUID = $Request.body.name
+ }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created BPA named $($Request.body.name)" -Sev 'Debug'
+
+ $body = [pscustomobject]@{'Results' = 'Successfully added template' }
+ } catch {
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "BPA Template Creation failed: $($_.Exception.Message)" -Sev 'Error'
+ $body = [pscustomobject]@{'Results' = "BPA Template Creation failed: $($_.Exception.Message)" }
+ }
+
+
+ # 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/Tools/Invoke-ExecGraphExplorerPreset.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1
index f04c365c5ccf..01e72df98868 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
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecGraphExplorerPreset {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1
index c94b9ecf1ea2..00c2cffc02e7 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-AddTenantAllowBlockList {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,10 +22,10 @@ Function Invoke-AddTenantAllowBlockList {
tenantid = $Request.body.tenantid
cmdlet = 'New-TenantAllowBlockListItems'
cmdParams = @{
- Entries = [string[]]$blocklistobj.entries
- ListType = [string]$blocklistobj.listType
- Notes = [string]$blocklistobj.notes
- $blocklistobj.listMethod = [bool]$true
+ Entries = [string[]]$blocklistobj.entries
+ ListType = [string]$blocklistobj.listType
+ Notes = [string]$blocklistobj.notes
+ $blocklistobj.listMethod = [bool]$true
}
}
@@ -43,10 +45,10 @@ Function Invoke-AddTenantAllowBlockList {
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = @{
- 'Results' = $result
- 'Request' = $ExoRequest
- }
- })
+ StatusCode = [HttpStatusCode]::OK
+ Body = @{
+ 'Results' = $result
+ 'Request' = $ExoRequest
+ }
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1
index 3f78672c9894..5ea8abad3067 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1
@@ -3,16 +3,18 @@ using namespace System.Net
Function Invoke-ExecExtensionNinjaOneQueue {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
+
Switch ($QueueItem.NinjaAction) {
'StartAutoMapping' { Invoke-NinjaOneOrgMapping }
- 'AutoMapTenant' { Invoke-NinjaOneOrgMappingTenant -QueueItem $QueueItem }
+ 'AutoMapTenant' { Invoke-NinjaOneOrgMappingTenant -QueueItem $QueueItem }
'SyncTenant' { Invoke-NinjaOneTenantSync -QueueItem $QueueItem }
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1
index d3695a00742f..1adc1799debd 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1
@@ -1,26 +1,28 @@
using namespace System.Net
Function Invoke-ExecListAppId {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- $ResponseURL = "$(($Request.headers.'x-ms-original-url').replace('/api/ExecListAppId','/api/ExecSAMSetup'))"
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $ResponseURL = "$(($Request.headers.'x-ms-original-url').replace('/api/ExecListAppId','/api/ExecSAMSetup'))"
- $Results = @{
- applicationId = $ENV:ApplicationID
- tenantId = $ENV:TenantID
- refreshUrl = "https://login.microsoftonline.com/$ENV:TenantID/oauth2/v2.0/authorize?client_id=$ENV:ApplicationID&response_type=code&redirect_uri=$ResponseURL&response_mode=query&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default+offline_access+profile+openid&state=1&prompt=select_account"
- }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ $Results = @{
+ applicationId = $ENV:ApplicationID
+ tenantId = $ENV:TenantID
+ refreshUrl = "https://login.microsoftonline.com/$ENV:TenantID/oauth2/v2.0/authorize?client_id=$ENV:ApplicationID&response_type=code&redirect_uri=$ResponseURL&response_mode=query&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default+offline_access+profile+openid&state=1&prompt=select_account"
+ }
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1
index a78905f8386a..403e4e3dcdfa 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1
@@ -1,30 +1,32 @@
using namespace System.Net
Function Invoke-ExecRestoreDeleted {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.ReadWrite
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
- try {
- $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/directory/deletedItems/$($Request.query.ID)/restore" -tenantid $TenantFilter -type POST -body '{}' -verbose
- $Results = [pscustomobject]@{'Results' = 'Successfully completed request.' }
- } catch {
- $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
- }
+ try {
+ $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/directory/deletedItems/$($Request.query.ID)/restore" -tenantid $TenantFilter -type POST -body '{}' -verbose
+ $Results = [pscustomobject]@{'Results' = 'Successfully completed request.' }
+ } catch {
+ $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" }
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $Results
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $Results
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1
index 2b4fd7d70190..6c373d6deaf4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSchedulerBillingRun {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Scheduler.Billing.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1
index b70f200aae55..e5293d373605 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSendOrgMessage {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -81,7 +83,7 @@ Function Invoke-ExecSendOrgMessage {
}
})
})
- })
+ })
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1
index 0d5b9b9e253d..98dae4f0f308 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecSyncAPDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
index eda323666fa1..f16a350fc2c6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ExecUniversalSearch {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1
index ab9092f13c1d..ec1381e24e45 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
function Invoke-ExecUserSettings {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.ReadWrite
#>
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1
index d9d49840c7b4..31c3e5dd4675 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAllTenantDeviceCompliance {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.DeviceCompliance.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -19,18 +21,18 @@ Function Invoke-ListAllTenantDeviceCompliance {
$TenantFilter = $Request.Query.TenantFilter
try {
if ($TenantFilter -eq 'AllTenants') {
- $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedDeviceCompliances'
- $StatusCode = [HttpStatusCode]::OK
+ $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedDeviceCompliances'
+ $StatusCode = [HttpStatusCode]::OK
} else {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedDeviceCompliances?`$top=999&`$filter=organizationId eq '$TenantFilter'"
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/managedDeviceCompliances?`$top=999&`$filter=organizationId eq '$TenantFilter'"
$StatusCode = [HttpStatusCode]::OK
}
- if ($GraphRequest.value.count -lt 1) {
+ if ($GraphRequest.value.count -lt 1) {
$StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = 'No data found - This client might not be onboarded in Lighthouse'
+ $GraphRequest = 'No data found - This client might not be onboarded in Lighthouse'
}
- } catch {
+ } catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
$StatusCode = [HttpStatusCode]::Forbidden
$GraphRequest = "Could not connect to Azure Lighthouse API: $($ErrorMessage)"
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1
index 1b6723d21c17..93a95f880983 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAppStatus {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Device.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1
index 43ae12082452..1b4c8f4a1440 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAutopilotconfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1
index f1b1b0592e76..0a02e1814601 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListAzureADConnectStatus {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -41,10 +43,10 @@ Function Invoke-ListAzureADConnectStatus {
$GraphRequest = foreach ($Type in $types) {
New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($Type)?`$select=$($selectlist -join ',')" -tenantid $TenantFilter | ForEach-Object {
if ($_.id -ne $null) {
- $_ | Add-Member -NotePropertyName ObjectType -NotePropertyValue $Type
+ $_ | Add-Member -NotePropertyName ObjectType -NotePropertyValue $Type
$_
}
-
+
}
}
$ObjectsInError = @($GraphRequest)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1
index 3bbefa764b84..9112981dad14 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListCalendarPermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1
index 768417a1db23..00a7b0410365 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListContacts {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Contact.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1
index 5b5a244c7e72..78a4f1bcbbf0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDefenderState {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -19,11 +21,11 @@ Function Invoke-ListDefenderState {
$TenantFilter = $Request.Query.TenantFilter
try {
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/windowsProtectionStates?`$top=999&`$filter=tenantId eq '$TenantFilter'"
- if ($GraphRequest.tenantDisplayName.length -lt 1) {
+ if ($GraphRequest.tenantDisplayName.length -lt 1) {
$StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = 'No data found - This client might not be onboarded in Lighthouse'
+ $GraphRequest = 'No data found - This client might not be onboarded in Lighthouse'
}
- } catch {
+ } catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
$StatusCode = [HttpStatusCode]::Forbidden
$GraphRequest = "Could not connect to Azure Lighthouse API: $($ErrorMessage)"
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1
index 2011f161abaf..01e7cacb254f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDefenderTVM {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -40,7 +42,7 @@ Function Invoke-ListDefenderTVM {
$StatusCode = [HttpStatusCode]::Forbidden
$GroupObj = $ErrorMessage
}
- # Associate values to output bindings by calling 'Push-OutputBinding'.
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = @($GroupObj)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1
index 2f3488655fa0..26d68ac580b7 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDeletedItems {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -19,7 +21,7 @@ Function Invoke-ListDeletedItems {
$TenantFilter = $Request.Query.TenantFilter
$Types = 'Application', 'User', 'Device', 'Group'
$GraphRequest = foreach ($Type in $Types) {
- (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directory/deletedItems/microsoft.graph.$($Type)" -tenantid $TenantFilter) | Where-Object -Property '@odata.context' -NotLike '*graph.microsoft.com*' | Select-Object *, @{ Name = 'TargetType'; Expression = { $Type } }
+ (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directory/deletedItems/microsoft.graph.$($Type)" -tenantid $TenantFilter) | Where-Object -Property '@odata.context' -NotLike '*graph.microsoft.com*' | Select-Object *, @{ Name = 'TargetType'; Expression = { $Type } }
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1
index f3a4d9f309c9..1d561c958f65 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListDeviceDetails {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Device.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -28,7 +30,7 @@ Function Invoke-ListDeviceDetails {
$Found = $False
if ($SeriaNumber -and $DeviceName) {
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=serialnumber eq '$DeviceSerial' and deviceName eq '$DeviceName'" -Tenantid $tenantfilter
-
+
if (($GraphRequest | Measure-Object).count -eq 1 -and $GraphRequest.'@odata.count' -ne 0 ) {
$Found = $True
}
@@ -75,7 +77,7 @@ Function Invoke-ListDeviceDetails {
$DeviceGroups = Get-GraphBulkResultByID -Results $BulkResults -ID 'DeviceGroups' -Value
$CompliancePolicies = Get-GraphBulkResultByID -Results $BulkResults -ID 'CompliancePolicies' -Value
- $DetectedApps = Get-GraphBulkResultByID -Results $BulkResults -ID 'DetectedApps'
+ $DetectedApps = Get-GraphBulkResultByID -Results $BulkResults -ID 'DetectedApps'
$Null = $GraphRequest | Add-Member -NotePropertyName 'DetectedApps' -NotePropertyValue ($DetectedApps.DetectedApps | Select-Object id, displayName, version)
$Null = $GraphRequest | Add-Member -NotePropertyName 'CompliancePolicies' -NotePropertyValue ($CompliancePolicies | Select-Object id, displayname, UserPrincipalName, state)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1
index 113b9d53a304..149eb8fa9a04 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1
@@ -1,35 +1,37 @@
using namespace System.Net
Function Invoke-ListDomains {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Administration.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
- try {
- $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Select-Object id, isdefault, isinitial | Sort-Object isdefault
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
- }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ try {
+ $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Select-Object id, isdefault, isinitial | Sort-Object isdefault
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = $ErrorMessage
+ }
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1
index 897fcf53b3ed..8c96c119f2f0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListExConnectorTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -14,14 +16,14 @@ Function Invoke-ListExConnectorTemplates {
#List new policies
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'ExConnectorTemplate'"
+ $Filter = "PartitionKey eq 'ExConnectorTemplate'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
$GUID = $_.RowKey
$Direction = $_.direction
- $data = $_.JSON | ConvertFrom-Json
+ $data = $_.JSON | ConvertFrom-Json
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $GUID
$data | Add-Member -NotePropertyName 'cippconnectortype' -NotePropertyValue $Direction
- $data
+ $data
} | Sort-Object -Property displayName
if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property RowKey -EQ $Request.query.id }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1
index 35b1863f45f8..95120eab6ac6 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListExchangeConnectors {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1
index 5e9cd48198c8..e2feff0542d7 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListExtensionsConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1
index 55fb22f3f99e..f5c773792ce2 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListExternalTenantInfo {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1
index 2be8941920f1..e3060be55daa 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
function Invoke-ListFunctionParameters {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
param($Request, $TriggerMetadata)
@@ -25,7 +27,7 @@ function Invoke-ListFunctionParameters {
$CommandQuery.Name = $Function
}
$IgnoreList = 'entryPoint', 'internal'
- $CommonParameters = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable', 'TenantFilter', 'APIName', 'ExecutingUser', 'ProgressAction')
+ $CommonParameters = @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction', 'ErrorVariable', 'WarningVariable', 'InformationVariable', 'OutVariable', 'OutBuffer', 'PipelineVariable', 'TenantFilter', 'APIName', 'ExecutingUser', 'ProgressAction', 'WhatIf', 'Confirm')
$TemporaryBlacklist = 'Get-CIPPAuthentication', 'Invoke-CippWebhookProcessing', 'Invoke-ListFunctionParameters', 'New-CIPPAPIConfig', 'New-CIPPGraphSubscription'
try {
$Functions = Get-Command @CommandQuery | Where-Object { $_.Visibility -eq 'Public' }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1
index 7a0ca462e60e..037801e25962 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListFunctionStats {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1
index ddb0c55b1444..32afe59ac176 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGenericAllTenants {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1
index 80012cd30de9..8cfed503e5cb 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGenericTestFunction {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1
index 100aa6a450ba..1212c03efee0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGraphExplorerPresets {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
index cd0f73a61f45..4177e3e24368 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphRequest.ps1
@@ -2,10 +2,9 @@
function Invoke-ListGraphRequest {
<#
.FUNCTIONALITY
- Entrypoint
-
+ Entrypoint
.ROLE
- Core.Read
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1
index 205410cd9f92..6a6bc6b12248 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGroupTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -17,9 +19,9 @@ Function Invoke-ListGroupTemplates {
#List new policies
$Table = Get-CippTable -tablename 'templates'
- $Filter = "PartitionKey eq 'GroupTemplate'"
+ $Filter = "PartitionKey eq 'GroupTemplate'"
$Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object {
- $data = $_.JSON | ConvertFrom-Json
+ $data = $_.JSON | ConvertFrom-Json
$data | Add-Member -MemberType NoteProperty -Name GUID -Value $_.RowKey -Force
$data
} | Sort-Object -Property displayName
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1
index d25ccd2c6d9f..b59ceae2fd06 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListGroups {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,16 +22,16 @@ Function Invoke-ListGroups {
$TenantFilter = $Request.Query.TenantFilter
$selectstring = "id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,grouptypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName&`$expand=members(`$select=userPrincipalName)"
- if ($Request.Query.GroupID) {
+ if ($Request.Query.GroupID) {
$groupid = $Request.query.groupid
$selectstring = 'id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,groupTypes,userPrincipalName'
}
- if ($Request.Query.members) {
+ if ($Request.Query.members) {
$members = 'members'
$selectstring = 'id,userPrincipalName,displayName,hideFromOutlookClients,hideFromAddressLists,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule'
}
- if ($Request.Query.owners) {
+ if ($Request.Query.owners) {
$members = 'owners'
$selectstring = 'id,userPrincipalName,displayName,hideFromOutlookClients,hideFromAddressLists,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule'
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1
index 84b1b3cae514..e00ba611aa67 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1
@@ -1,49 +1,51 @@
using namespace System.Net
Function Invoke-ListHaloClients {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Extension.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- try {
- $Table = Get-CIPPTable -TableName Extensionsconfig
- $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).HaloPSA
- $Token = Get-HaloToken -configuration $Configuration
- $i = 1
- $RawHaloClients = do {
- $Result = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Client?page_no=$i&page_size=999&pageinate=true" -ContentType 'application/json' -Method GET -Headers @{Authorization = "Bearer $($token.access_token)" }
- $Result.clients | Select-Object * -ExcludeProperty logo
- $i++
- $pagecount = [Math]::Ceiling($Result.record_count / 999)
- } while ($i -le $pagecount)
- $HaloClients = $RawHaloClients | ForEach-Object {
- [PSCustomObject]@{
- label = $_.name
- value = $_.id
- }
- }
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $HaloClients = $ErrorMessage
+ # Interact with query parameters or the body of the request.
+ try {
+ $Table = Get-CIPPTable -TableName Extensionsconfig
+ $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).HaloPSA
+ $Token = Get-HaloToken -configuration $Configuration
+ $i = 1
+ $RawHaloClients = do {
+ $Result = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Client?page_no=$i&page_size=999&pageinate=true" -ContentType 'application/json' -Method GET -Headers @{Authorization = "Bearer $($token.access_token)" }
+ $Result.clients | Select-Object * -ExcludeProperty logo
+ $i++
+ $pagecount = [Math]::Ceiling($Result.record_count / 999)
+ } while ($i -le $pagecount)
+ $HaloClients = $RawHaloClients | ForEach-Object {
+ [PSCustomObject]@{
+ label = $_.name
+ value = $_.id
+ }
}
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $HaloClients = $ErrorMessage
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($HaloClients)
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($HaloClients)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1
index 985473bc5bb8..bf031cfb22a8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListIPWhitelist {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1
index 3ce42719c362..559543a51a67 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1
@@ -1,36 +1,38 @@
using namespace System.Net
Function Invoke-ListInactiveAccounts {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- if ($TenantFilter -eq 'AllTenants') { $TenantFilter = (get-tenants).customerId }
- try {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/inactiveUsers?`$count=true" -tenantid $env:TenantId | Where-Object { $_.tenantId -in $TenantFilter }
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = "Could not connect to Azure Lighthouse API: $($ErrorMessage)"
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ if ($TenantFilter -eq 'AllTenants') { $TenantFilter = (get-tenants).customerId }
+ try {
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/inactiveUsers?`$count=true" -tenantid $env:TenantId | Where-Object { $_.tenantId -in $TenantFilter }
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = "Could not connect to Azure Lighthouse API: $($ErrorMessage)"
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1
index cb98c87d6e67..b7043311731c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1
@@ -1,35 +1,37 @@
using namespace System.Net
Function Invoke-ListIntuneIntents {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- try {
- $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/Intents?`$expand=settings,categories" -tenantid $TenantFilter
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ try {
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/Intents?`$expand=settings,categories" -tenantid $TenantFilter
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = $ErrorMessage
+ }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1
index 5429292d5a6c..6bbf36a98274 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListIntunePolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -24,7 +26,8 @@ Function Invoke-ListIntunePolicy {
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)('$ID')" -tenantid $tenantfilter
} else {
- $GraphURLS = @("https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$select=id,displayName,lastModifiedDateTime,roleScopeTagIds,microsoft.graph.unsupportedDeviceConfiguration/originalEntityTypeName&`$expand=assignments&top=1000",
+ $GraphURLS = @("https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$select=id,displayName,lastModifiedDateTime,roleScopeTagIds,microsoft.graph.unsupportedDeviceConfiguration/originalEntityTypeName&`$expand=assignments&top=1000"
+ 'https://graph.microsoft.com/beta/deviceManagement/windowsDriverUpdateProfiles'
"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=1000"
"https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations?`$expand=assignments&`$filter=microsoft.graph.androidManagedStoreAppConfiguration/appSupportsOemConfig%20eq%20true"
'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies'
@@ -46,7 +49,7 @@ Function Invoke-ListIntunePolicy {
default { $_.'assignments@odata.context' }
}
if ($_.displayname -eq $null) { $_ | Add-Member -NotePropertyName displayName -NotePropertyValue $_.name }
- $_ | Add-Member -NotePropertyName PolicyTypeName -NotePropertyValue $policyTypeName
+ $_ | Add-Member -NotePropertyName PolicyTypeName -NotePropertyValue $policyTypeName
$_ | Add-Member -NotePropertyName URLName -NotePropertyValue $URLName
$_
} | Where-Object { $_.DisplayName -ne $null }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1
index d9c02d090fb2..c94431612970 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListIntuneTemplates {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -36,7 +38,7 @@ Function Invoke-ListIntuneTemplates {
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force
$data
} | Sort-Object -Property displayName
- }
+ }
if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property guid -EQ $Request.query.id }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1
index 061146ae725f..09f488be2304 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListKnownIPDb {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1
index ead6a0d2cd9d..82bb1e4aab1f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListLicenses {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Directory.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -47,9 +49,13 @@ Function Invoke-ListLicenses {
Write-Host "Started permissions orchestration with ID = '$InstanceId'"
}
} else {
- $GraphRequest = $Rows | ForEach-Object {
- $TermInfo = $_.TermInfo | ConvertFrom-Json -ErrorAction SilentlyContinue
- $_.TermInfo = $TermInfo
+ $GraphRequest = $Rows | Where-Object { $_.License } | ForEach-Object {
+ if ($_.TermInfo) {
+ $TermInfo = $_.TermInfo | ConvertFrom-Json -ErrorAction SilentlyContinue
+ $_.TermInfo = $TermInfo
+ } else {
+ $_ | Add-Member -NotePropertyName TermInfo -NotePropertyValue $null
+ }
$_
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
index a3963bd0bc94..0a3877cfc4c9 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
@@ -3,14 +3,18 @@ using namespace System.Net
Function Invoke-ListLogs {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
+ $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $TenantList = Get-Tenants -IncludeErrors
if ($request.Query.Filter -eq 'True') {
$LogLevel = if ($Request.query.Severity) { ($Request.query.Severity).split(',') } else { 'Info', 'Warn', 'Error', 'Critical', 'Alert' }
$PartitionKey = $Request.query.DateFilter
@@ -34,6 +38,15 @@ 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) {
+
+ if ($AllowedTenants -notcontains 'AllTenants') {
+ if ($Row.Tenant -ne 'None') {
+ $Tenant = $TenantList | Where-Object -Property defaultDomainName -EQ $Row.Tenant
+ if ($Tenant.customerId -notin $AllowedTenants) {
+ continue
+ }
+ }
+ }
$LogData = if ($Row.LogData -and (Test-Json -Json $Row.LogData)) {
$Row.LogData | ConvertFrom-Json
} else { $Row.LogData }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1
index 118ca8d4b050..e73aa9205517 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMFAUsers {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1
index ef93210d4c25..4386157564d4 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailboxCAS {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1
deleted file mode 100644
index 8199d4204326..000000000000
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices copy.ps1
+++ /dev/null
@@ -1,55 +0,0 @@
-using namespace System.Net
-
-Function Invoke-ListMailboxMobileDevices {
- <#
- .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'
-
-
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
-
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- $Mailbox = $Request.Query.Mailbox
-
- Write-Host $TenantFilter
- Write-Host $Mailbox
-
- $Bytes = [System.Text.Encoding]::UTF8.GetBytes($Mailbox)
- $base64IdentityParam = [Convert]::ToBase64String($Bytes)
-
- try {
- $GraphRequest = New-GraphGetRequest -uri "https://outlook.office365.com:443/adminapi/beta/$($TenantFilter)/mailbox('$($base64IdentityParam)')/MobileDevice/Exchange.GetMobileDeviceStatistics()/?IsEncoded=True" -Tenantid $tenantfilter -scope ExchangeOnline | Select-Object @{ Name = 'clientType'; Expression = { $_.ClientType } },
- @{ Name = 'clientVersion'; Expression = { $_.ClientVersion } },
- @{ Name = 'deviceAccessState'; Expression = { $_.DeviceAccessState } },
- @{ Name = 'deviceFriendlyName'; Expression = { if ([string]::IsNullOrEmpty($_.DeviceFriendlyName)) { 'Unknown' }else { $_.DeviceFriendlyName } } },
- @{ Name = 'deviceModel'; Expression = { $_.DeviceModel } },
- @{ Name = 'deviceOS'; Expression = { $_.DeviceOS } },
- @{ Name = 'deviceType'; Expression = { $_.DeviceType } },
- @{ Name = 'firstSync'; Expression = { $_.FirstSyncTime.toString() } },
- @{ Name = 'lastSyncAttempt'; Expression = { $_.LastSyncAttemptTime.toString() } },
- @{ Name = 'lastSuccessSync'; Expression = { $_.LastSuccessSync.toString() } },
- @{ Name = 'status'; Expression = { $_.Status } },
- @{ Name = 'deviceID'; Expression = { $_.deviceID } },
- @{ Name = 'Guid'; Expression = { $_.Guid } }
-
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
- }
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
-
-}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1
index 8199d4204326..d1bab545e7a8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailboxMobileDevices {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1
index f47458585c09..35d44175e0a5 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1
@@ -1,4 +1,10 @@
function Invoke-ListMailboxRestores {
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
+ #>
param($Request, $TriggerMetadata)
$APIName = $TriggerMetadata.FunctionName
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1
index 696369dc8c38..e5bd0a1530c9 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailboxRules {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxStatistics.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxStatistics.ps1
index d1f1af749fb7..795812096c50 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxStatistics.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxStatistics.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailboxStatistics {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1
index c924a85ea1dd..7a125550426a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListMailboxes {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1
index 0acac97628d5..c1fb2e5c731a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListNamedLocations {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -18,7 +20,7 @@ Function Invoke-ListNamedLocations {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
try {
- $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -Tenantid $tenantfilter | Select-Object *,
+ $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -Tenantid $tenantfilter | Select-Object *,
@{
name = 'rangeOrLocation'
expression = { if ($_.ipRanges) { $_.ipranges.cidrAddress -join ', ' } else { $_.countriesAndRegions -join ', ' } }
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1
index 68545565ee6b..a375c65deb04 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListNotificationConfig {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.AppSettings.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1
index 13fafdf39a2c..2183317e991d 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1
@@ -1,54 +1,56 @@
using namespace System.Net
Function Invoke-ListOAuthApps {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Application.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
-
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
-
-
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
-
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- if ($TenantFilter -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $tenants = $TenantFilter }
-
- try {
- $GraphRequest = foreach ($Tenant in $Tenants) {
- try {
- $ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=id,displayName,appid" -tenantid $Tenant
- New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/oauth2PermissionGrants' -tenantid $Tenant | ForEach-Object {
- $CurrentServicePrincipal = ($ServicePrincipals | Where-Object -Property id -EQ $_.clientId)
- [PSCustomObject]@{
- Tenant = $Tenant
- Name = $CurrentServicePrincipal.displayName
- ApplicationID = $CurrentServicePrincipal.appid
- ObjectID = $_.clientId
- Scope = ($_.scope -join ',')
- StartTime = $_.startTime
- }
- }
- $StatusCode = [HttpStatusCode]::OK
- } catch {
- continue
- }
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
+
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+
+
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
+
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ if ($TenantFilter -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $tenants = $TenantFilter }
+
+ try {
+ $GraphRequest = foreach ($Tenant in $Tenants) {
+ try {
+ $ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=id,displayName,appid" -tenantid $Tenant
+ New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/oauth2PermissionGrants' -tenantid $Tenant | ForEach-Object {
+ $CurrentServicePrincipal = ($ServicePrincipals | Where-Object -Property id -EQ $_.clientId)
+ [PSCustomObject]@{
+ Tenant = $Tenant
+ Name = $CurrentServicePrincipal.displayName
+ ApplicationID = $CurrentServicePrincipal.appid
+ ObjectID = $_.clientId
+ Scope = ($_.scope -join ',')
+ StartTime = $_.startTime
+ }
}
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- $StatusCode = [HttpStatusCode]::Forbidden
- $GraphRequest = $ErrorMessage
+ $StatusCode = [HttpStatusCode]::OK
+ } catch {
+ continue
+ }
}
-
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = $StatusCode
- Body = @($GraphRequest)
- })
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ $StatusCode = [HttpStatusCode]::Forbidden
+ $GraphRequest = $ErrorMessage
+ }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = $StatusCode
+ Body = @($GraphRequest)
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1
index 20842ce9dafb..feb6de0d2f74 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1
@@ -1,32 +1,34 @@
using namespace System.Net
Function Invoke-ListOrg {
- <#
+ <#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Core.Read
#>
- [CmdletBinding()]
- param($Request, $TriggerMetadata)
+ [CmdletBinding()]
+ param($Request, $TriggerMetadata)
- $APIName = $TriggerMetadata.FunctionName
- Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
+ $APIName = $TriggerMetadata.FunctionName
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
- # Write to the Azure Functions log stream.
- Write-Host 'PowerShell HTTP trigger function processed a request.'
+ # Write to the Azure Functions log stream.
+ Write-Host 'PowerShell HTTP trigger function processed a request.'
- # Interact with query parameters or the body of the request.
- $TenantFilter = $Request.Query.TenantFilter
- if ($TenantFilter -eq 'AllTenants') {
-
- } else {
- $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/organization' -tenantid $TenantFilter
- }
+ # Interact with query parameters or the body of the request.
+ $TenantFilter = $Request.Query.TenantFilter
+ if ($TenantFilter -eq 'AllTenants') {
- # Associate values to output bindings by calling 'Push-OutputBinding'.
- Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
- StatusCode = [HttpStatusCode]::OK
- Body = $GraphRequest
- })
+ } else {
+ $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/organization' -tenantid $TenantFilter
+ }
+
+ # Associate values to output bindings by calling 'Push-OutputBinding'.
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::OK
+ Body = $GraphRequest
+ })
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1
index 591b6b23d3bf..6ca16cfe8fd9 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListPartnerRelationships {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Relationship.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1
index 24c7020f0e31..96c4a6eeb13a 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListPendingWebhooks {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1
index 86062e4e80fa..0dfbeaa01642 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListPotentialApps {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1
index 6eca5db05c5b..b56c40828a63 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListRoles {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Role.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -21,7 +23,7 @@ Function Invoke-ListRoles {
[System.Collections.Generic.List[PSCustomObject]]$Roles = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/directoryRoles?`$expand=members" -tenantid $TenantFilter
$GraphRequest = foreach ($Role in $Roles) {
-
+
#[System.Collections.Generic.List[PSCustomObject]]$Members = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/$($Role.id)/members?`$select=$($selectlist -join ',')" -tenantid $TenantFilter | Select-Object $SelectList
$Members = if ($Role.members) { $role.members | ForEach-Object { " $($_.displayName) ($($_.userPrincipalName))" } } else { 'none' }
[PSCustomObject]@{
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1
index 74148522dec5..6f586800d8d0 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListRoomLists {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Room.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -20,9 +22,9 @@ Function Invoke-ListRoomLists {
try {
$params = @{
- uri = 'https://graph.microsoft.com/beta/places/microsoft.graph.roomlist'
+ uri = 'https://graph.microsoft.com/beta/places/microsoft.graph.roomlist'
tenantid = $TenantFilter
- AsApp = $true
+ AsApp = $true
}
$GraphRequest = New-GraphGetRequest @params
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1
index 4e2f57124129..34074ce76c3c 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListRooms {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Room.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1
index 1c497fb40f9e..d9242a3e29a3 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListServiceHealth {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Administration.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1
index 683f05eed5a1..4467289996ab 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSharedMailboxAccountEnabled {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -27,18 +29,18 @@ Function Invoke-ListSharedMailboxAccountEnabled {
if ($User.accountEnabled) {
$User | Select-Object `
@{Name = 'UserPrincipalName'; Expression = { $User.UserPrincipalName } }, `
- @{Name = 'displayName'; Expression = { $User.displayName } },
- @{Name = 'givenName'; Expression = { $User.givenName } },
- @{Name = 'surname'; Expression = { $User.surname } },
+ @{Name = 'displayName'; Expression = { $User.displayName } },
+ @{Name = 'givenName'; Expression = { $User.givenName } },
+ @{Name = 'surname'; Expression = { $User.surname } },
@{Name = 'accountEnabled'; Expression = { $User.accountEnabled } },
@{Name = 'id'; Expression = { $User.id } },
@{Name = 'onPremisesSyncEnabled'; Expression = { $User.onPremisesSyncEnabled } }
-
+
}
}
}
catch {
- Write-LogMessage -API 'Tenant' -tenant $tenantfilter -message "Shared Mailbox Enabled Accounts on $($tenantfilter). Error: $($_.exception.message)" -sev 'Error'
+ Write-LogMessage -API 'Tenant' -tenant $tenantfilter -message "Shared Mailbox Enabled Accounts on $($tenantfilter). Error: $($_.exception.message)" -sev 'Error'
}
$GraphRequest = $EnabledUsersWithSharedMailbox
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1
index 387d82b3f6dd..4b16ac630c80 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSharedMailboxStatistics {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1
index b1a7dc2236ab..b8d7d8a50995 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListSharepointQuota {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Sharepoint.Admin.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1
index debfb0931ac0..b58f472a7494 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1
@@ -3,12 +3,14 @@ using namespace System.Net
Function Invoke-ListSignIns {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.AuditLog.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
-
+
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
@@ -18,8 +20,8 @@ Function Invoke-ListSignIns {
if ($Request.query.failedlogonOnly) {
$FailedLogons = ' and (status/errorCode eq 50126)'
}
-
- $filters = if ($Request.query.Filter) {
+
+ $filters = if ($Request.query.Filter) {
$request.query.filter
} else {
$currentTime = Get-Date -Format 'yyyy-MM-dd'
@@ -30,12 +32,12 @@ Function Invoke-ListSignIns {
Write-Host $Filters
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/auditLogs/signIns?api-version=beta&`$filter=$($filters)" -tenantid $TenantFilter -erroraction stop
- $response = $GraphRequest | Select-Object *,
+ $response = $GraphRequest | Select-Object *,
@{l = 'additionalDetails'; e = { $_.status.additionalDetails } } ,
@{l = 'errorCode'; e = { $_.status.errorCode } },
- @{l = 'locationcipp'; e = { "$($_.location.city) - $($_.location.countryOrRegion)" } }
+ @{l = 'locationcipp'; e = { "$($_.location.city) - $($_.location.countryOrRegion)" } }
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Retrieved sign in report' -Sev 'Debug' -tenant $TenantFilter
-
+
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1
index ef3e205c8467..dd39cb4ac683 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListStandards {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1
index ed51de874171..d67651c0bc3f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListTenantAllowBlockList {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -16,7 +18,7 @@ Function Invoke-ListTenantAllowBlockList {
# Interact with query parameters or the body of the request.
$TenantFilter = $Request.Query.TenantFilter
- $ListTypes = 'Sender','Url','FileHash'
+ $ListTypes = 'Sender', 'Url', 'FileHash'
try {
$cmdletArray = $ListTypes | ForEach-Object {
@{
@@ -26,7 +28,7 @@ Function Invoke-ListTenantAllowBlockList {
}
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $TenantFilter -cmdletArray $cmdletArray
+ $BatchResults = New-ExoBulkRequest -tenantid $TenantFilter -cmdletArray @($cmdletArray)
$StatusCode = [HttpStatusCode]::OK
} catch {
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
index d855df71778b..41f16aba1e48 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-ListmailboxPermissions {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Mailbox.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -21,9 +23,9 @@ Function Invoke-ListmailboxPermissions {
Write-Host "Tenant Filter: $TenantFilter"
try {
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($Request.Query.UserID)
- $base64IdentityParam = [Convert]::ToBase64String($Bytes)
- $PermsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($Request.Query.UserID)')/MailboxPermission" -Tenantid $tenantfilter -scope ExchangeOnline
- $PermsRequest2 = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Recipient('$base64IdentityParam')?`$expand=RecipientPermission&isEncoded=true" -Tenantid $tenantfilter -scope ExchangeOnline
+ $base64IdentityParam = [Convert]::ToBase64String($Bytes)
+ $PermsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($Request.Query.UserID)')/MailboxPermission" -Tenantid $tenantfilter -scope ExchangeOnline
+ $PermsRequest2 = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Recipient('$base64IdentityParam')?`$expand=RecipientPermission&isEncoded=true" -Tenantid $tenantfilter -scope ExchangeOnline
$PermRequest3 = New-ExoRequest -Anchor $Request.Query.UserID -tenantid $Tenantfilter -cmdlet 'Get-Mailbox' -cmdParams @{Identity = $($Request.Query.UserID); }
$GraphRequest = foreach ($Perm in $PermsRequest, $PermsRequest2.RecipientPermission, $PermRequest3) {
@@ -34,20 +36,20 @@ Function Invoke-ListmailboxPermissions {
Permissions = $_.accessRights
}
}
-
+
}
if ($perm.PermissionList) {
$perm | Where-Object User | ForEach-Object { [PSCustomObject]@{
User = $_.User
Permissions = $_.PermissionList.accessRights -join ', '
- }
+ }
}
}
if ($perm.GrantSendonBehalfTo -ne $null) {
$perm.GrantSendonBehalfTo | ForEach-Object { [PSCustomObject]@{
User = $_
Permissions = 'SendOnBehalf'
- }
+ }
}
}
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-PublicPhishingCheck.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-PublicPhishingCheck.ps1
index 37136c230bdd..105bdf0df0d8 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-PublicPhishingCheck.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-PublicPhishingCheck.ps1
@@ -3,12 +3,12 @@ using namespace System.Net
Function Invoke-PublicPhishingCheck {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
Write-Host ($request | ConvertTo-Json)
-
+
# List valid referers
$validList = @(
'https://login.microsoftonline.com',
@@ -25,20 +25,20 @@ Function Invoke-PublicPhishingCheck {
Write-Host 'Not being Phished, no issue'
} else {
$bytes = [Convert]::FromBase64String('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')
-
+
$AlertMessage = If ($Request.headers.referer) {
- "Potential Phishing page detected. Detected Information: Hosted at $($Request.headers.referer). Access by IP $($request.headers.'x-forwarded-for')"
+ "Potential Phishing page detected. Detected Information: Hosted at $($Request.headers.referer). Access by IP $($request.headers.'x-forwarded-for')"
} else {
- "Potential Phishing page detected. Detected Information: Access by IP $($request.headers.'x-forwarded-for')"
+ "Potential Phishing page detected. Detected Information: Access by IP $($request.headers.'x-forwarded-for')"
}
- Write-AlertMessage -message $AlertMessage -sev 'Alert' -tenant $Request.query.TenantId
+ Write-AlertMessage -message $AlertMessage -sev 'Alert' -tenant $Request.query.TenantId
}
-
+
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
ContentType = 'image/png'
- Body = $bytes
+ Body = $bytes
})
}
diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1
index d9f99772b4d8..52807bdcc27f 100644
--- a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1
+++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveTenantAllowBlockList {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.SpamFilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Get-CIPPBackup.ps1 b/Modules/CIPPCore/Public/Get-CIPPBackup.ps1
new file mode 100644
index 000000000000..e463202983a1
--- /dev/null
+++ b/Modules/CIPPCore/Public/Get-CIPPBackup.ps1
@@ -0,0 +1,14 @@
+function Get-CIPPBackup {
+ [CmdletBinding()]
+ param (
+ [string]$Type,
+ [string]$TenantFilter
+ )
+ $Table = Get-CippTable -tablename "$($Type)Backup"
+ if ($TenantFilter) {
+ $Filter = "PartitionKey eq '$($Type)Backup' and TenantFilter eq '$($TenantFilter)'"
+ $Table.Filter = $Filter
+ }
+ $Info = Get-CIPPAzDataTableEntity @Table
+ return $info
+}
diff --git a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
index 319f9a81e726..28d526a9944d 100644
--- a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
+++ b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
@@ -6,18 +6,17 @@ function Get-CIPPMFAState {
$APIName = 'Get MFA Status',
$ExecutingUser
)
-
- $users = foreach ($user in (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$select=id,UserPrincipalName,DisplayName,accountEnabled,assignedLicenses' -tenantid $TenantFilter)) {
+ $PerUserMFAState = Get-CIPPPerUserMFA -TenantFilter $TenantFilter -AllUsers $true
+ $users = foreach ($user in (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$top=999&$select=id,UserPrincipalName,DisplayName,accountEnabled,assignedLicenses' -tenantid $TenantFilter)) {
[PSCustomObject]@{
- UserPrincipalName = $user.UserPrincipalName
- isLicensed = [boolean]$user.assignedLicenses.skuid
- accountEnabled = $user.accountEnabled
- DisplayName = $user.DisplayName
- ObjectId = $user.id
- StrongAuthenticationRequirements = @{StrongAuthenticationRequirement = @{state = 'See Documentation' } }
+ UserPrincipalName = $user.UserPrincipalName
+ isLicensed = [boolean]$user.assignedLicenses.skuid
+ accountEnabled = $user.accountEnabled
+ DisplayName = $user.DisplayName
+ ObjectId = $user.id
}
}
-
+
$SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $TenantFilter ).IsEnabled
$CAState = New-Object System.Collections.ArrayList
@@ -62,7 +61,6 @@ function Get-CIPPMFAState {
Write-Host 'Processing users'
$UserCAState = New-Object System.Collections.ArrayList
foreach ($CA in $CAState) {
- Write-Host 'Looping CAState'
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 }
@@ -75,7 +73,7 @@ function Get-CIPPMFAState {
}
}
- $PerUser = if ($_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state -ne $null) { $_.StrongAuthenticationRequirements.StrongAuthenticationRequirement.state } else { 'Disabled' }
+ $PerUser = if ($PerUserMFAState -eq $null) { $null } else { ($PerUserMFAState | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).PerUserMFAState }
$MFARegUser = if (($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).IsMFARegistered -eq $null) { $false } else { ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName) }
diff --git a/Modules/CIPPCore/Public/Get-CIPPPerUserMFA.ps1 b/Modules/CIPPCore/Public/Get-CIPPPerUserMFA.ps1
new file mode 100644
index 000000000000..5c525962009f
--- /dev/null
+++ b/Modules/CIPPCore/Public/Get-CIPPPerUserMFA.ps1
@@ -0,0 +1,34 @@
+function Get-CIPPPerUserMFA {
+ [CmdletBinding()]
+ param(
+ $TenantFilter,
+ $userId,
+ $executingUser,
+ $AllUsers = $false
+ )
+ try {
+ if ($AllUsers -eq $true) {
+ $AllUsers = New-graphGetRequest -Uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=UserPrincipalName,Id" -tenantid $tenantfilter
+ $Requests = foreach ($id in $AllUsers.userPrincipalName) {
+ @{
+ id = $int++
+ method = 'GET'
+ url = "users/$id/authentication/requirements"
+ }
+ }
+ $Requests = New-GraphBulkRequest -tenantid $tenantfilter -scope 'https://graph.microsoft.com/.default' -Requests @($Requests) -asapp $true
+ if ($Requests.body) {
+ $UsersWithoutMFA = $Requests.body | Select-Object peruserMFAState, @{Name = 'UserPrincipalName'; Expression = { [System.Web.HttpUtility]::UrlDecode($_.'@odata.context'.split("'")[1]) } }
+ return $UsersWithoutMFA
+ }
+ } else {
+ $MFAState = New-graphGetRequest -Uri "https://graph.microsoft.com/beta/users/$($userId)/authentication/requirements" -tenantid $tenantfilter
+ return [PSCustomObject]@{
+ PerUserMFAState = $MFAState.perUserMfaState
+ UserPrincipalName = $userId
+ }
+ }
+ } catch {
+ "Failed to get MFA State for $id : $_"
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1 b/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1
new file mode 100644
index 000000000000..b85edb06af86
--- /dev/null
+++ b/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1
@@ -0,0 +1,84 @@
+function Get-CIPPSchemaExtensions {
+ [CmdletBinding()]
+ Param()
+
+ $Schemas = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/schemaExtensions?`$filter=owner eq '$($env:applicationid)' and status eq 'Available'" -NoAuthCheck $true -AsApp $true
+
+ $SchemaDefinitions = [PSCustomObject]@(
+ @{
+ id = 'cippUser'
+ description = 'CIPP User Schema'
+ targetTypes = @('User')
+ properties = @(
+ @{
+ name = 'jitAdminEnabled'
+ type = 'Boolean'
+ }
+ @{
+ name = 'jitAdminExpiration'
+ type = 'DateTime'
+ }
+ @{
+ name = 'mailboxType'
+ type = 'String'
+ }
+ @{
+ name = 'archiveEnabled'
+ type = 'Boolean'
+ }
+ @{
+ name = 'autoExpandingArchiveEnabled'
+ type = 'Boolean'
+ }
+ @{
+ name = 'perUserMfaState'
+ type = 'String'
+ }
+ )
+ }
+ )
+ foreach ($SchemaDefinition in $SchemaDefinitions) {
+ $SchemaFound = $false
+ foreach ($Schema in $Schemas) {
+ if ($Schema.id -match $SchemaDefinition.id) {
+ $SchemaFound = $true
+ $Schema = $Schemas | Where-Object { $_.id -match $SchemaDefinition.id }
+ $Patch = @{}
+ if (Compare-Object -ReferenceObject ($SchemaDefinition.properties | Select-Object name, type) -DifferenceObject ($Schema.properties | Select-Object name, type)) {
+ $Patch.properties = $SchemaDefinitions.Properties
+ }
+ if ($Schema.status -ne 'Available') {
+ $Patch.status = 'Available'
+ }
+ if ($Schema.targetTypes -ne $SchemaDefinition.targetTypes) {
+ $Patch.targetTypes = $SchemaDefinition.targetTypes
+ }
+ if ($Patch -and $Patch.Keys.Count -gt 0) {
+ Write-Information "Updating $($Schema.id)"
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Patch
+ Write-Information $Json
+ New-GraphPOSTRequest -type PATCH -Uri "https://graph.microsoft.com/v1.0/schemaExtensions/$($Schema.id)" -Body $Json -AsApp $true -NoAuthCheck $true
+ } else {
+ $Schema
+ }
+ }
+ }
+ if (!$SchemaFound) {
+ Write-Information "Creating Schema Extension for $($SchemaDefinition.id)"
+ $Body = [PSCustomObject]@{
+ id = 'cippUser'
+ description = 'CIPP User'
+ targetTypes = $SchemaDefinition.TargetTypes
+ properties = $SchemaDefinition.Properties
+ }
+
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Body
+ $Schema = New-GraphPOSTRequest -type POST -Uri 'https://graph.microsoft.com/v1.0/schemaExtensions' -Body $Json -AsApp $true -NoAuthCheck $true
+ $Patch = [PSCustomObject]@{
+ status = 'Available'
+ }
+ $PatchJson = ConvertTo-Json -Depth 5 -InputObject $Patch
+ New-GraphPOSTRequest -type PATCH -Uri "https://graph.microsoft.com/v1.0/schemaExtensions/$($Schema.id)" -Body $PatchJson -AsApp $true -NoAuthCheck $true
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1 b/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1
new file mode 100644
index 000000000000..b59ce99a3160
--- /dev/null
+++ b/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1
@@ -0,0 +1,264 @@
+function Get-SlackAlertBlocks {
+ [CmdletBinding()]
+ Param(
+ $JSONBody
+ )
+
+ $Blocks = [system.collections.generic.list[object]]::new()
+
+ $Payload = $JSONBody | ConvertFrom-Json
+
+ if ($Payload.API -eq 'Alerts') {
+ foreach ($Entry in $Payload) {
+ # Alert log alerts
+ $Blocks.Add([PSCustomObject]@{
+ type = 'header'
+ text = @{
+ type = 'plain_text'
+ text = 'New Alert from CIPP'
+ emoji = $true
+ }
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ fields = @(
+ @{
+ type = 'mrkdwn'
+ text = "*Tenant:*`n" + $Entry.Tenant
+ },
+ @{
+ type = 'mrkdwn'
+ text = "*Username:*`n" + $Entry.Username
+ },
+ @{
+ type = 'mrkdwn'
+ text = "*Timestamp:*`n" + ($Entry.Timestamp | Get-Date).ToString('yyyy-MM-dd @ hh:mm:ss tt')
+ }
+ )
+ })
+
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = "*Message:*`n" + $Entry.Message
+ }
+ })
+ }
+ } elseif ($Payload.TaskInfo -is [object]) {
+ #Scheduler
+ $Blocks.Add([PSCustomObject]@{
+ type = 'header'
+ text = @{
+ type = 'plain_text'
+ text = 'New Alert from CIPP'
+ emoji = $true
+ }
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = "*Task Name:*`n" + $Payload.TaskInfo.Name
+ }
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ fields = @(
+ @{
+ type = 'mrkdwn'
+ text = "*Timestamp:*`n" + ($Payload.TaskInfo.Timestamp | Get-Date).ToString('yyyy-MM-dd @ hh:mm:ss tt')
+ },
+ @{
+ type = 'mrkdwn'
+ text = "*Tenant:*`n" + $Payload.Tenant
+ }
+ )
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'divider'
+ })
+ foreach ($Result in $Payload.Results) {
+ # Check if results is [string] and create text section
+ if ($Result -is [string]) {
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = $Result
+ }
+ })
+ } else {
+ #Iterate through property names and create fields
+ $Fields = [system.collections.generic.list[object]]::new()
+ foreach ($Key in $Result.PSObject.Properties.Name) {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $Result.$Key
+ })
+ }
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ fields = @($Fields)
+
+ })
+ }
+ }
+ } elseif ($Payload.RawData -is [object]) {
+ # Webhook alert
+ $Blocks.Add([PSCustomObject]@{
+ type = 'header'
+ text = @{
+ type = 'plain_text'
+ text = 'New Alert from CIPP'
+ emoji = $true
+ }
+ })
+
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = "*Title:*`n" + $Payload.Title
+ }
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'actions'
+ elements = @(
+ @{
+ type = 'button'
+ text = @{
+ type = 'plain_text'
+ text = $Payload.ActionText ?? 'Go to CIPP'
+ }
+ url = $Payload.ActionUrl
+ style = 'primary'
+ }
+ )
+ })
+ $Blocks.Add([PSCustomObject]@{
+ type = 'divider'
+ })
+
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = '*Webhook Data:*'
+ }
+ })
+ #loop through rawdata properties and create key value fields
+ $Fields = [system.collections.generic.list[object]]::new()
+ foreach ($Key in $Payload.RawData.PSObject.Properties.Name) {
+ # if value is json continue to next property
+ if ($Payload.RawData.$Key -is [string] -and ![string]::IsNullOrEmpty($Payload.RawData.$Key)) {
+ continue
+ }
+ # if value is date object
+ if ($Payload.RawData.$Key -is [datetime]) {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $Payload.RawData.$Key.ToString('yyyy-MM-dd @ hh:mm:ss tt')
+ })
+ } elseif ($Payload.RawData.$Key -is [array] -and $Payload.RawData.$Key.Count -gt 0) {
+ foreach ($SubKey in $Payload.RawData.$Key) {
+ if ([string]::IsNullOrEmpty($SubKey)) {
+ continue
+ } elseif ($SubKey -is [datetime]) {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $SubKey.ToString('yyyy-MM-dd @ hh:mm:ss tt')
+ })
+ } else {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $SubKey
+ })
+ }
+ }
+ } elseif ($Payload.RawData.$Key.PSObject.Properties.Name -is [array] -and $Payload.RawData.$Key.PSObject.Properties.Name.Count -gt 0) {
+ foreach ($SubKey in $Payload.RawData.$Key.PSObject.Properties.Name) {
+ if ([string]::IsNullOrEmpty($Payload.RawData.$Key.$SubKey)) {
+ continue
+ } elseif ($Payload.RawData.$Key.$SubKey -is [datetime]) {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key)/$($SubKey):*`n" + $Payload.RawData.$Key.$SubKey.ToString('yyyy-MM-dd @ hh:mm:ss tt')
+ })
+ } elseif (Test-Json $Payload.RawData.$Key.$SubKey -ErrorAction SilentlyContinue) {
+ # parse json and iterate through properties
+ $SubKeyData = $Payload.RawData.$Key.$SubKey | ConvertFrom-Json
+ foreach ($SubSubKey in $SubKeyData.PSObject.Properties.Name) {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key)/$($SubKey)/$($SubSubKey):*`n" + $SubKeyData.$SubSubKey
+ })
+ }
+ } else {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key)/$($SubKey):*`n" + $Payload.RawData.$Key.$SubKey
+ })
+ }
+ }
+ } else {
+ $Fields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $Payload.RawData.$Key
+ })
+ }
+ }
+
+ $FieldBatch = [system.collections.generic.list[object]]::new()
+ for ($i = 0; $i -lt $Fields.Count; $i += 10) {
+ $FieldBatch.Add($Fields[$i..[math]::Min($i + 9, $Fields.Count - 1)])
+ }
+ foreach ($Batch in $FieldBatch) {
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ fields = @($Batch)
+ })
+ }
+
+ # if potentiallocationinfo is present
+ if ($Payload.PotentialLocationInfo) {
+ # add divider
+ $Blocks.Add([PSCustomObject]@{
+ type = 'divider'
+ })
+ # add text section for location
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ text = @{
+ type = 'mrkdwn'
+ text = '*Potential Location Info:*'
+ }
+ })
+ # loop through location properties and add fields
+ $LocationFields = [system.collections.generic.list[object]]::new()
+ foreach ($Key in $Payload.PotentialLocationInfo.PSObject.Properties.Name) {
+ $LocationFields.Add(@{
+ type = 'mrkdwn'
+ text = "*$($Key):*`n" + $Payload.PotentialLocationInfo.$Key
+ })
+ }
+ # add fields to section in groups of 10
+ $LocationFieldBatch = [system.collections.generic.list[object]]::new()
+ for ($i = 0; $i -lt $LocationFields.Count; $i += 10) {
+ $LocationFieldBatch.Add($LocationFields[$i..[math]::Min($i + 9, $LocationFields.Count - 1)])
+ }
+ foreach ($Batch in $LocationFieldBatch) {
+ $Blocks.Add([PSCustomObject]@{
+ type = 'section'
+ fields = @($Batch)
+ })
+ }
+ }
+ }
+
+ if (($Blocks | Measure-Object).Count -gt 0) {
+ [PSCustomObject]@{
+ blocks = $Blocks
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
index c38b5c1c59b3..fdcb3d3eb95b 100644
--- a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1
@@ -103,7 +103,7 @@ function Get-Tenants {
}
}
- [PSCustomObject]@{
+ $Obj = [PSCustomObject]@{
PartitionKey = 'Tenants'
RowKey = $_.Name
customerId = $_.Name
@@ -123,6 +123,11 @@ function Get-Tenants {
RequiresRefresh = [bool]$RequiresRefresh
LastRefresh = (Get-Date).ToUniversalTime()
}
+ if ($Obj.defaultDomainName -eq 'Invalid' -or !$Obj.defaultDomainName) {
+ continue
+ }
+ Add-CIPPAzDataTableEntity @TenantsTable -Entity $Obj -Force | Out-Null
+ $Obj
}
}
$IncludedTenantsCache = [system.collections.generic.list[object]]::new()
@@ -133,7 +138,7 @@ function Get-Tenants {
RowKey = $env:TenantID
PartitionKey = 'Tenants'
customerId = $env:TenantID
- defaultDomainName = ($Domains | Where-Object { $_.isInitial -eq $true }).id
+ defaultDomainName = ($Domains | Where-Object { $_.isDefault -eq $true }).id
initialDomainName = ($Domains | Where-Object { $_.isInitial -eq $true }).id
displayName = '*Partner Tenant'
domains = 'PartnerTenant'
@@ -145,6 +150,7 @@ function Get-Tenants {
RequiresRefresh = [bool]$RequiresRefresh
LastRefresh = (Get-Date).ToUniversalTime()
}) | Out-Null
+
}
foreach ($Tenant in $TenantList) {
if ($Tenant.defaultDomainName -eq 'Invalid' -or !$Tenant.defaultDomainName) {
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
index 4a05cf778fe7..8ef890eaf10d 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1
@@ -22,15 +22,25 @@ function New-ExoRequest ($tenantid, $cmdlet, $cmdParams, $useSystemMailbox, $Anc
if ($cmdparams.Identity) { $Anchor = $cmdparams.Identity }
if ($cmdparams.anr) { $Anchor = $cmdparams.anr }
if ($cmdparams.User) { $Anchor = $cmdparams.User }
+ if ($cmdparams.mailbox) { $Anchor = $cmdparams.mailbox }
if (!$Anchor -or $useSystemMailbox) {
- if (!$Tenant.initialDomainName) {
+ if (!$Tenant.initialDomainName -or $Tenant.initialDomainName -notlike '*onmicrosoft.com*') {
$OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $tenantid -NoAuthCheck $NoAuthCheck | Where-Object -Property isInitial -EQ $true).id
} else {
$OnMicrosoft = $Tenant.initialDomainName
}
$anchor = "UPN:SystemMailbox{8cc370d3-822a-4ab8-a926-bb94bd0641a9}@$($OnMicrosoft)"
}
+ #if the anchor is a GUID, try looking up the user.
+ if ($Anchor -match '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
+ $Anchor = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$Anchor" -tenantid $tenantid -NoAuthCheck $NoAuthCheck
+ if ($Anchor) {
+ $Anchor = $Anchor.UserPrincipalName
+ } else {
+ Write-Error "Failed to find user with GUID $Anchor"
+ }
+ }
}
Write-Host "Using $Anchor"
$Headers = @{
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
index ebe6af9675b9..f37be378e39d 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1
@@ -33,7 +33,8 @@ function New-GraphBulkRequest {
$req = @{}
# Use select to create hashtables of id, method and url for each call
$req['requests'] = ($Requests[$i..($i + 19)])
- Invoke-RestMethod -Uri $URL -Method POST -Headers $headers -ContentType 'application/json; charset=utf-8' -Body ($req | ConvertTo-Json -Depth 10)
+ $ReqBody = ($req | ConvertTo-Json -Depth 10)
+ Invoke-RestMethod -Uri $URL -Method POST -Headers $headers -ContentType 'application/json; charset=utf-8' -Body $ReqBody
}
foreach ($MoreData in $ReturnedData.Responses | Where-Object { $_.body.'@odata.nextLink' }) {
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1
index bc0ef417a3c3..65a5edca23f2 100644
--- a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1
@@ -52,7 +52,9 @@ function New-GraphGetRequest {
if ($noPagination) { $nextURL = $null } else { $nextURL = $data.'@odata.nextLink' }
}
} catch {
- $Message = ($_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue).error.message
+ try {
+ $Message = ($_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue).error.message
+ } catch { $Message = $null }
if ($Message -eq $null) { $Message = $($_.Exception.Message) }
if ($Message -ne 'Request not applicable to target tenant.' -and $Tenant) {
$Tenant.LastGraphError = $Message
@@ -61,7 +63,7 @@ function New-GraphGetRequest {
}
throw $Message
}
- } until ($null -eq $NextURL)
+ } until ($null -eq $NextURL -or ' ' -eq $NextURL)
$Tenant.LastGraphError = ''
Update-AzDataTableEntity @TenantsTable -Entity $Tenant
return $ReturnedData
diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1
index dfbb5445c5e8..753a47922b66 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, $IgnoreErrors = $false) {
+function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $NoAuthCheck, $skipTokenCache, $AddedHeaders, $contentType, $IgnoreErrors = $false, $returnHeaders = $false) {
<#
.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 -SkipHttpErrorCheck:$IgnoreErrors)
+ $ReturnedData = (Invoke-RestMethod -Uri $($uri) -Method $TYPE -Body $body -Headers $headers -ContentType $contentType -SkipHttpErrorCheck:$IgnoreErrors -ResponseHeadersVariable responseHeaders)
} catch {
$Message = if ($_.ErrorDetails.Message) {
Get-NormalizedError -Message $_.ErrorDetails.Message
@@ -29,7 +29,11 @@ function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $N
}
throw $Message
}
- return $ReturnedData
+ if ($returnHeaders) {
+ return $responseHeaders
+ } else {
+ return $ReturnedData
+ }
} else {
Write-Error 'Not allowed. You cannot manage your own tenant or tenants not under your scope'
}
diff --git a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1
index 1bbab4a3f025..99057374f0de 100644
--- a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1
+++ b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1
@@ -9,9 +9,12 @@ function Remove-CIPPCache {
# Remove all tenants except excluded
$TenantsTable = Get-CippTable -tablename 'Tenants'
$Filter = "PartitionKey eq 'Tenants' and Excluded eq false"
- $ClearIncludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter
- Remove-AzDataTableEntity @TenantsTable -Entity $ClearIncludedTenants
- if ($tenantsonly -eq 'false') {
+ $ClearIncludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter $Filter -Property PartitionKey, RowKey
+ if ($ClearIncludedTenants) {
+ Remove-AzDataTableEntity @TenantsTable -Entity $ClearIncludedTenants
+ }
+
+ if ($TenantsOnly -eq 'false') {
Write-Host 'Clearing all'
# Remove Domain Analyser cached results
$DomainsTable = Get-CippTable -tablename 'Domains'
@@ -20,11 +23,15 @@ function Remove-CIPPCache {
$_.DomainAnalyser = ''
$_
}
- Update-AzDataTableEntity @DomainsTable -Entity $ClearDomainAnalyserRows
+ if ($ClearDomainAnalyserRows) {
+ Update-AzDataTableEntity @DomainsTable -Entity $ClearDomainAnalyserRows
+ }
#Clear BPA
- $BPATable = Get-CippTable -tablename 'cachebpa'
+ $BPATable = Get-CippTable -tablename 'cachebpav2'
$ClearBPARows = Get-CIPPAzDataTableEntity @BPATable
- Remove-AzDataTableEntity @BPATable -Entity $ClearBPARows
+ if ($ClearBPARows) {
+ Remove-AzDataTableEntity @BPATable -Entity $ClearBPARows
+ }
$ENV:SetFromProfile = $null
$Script:SkipListCache = $Null
$Script:SkipListCacheEmpty = $Null
diff --git a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1
index 80fd965ad859..20620029e0e9 100644
--- a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1
+++ b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1
@@ -66,6 +66,8 @@ function Get-GraphRequestList {
[string]$ReverseTenantLookupProperty = 'tenantId'
)
+ $SingleTenantThreshold = 8000
+
$TableName = ('cache{0}' -f ($Endpoint -replace '[^A-Za-z0-9]'))[0..62] -join ''
Write-Information "Table: $TableName"
$Endpoint = $Endpoint -replace '^/', ''
@@ -86,39 +88,64 @@ function Get-GraphRequestList {
$GraphQuery.Query = $ParamCollection.ToString()
$PartitionKey = Get-StringHash -String (@($Endpoint, $ParamCollection.ToString()) -join '-')
Write-Information "PK: $PartitionKey"
-
Write-Information ( 'GET [ {0} ]' -f $GraphQuery.ToString())
+ # Perform $count check before caching
+ $Count = 0
+ if ($TenantFilter -ne 'AllTenants') {
+ $GraphRequest = @{
+ uri = $GraphQuery.ToString()
+ tenantid = $TenantFilter
+ ComplexFilter = $true
+ }
+
+ if ($NoPagination.IsPresent) {
+ $GraphRequest.noPagination = $NoPagination.IsPresent
+ }
+ if ($CountOnly.IsPresent) {
+ $GraphRequest.CountOnly = $CountOnly.IsPresent
+ }
+ if ($NoAuthCheck.IsPresent) {
+ $GraphRequest.noauthcheck = $NoAuthCheck.IsPresent
+ }
+ if ($Parameters.'$count' -and !$SkipCache.IsPresent -and !$NoPagination.IsPresent) {
+ $Count = New-GraphGetRequest @GraphRequest -CountOnly -ErrorAction Stop
+ if ($CountOnly.IsPresent) { return $Count }
+ Write-Information "Total results (`$count): $Count"
+ }
+ }
+
try {
if ($QueueId) {
$Table = Get-CIPPTable -TableName $TableName
$Filter = "QueueId eq '{0}'" -f $QueueId
$Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter
$Type = 'Queue'
- } elseif ($TenantFilter -eq 'AllTenants' -or (!$SkipCache.IsPresent -and !$ClearCache.IsPresent -and !$CountOnly.IsPresent)) {
- $Table = Get-CIPPTable -TableName $TableName
- $Timestamp = (Get-Date).AddHours(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK')
- if ($TenantFilter -eq 'AllTenants') {
- $Filter = "PartitionKey eq '{0}' and QueueType eq 'AllTenants' and Timestamp ge datetime'{1}'" -f $PartitionKey, $Timestamp
- } else {
- $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}' and Timestamp ge datetime'{2}'" -f $PartitionKey, $TenantFilter, $Timestamp
+ Write-Information "Cached: $(($Rows | Measure-Object).Count) rows (Type: $($Type))"
+ $QueueReference = '{0}-{1}' -f $TenantFilter, $PartitionKey
+ $RunningQueue = Invoke-ListCippQueue | Where-Object { $_.Reference -eq $QueueReference -and $_.Status -ne 'Completed' -and $_.Status -ne 'Failed' }
+ } elseif (!$SkipCache.IsPresent -and !$ClearCache.IsPresent -and !$CountOnly.IsPresent) {
+ if ($TenantFilter -eq 'AllTenants' -or $Count -gt $SingleTenantThreshold) {
+ $Table = Get-CIPPTable -TableName $TableName
+ $Timestamp = (Get-Date).AddHours(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK')
+ if ($TenantFilter -eq 'AllTenants') {
+ $Filter = "PartitionKey eq '{0}' and QueueType eq 'AllTenants' and Timestamp ge datetime'{1}'" -f $PartitionKey, $Timestamp
+ } else {
+ $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}' and Timestamp ge datetime'{2}'" -f $PartitionKey, $TenantFilter, $Timestamp
+ }
+ $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter
+ $Type = 'Cache'
+ Write-Information "Cached: $(($Rows | Measure-Object).Count) rows (Type: $($Type))"
+ $QueueReference = '{0}-{1}' -f $TenantFilter, $PartitionKey
+ $RunningQueue = Invoke-ListCippQueue | Where-Object { $_.Reference -eq $QueueReference -and $_.Status -ne 'Completed' -and $_.Status -ne 'Failed' }
}
- #Write-Information $Filter
- $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter
- $Type = 'Cache'
- } else {
- $Type = 'None'
- $Rows = @()
}
- Write-Information "Cached: $(($Rows | Measure-Object).Count) rows (Type: $($Type))"
-
- $QueueReference = '{0}-{1}' -f $TenantFilter, $PartitionKey
- $RunningQueue = Invoke-ListCippQueue | Where-Object { $_.Reference -eq $QueueReference -and $_.Status -ne 'Completed' -and $_.Status -ne 'Failed' }
} catch {
Write-Information $_.InvocationInfo.PositionMessage
}
if ($TenantFilter -ne 'AllTenants' -and $Endpoint -match '%tenantid%') {
+ Write-Information "Replacing TenantId in endpoint with $TenantFilter"
$TenantId = (Get-Tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $TenantFilter -or $_.customerId -eq $TenantFilter }).customerId
$Endpoint = $Endpoint -replace '%tenantid%', $TenantId
$GraphQuery = [System.UriBuilder]('https://graph.microsoft.com/{0}/{1}' -f $Version, $Endpoint)
@@ -127,6 +154,7 @@ function Get-GraphRequestList {
$ParamCollection.Add($Item.Key, $Item.Value)
}
$GraphQuery.Query = $ParamCollection.ToString()
+ $GraphRequest.uri = $GraphQuery.ToString()
}
if (!$Rows) {
@@ -208,31 +236,10 @@ function Get-GraphRequestList {
}
}
default {
- $GraphRequest = @{
- uri = $GraphQuery.ToString()
- tenantid = $TenantFilter
- ComplexFilter = $true
- }
-
- if ($NoPagination.IsPresent) {
- $GraphRequest.noPagination = $NoPagination.IsPresent
- }
-
- if ($CountOnly.IsPresent) {
- $GraphRequest.CountOnly = $CountOnly.IsPresent
- }
-
- if ($NoAuthCheck.IsPresent) {
- $GraphRequest.noauthcheck = $NoAuthCheck.IsPresent
- }
-
try {
$QueueThresholdExceeded = $false
if ($Parameters.'$count' -and !$SkipCache -and !$NoPagination) {
- $Count = New-GraphGetRequest @GraphRequest -CountOnly -ErrorAction Stop
- if ($CountOnly.IsPresent) { return $Count }
- Write-Information "Total results (`$count): $Count"
- if ($Count -gt 8000) {
+ if ($Count -gt $singleTenantThreshold) {
$QueueThresholdExceeded = $true
if ($RunningQueue) {
Write-Information 'Queue currently running'
diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1
index 0d45ac6311df..533d0954679a 100644
--- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1
+++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1
@@ -13,6 +13,7 @@ function Invoke-CIPPOffboardingJob {
$Options = $Options | ConvertFrom-Json
}
$userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)" -tenantid $Tenantfilter).id
+ Write-Host "Running offboarding job for $username with options: $($Options | ConvertTo-Json -Depth 10)"
$Return = switch ($Options) {
{ $_.'ConvertToShared' -eq 'true' } {
Set-CIPPMailboxType -ExecutingUser $ExecutingUser -tenantFilter $tenantFilter -userid $username -username $username -MailboxType 'Shared' -APIName $APIName
@@ -59,14 +60,15 @@ function Invoke-CIPPOffboardingJob {
Remove-CIPPUser -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName
}
- { $_.'RemoveRules' -eq 'true' } {
+ { $_.'removeRules' -eq 'true' } {
+ Write-Host "Removing rules for $username"
Remove-CIPPRules -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName
}
- { $_.'RemoveMobile' -eq 'true' } {
+ { $_.'removeMobile' -eq 'true' } {
Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName
}
- { $_.'RemovePermissions' } {
+ { $_.'removePermissions' } {
if ($RunScheduled) {
Remove-CIPPMailboxPermissions -PermissionsLevel @('FullAccess', 'SendAs', 'SendOnBehalf') -userid 'AllUsers' -AccessUser $UserName -TenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser
diff --git a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
index 402e91d285ff..a1787ddbae34 100644
--- a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
+++ b/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1
@@ -5,7 +5,7 @@ function Invoke-CippWebhookProcessing {
$Data,
$Resource,
$Operations,
- $CIPPPURL,
+ $CIPPURL,
$APIName = 'Process webhook',
$ExecutingUser
)
@@ -62,22 +62,23 @@ function Invoke-CippWebhookProcessing {
switch ($action) {
'generatemail' {
Write-Host 'Going to create the email'
- $GenerateEmail = New-CIPPAlertTemplate -format 'html' -data $Data -ActionResults $ActionResults
+ $GenerateEmail = New-CIPPAlertTemplate -format 'html' -data $Data -ActionResults $ActionResults -CIPPURL $CIPPURL
Write-Host 'Going to send the mail'
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 -ActionResults $ActionResults
+ $GenerateEmail = New-CIPPAlertTemplate -format 'html' -data $Data -ActionResults $ActionResults -CIPPURL $CIPPURL
Send-CIPPAlert -Type 'psa' -Title $GenerateEmail.title -HTMLContent $GenerateEmail.htmlcontent -TenantFilter $TenantFilter
}
'generateWebhook' {
Write-Host 'Generating the webhook content'
$LocationInfo = $Data.CIPPLocationInfo | ConvertFrom-Json -ErrorAction SilentlyContinue
- $GenerateJSON = New-CIPPAlertTemplate -format 'json' -data $Data -ActionResults $ActionResults
+ $GenerateJSON = New-CIPPAlertTemplate -format 'json' -data $Data -ActionResults $ActionResults -CIPPURL $CIPPURL
$JsonContent = @{
Title = $GenerateJSON.Title
ActionUrl = $GenerateJSON.ButtonUrl
+ ActionText = $GenerateJSON.ButtonText
RawData = $Data
IP = $data.ClientIP
PotentialLocationInfo = $LocationInfo
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1
index 8639d495321d..1c474b20a44f 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveAPDevice {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Autopilot.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1
index f0ca41db08a0..b154d77568eb 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1
index 8cef68c26155..da878e3dbba2 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveCAPolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1
index 318184576061..7ff2f2bf5df8 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveCATemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.ConditionalAccess.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1
index c4a47e9b182a..fc34c0073005 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveContact {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Contact.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1
index f16befc4906b..79b201c068b4 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveExConnector {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -11,9 +13,9 @@ Function Invoke-RemoveExConnector {
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$Tenantfilter = $request.Query.tenantfilter
-
+
try {
-
+
$Params = @{ Identity = $request.query.GUID }
$GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "Remove-$($Request.query.Type)Connector" -cmdParams $params -useSystemMailbox $true
$Result = "Deleted $($Request.query.guid)"
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1
index 3e78057683d9..b12df6a3d0aa 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveExConnectorTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Connector.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1
index 2efd9d639307..85e4346a2b81 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveGroupTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.Group.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1
index 4575cf0fe57a..f1b2c51ca2bf 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveIntuneTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 b/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1
index 58cc90823d16..c7805fb46a48 100644
--- a/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemovePolicy {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.MEM.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1
index add290577208..1e1d3fd4de14 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveQueuedApp {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Endpoint.Application.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1
index e962aab4a7a4..55f525aa36f2 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveSpamfilter {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Spamfilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -12,20 +14,20 @@ Function Invoke-RemoveSpamfilter {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'
$Tenantfilter = $request.Query.tenantfilter
-
$Params = @{
Identity = $request.query.name
}
try {
$cmdlet = 'Remove-HostedContentFilterRule'
- $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params
+ $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true
$cmdlet = 'Remove-HostedContentFilterPolicy'
- $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params
+ $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true
$Result = "Deleted $($Request.query.name)"
Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Deleted transport rule $($Request.query.name)" -sev Debug
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception
+ Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Failed deleting transport rule $($Request.query.name). Error:$ErrorMessage" -Sev Error
$Result = $ErrorMessage
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1
index 8008d3b11a18..eaa19ff08df6 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveSpamfilterTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.Spamfilter.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1
index d3898d337a73..88d7f21e3212 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveStandard {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1
index e95f74ecd11e..b7c11bd2d584 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveStandardTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Tenant.Standards.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1
index b340f331903f..3a86c418314d 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveTransportRule {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1
index 952796e819d8..3510d02b34a2 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveTransportRuleTemplate {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Exchange.TransportRule.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1
index 386ab3e4be6b..040278ba9d80 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveUser {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ Identity.User.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
diff --git a/Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1
index 0e9a92ac7868..e2a0b4d3bce2 100644
--- a/Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1
+++ b/Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1
@@ -3,7 +3,9 @@ using namespace System.Net
Function Invoke-RemoveWebhookAlert {
<#
.FUNCTIONALITY
- Entrypoint
+ Entrypoint
+ .ROLE
+ CIPP.Alert.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
@@ -13,7 +15,7 @@ Function Invoke-RemoveWebhookAlert {
$Table = get-cipptable -TableName 'SchedulerConfig'
try {
- $WebhookTable = Get-CIPPTable -TableName SchedulerConfig
+ $WebhookTable = Get-CIPPTable -TableName SchedulerConfig
$WebhookRow = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq 'WebhookAlert'" | Where-Object -Property Tenant -EQ $Request.query.TenantFilter
Write-Host "The webhook count is $($WebhookRow.count)"
if ($WebhookRow.count -gt 1) {
@@ -37,7 +39,7 @@ Function Invoke-RemoveWebhookAlert {
} else {
$Tenants = $Request.query.TenantFilter
}
-
+
$Results = foreach ($Tenant in $Tenants) {
Remove-CIPPGraphSubscription -TenantFilter $Tenant -Type 'AuditLog'
$Entity = $WebhookRow | Where-Object -Property RowKey -EQ $Request.query.ID
diff --git a/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1 b/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1
index c502a2ea1bf7..ff9853aca307 100644
--- a/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1
@@ -5,7 +5,8 @@ function New-CIPPAlertTemplate {
[Parameter(Mandatory = $true)]
$Format,
$LocationInfo,
- $ActionResults
+ $ActionResults,
+ $CIPPURL
)
$Appname = '[{"Application Name":"ACOM Azure Website","Application IDs":"23523755-3a2b-41ca-9315-f81f3f566a95"},{"Application Name":"AEM-DualAuth","Application IDs":"69893ee3-dd10-4b1c-832d-4870354be3d8"},{"Application Name":"ASM Campaign Servicing","Application IDs":"0cb7b9ec-5336-483b-bc31-b15b5788de71"},{"Application Name":"Azure Advanced Threat Protection","Application IDs":"7b7531ad-5926-4f2d-8a1d-38495ad33e17"},{"Application Name":"Azure Data Lake","Application IDs":"e9f49c6b-5ce5-44c8-925d-015017e9f7ad"},{"Application Name":"Azure Lab Services Portal","Application IDs":"835b2a73-6e10-4aa5-a979-21dfda45231c"},{"Application Name":"Azure Portal","Application IDs":"c44b4083-3bb0-49c1-b47d-974e53cbdf3c"},{"Application Name":"AzureSupportCenter","Application IDs":"37182072-3c9c-4f6a-a4b3-b3f91cacffce"},{"Application Name":"Bing","Application IDs":"9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7"},{"Application Name":"CPIM Service","Application IDs":"bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4"},{"Application Name":"CRM Power BI Integration","Application IDs":"e64aa8bc-8eb4-40e2-898b-cf261a25954f"},{"Application Name":"Dataverse","Application IDs":"00000007-0000-0000-c000-000000000000"},{"Application Name":"Enterprise Roaming and Backup","Application IDs":"60c8bde5-3167-4f92-8fdb-059f6176dc0f"},{"Application Name":"IAM Supportability","Application IDs":"a57aca87-cbc0-4f3c-8b9e-dc095fdc8978"},{"Application Name":"IrisSelectionFrontDoor","Application IDs":"16aeb910-ce68-41d1-9ac3-9e1673ac9575"},{"Application Name":"MCAPI Authorization Prod","Application IDs":"d73f4b35-55c9-48c7-8b10-651f6f2acb2e"},{"Application Name":"Media Analysis and Transformation Service","Application IDs":"944f0bd1-117b-4b1c-af26-804ed95e767e
0cd196ee-71bf-4fd6-a57c-b491ffd4fb1e"},{"Application Name":"Microsoft 365 Support Service","Application IDs":"ee272b19-4411-433f-8f28-5c13cb6fd407"},{"Application Name":"Microsoft App Access Panel","Application IDs":"0000000c-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Approval Management","Application IDs":"65d91a3d-ab74-42e6-8a2f-0add61688c74
38049638-cc2c-4cde-abe4-4479d721ed44"},{"Application Name":"Microsoft Authentication Broker","Application IDs":"29d9ed98-a469-4536-ade2-f981bc1d605e"},{"Application Name":"Microsoft Azure CLI","Application IDs":"04b07795-8ddb-461a-bbee-02f9e1bf7b46"},{"Application Name":"Microsoft Azure PowerShell","Application IDs":"1950a258-227b-4e31-a9cf-717495945fc2"},{"Application Name":"Microsoft Bing Search","Application IDs":"cf36b471-5b44-428c-9ce7-313bf84528de"},{"Application Name":"Microsoft Bing Search for Microsoft Edge","Application IDs":"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8"},{"Application Name":"Microsoft Bing Default Search Engine","Application IDs":"1786c5ed-9644-47b2-8aa0-7201292175b6"},{"Application Name":"Microsoft Defender for Cloud Apps","Application IDs":"3090ab82-f1c1-4cdf-af2c-5d7a6f3e2cc7"},{"Application Name":"Microsoft Docs","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Dynamics ERP","Application IDs":"00000015-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Edge Insider Addons Prod","Application IDs":"6253bca8-faf2-4587-8f2f-b056d80998a7"},{"Application Name":"Microsoft Exchange Online Protection","Application IDs":"00000007-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Forms","Application IDs":"c9a559d2-7aab-4f13-a6ed-e7e9c52aec87"},{"Application Name":"Microsoft Graph","Application IDs":"00000003-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Intune Web Company Portal","Application IDs":"74bcdadc-2fdc-4bb3-8459-76d06952a0e9"},{"Application Name":"Microsoft Intune Windows Agent","Application IDs":"fc0f3af4-6835-4174-b806-f7db311fd2f3"},{"Application Name":"Microsoft Learn","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Office","Application IDs":"d3590ed6-52b3-4102-aeff-aad2292ab01c"},{"Application Name":"Microsoft Office 365 Portal","Application IDs":"00000006-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Office Web Apps Service","Application IDs":"67e3df25-268a-4324-a550-0de1c7f97287"},{"Application Name":"Microsoft Online Syndication Partner Portal","Application IDs":"d176f6e7-38e5-40c9-8a78-3998aab820e7"},{"Application Name":"Microsoft password reset service","Application IDs":"93625bc8-bfe2-437a-97e0-3d0060024faa"},{"Application Name":"Microsoft Power BI","Application IDs":"871c010f-5e61-4fb1-83ac-98610a7e9110"},{"Application Name":"Microsoft Storefronts","Application IDs":"28b567f6-162c-4f54-99a0-6887f387bbcc"},{"Application Name":"Microsoft Stream Portal","Application IDs":"cf53fce8-def6-4aeb-8d30-b158e7b1cf83"},{"Application Name":"Microsoft Substrate Management","Application IDs":"98db8bd6-0cc0-4e67-9de5-f187f1cd1b41"},{"Application Name":"Microsoft Support","Application IDs":"fdf9885b-dd37-42bf-82e5-c3129ef5a302"},{"Application Name":"Microsoft Teams","Application IDs":"1fec8e78-bce4-4aaf-ab1b-5451cc387264"},{"Application Name":"Microsoft Teams Services","Application IDs":"cc15fd57-2c6c-4117-a88c-83b1d56b4bbe"},{"Application Name":"Microsoft Teams Web Client","Application IDs":"5e3ce6c0-2b1f-4285-8d4b-75ee78787346"},{"Application Name":"Microsoft Whiteboard Services","Application IDs":"95de633a-083e-42f5-b444-a4295d8e9314"},{"Application Name":"O365 Suite UX","Application IDs":"4345a7b9-9a63-4910-a426-35363201d503"},{"Application Name":"Office 365 Exchange Online","Application IDs":"00000002-0000-0ff1-ce00-000000000000"},{"Application Name":"Office 365 Management","Application IDs":"00b41c95-dab0-4487-9791-b9d2c32c80f2"},{"Application Name":"Office 365 Search Service","Application IDs":"66a88757-258c-4c72-893c-3e8bed4d6899"},{"Application Name":"Office 365 SharePoint Online","Application IDs":"00000003-0000-0ff1-ce00-000000000000"},{"Application Name":"Office Delve","Application IDs":"94c63fef-13a3-47bc-8074-75af8c65887a"},{"Application Name":"Office Online Add-in SSO","Application IDs":"93d53678-613d-4013-afc1-62e9e444a0a5"},{"Application Name":"Office Online Client AAD- Augmentation Loop","Application IDs":"2abdc806-e091-4495-9b10-b04d93c3f040"},{"Application Name":"Office Online Client AAD- Loki","Application IDs":"b23dd4db-9142-4734-867f-3577f640ad0c"},{"Application Name":"Office Online Client AAD- Maker","Application IDs":"17d5e35f-655b-4fb0-8ae6-86356e9a49f5"},{"Application Name":"Office Online Client MSA- Loki","Application IDs":"b6e69c34-5f1f-4c34-8cdf-7fea120b8670"},{"Application Name":"Office Online Core SSO","Application IDs":"243c63a3-247d-41c5-9d83-7788c43f1c43"},{"Application Name":"Office Online Search","Application IDs":"a9b49b65-0a12-430b-9540-c80b3332c127"},{"Application Name":"Office.com","Application IDs":"4b233688-031c-404b-9a80-a4f3f2351f90"},{"Application Name":"Office365 Shell WCSS-Client","Application IDs":"89bee1f7-5e6e-4d8a-9f3d-ecd601259da7"},{"Application Name":"OfficeClientService","Application IDs":"0f698dd4-f011-4d23-a33e-b36416dcb1e6"},{"Application Name":"OfficeHome","Application IDs":"4765445b-32c6-49b0-83e6-1d93765276ca"},{"Application Name":"OfficeShredderWacClient","Application IDs":"4d5c2d63-cf83-4365-853c-925fd1a64357"},{"Application Name":"OMSOctopiPROD","Application IDs":"62256cef-54c0-4cb4-bcac-4c67989bdc40"},{"Application Name":"OneDrive SyncEngine","Application IDs":"ab9b8c07-8f02-4f72-87fa-80105867a763"},{"Application Name":"OneNote","Application IDs":"2d4d3d8e-2be3-4bef-9f87-7875a61c29de"},{"Application Name":"Outlook Mobile","Application IDs":"27922004-5251-4030-b22d-91ecd9a37ea4"},{"Application Name":"Partner Customer Delegated Admin Offline Processor","Application IDs":"a3475900-ccec-4a69-98f5-a65cd5dc5306"},{"Application Name":"Password Breach Authenticator","Application IDs":"bdd48c81-3a58-4ea9-849c-ebea7f6b6360"},{"Application Name":"Power BI Service","Application IDs":"00000009-0000-0000-c000-000000000000"},{"Application Name":"SharedWithMe","Application IDs":"ffcb16e8-f789-467c-8ce9-f826a080d987"},{"Application Name":"SharePoint Online Web Client Extensibility","Application IDs":"08e18876-6177-487e-b8b5-cf950c1e598c"},{"Application Name":"Signup","Application IDs":"b4bddae8-ab25-483e-8670-df09b9f1d0ea"},{"Application Name":"Skype for Business Online","Application IDs":"00000004-0000-0ff1-ce00-000000000000"},{"Application Name":"Sway","Application IDs":"905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba"},{"Application Name":"Universal Store Native Client","Application IDs":"268761a2-03f3-40df-8a8b-c3db24145b6b"},{"Application Name":"Vortex [wsfed enabled]","Application IDs":"5572c4c0-d078-44ce-b81c-6cbf8d3ed39e"},{"Application Name":"Windows Azure Active Directory","Application IDs":"00000002-0000-0000-c000-000000000000"},{"Application Name":"Windows Azure Service Management API","Application IDs":"797f4846-ba00-4fd7-ba43-dac1f8f63013"},{"Application Name":"WindowsDefenderATP Portal","Application IDs":"a3b79187-70b2-4139-83f9-6016c58cd27b"},{"Application Name":"Windows Search","Application IDs":"26a7ee05-5602-4d76-a7ba-eae8b7b67941"},{"Application Name":"Windows Spotlight","Application IDs":"1b3c667f-cde3-4090-b60b-3d2abd0117f0"},{"Application Name":"Windows Store for Business","Application IDs":"45a330b1-b1ec-4cc1-9161-9f03992aa49f"},{"Application Name":"Yammer","Application IDs":"00000005-0000-0ff1-ce00-000000000000"},{"Application Name":"Yammer Web","Application IDs":"c1c74fed-04c9-4704-80dc-9f79a2e515cb"},{"Application Name":"Yammer Web Embed","Application IDs":"e1ef36fd-b883-4dbf-97f0-9ece4b576fc6"}]' | ConvertFrom-Json | Where-Object -Property 'Application IDs' -EQ $data.applicationId
$HTMLTemplate = Get-Content 'TemplateEmail.HTML' -Raw | Out-String
@@ -21,14 +22,14 @@ function New-CIPPAlertTemplate {
'New-InboxRule' {
$Title = "$($TenantFilter) - New Rule Detected for $($data.UserId)"
$RuleTable = ($Data.CIPPParameters | ConvertFrom-Json | ConvertTo-Html -Fragment | Out-String).Replace('', ' ')
-
+
$IntroText = "A new rule has been created for the user $($data.UserId). You should check if this rule is not malicious. The rule information can be found in the table below.
$RuleTable"
if ($ActionResults) { $IntroText = $IntroText + "Based on the rule, the following actions have been taken: $($ActionResults -join '
' )
" }
if ($LocationInfo) {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/ViewBec?userId=$($data.UserId)&tenantDomain=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/ViewBec?userId=$($data.UserId)&tenantDomain=$($data.OrganizationId)"
$ButtonText = 'Start BEC Investigation'
$AfterButtonText = 'If you believe this is a suspect rule, you can click the button above to start the investigation.
'
}
@@ -41,7 +42,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/ViewBec?userId=$($data.UserId)&tenantDomain=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/ViewBec?userId=$($data.UserId)&tenantDomain=$($data.OrganizationId)"
$ButtonText = 'Start BEC Investigation'
$AfterButtonText = 'If you believe this is a suspect rule, you can click the button above to start the investigation.
'
}
@@ -54,7 +55,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/roles?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/roles?customerId=$($data.OrganizationId)"
$ButtonText = 'Role Management'
$AfterButtonText = 'If this role is incorrect, or you need more information, use the button to jump to the Role Management page.
'
@@ -67,14 +68,14 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
$ButtonText = 'User Management'
$AfterButtonText = 'If this is incorrect, use the user management screen to unblock the users sign-in
'
}
'Enable account.' {
$Title = "$($TenantFilter) - $($data.ObjectId) has been enabled"
$IntroText = "$($data.ObjectId) has been enabled by $($data.UserId)."
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
if ($ActionResults) { $IntroText = $IntroText + "Based on the rule, the following actions have been taken: $($ActionResults -join '
' )
" }
if ($LocationInfo) {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
@@ -86,7 +87,7 @@ function New-CIPPAlertTemplate {
'Update StsRefreshTokenValidFrom Timestamp.' {
$Title = "$($TenantFilter) - $($data.ObjectId) has had all sessions revoked"
$IntroText = "$($data.ObjectId) has had their sessions revoked by $($data.UserId)."
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
if ($ActionResults) { $IntroText = $IntroText + "Based on the rule, the following actions have been taken: $($ActionResults -join '
' )
" }
if ($LocationInfo) {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
@@ -103,7 +104,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
$ButtonText = 'User Management'
$AfterButtonText = 'If this is incorrect, use the user management screen to reenable MFA
'
}
@@ -116,7 +117,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/roles?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/roles?customerId=$($data.OrganizationId)"
$ButtonText = 'Role Management'
$AfterButtonText = 'If this role change is incorrect, or you need more information, use the button to jump to the Role Management page.
'
@@ -130,7 +131,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
$ButtonText = 'User Management'
$AfterButtonText = 'If this is incorrect, use the user management screen to unblock the users sign-in
'
@@ -145,7 +146,7 @@ function New-CIPPAlertTemplate {
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
$IntroText = "$($data.ObjectId) has been added by $($data.UserId)."
- $ButtonUrl = "$CIPPPURL/tenant/administration/enterprise-apps?customerId=?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/tenant/administration/enterprise-apps?customerId=?customerId=$($data.OrganizationId)"
$ButtonText = 'Enterprise Apps'
}
'Remove service principal.' {
@@ -158,7 +159,7 @@ function New-CIPPAlertTemplate {
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
$IntroText = "$($data.ObjectId) has been added by $($data.UserId)."
- $ButtonUrl = "$CIPPPURL/tenant/administration/enterprise-apps?customerId=?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/tenant/administration/enterprise-apps?customerId=?customerId=$($data.OrganizationId)"
$ButtonText = 'Enterprise Apps'
}
'UserLoggedIn' {
@@ -171,7 +172,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/ViewBec?userId=$($data.ObjectId)&tenantDomain=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/ViewBec?userId=$($data.ObjectId)&tenantDomain=$($data.OrganizationId)"
$ButtonText = 'User Management'
$AfterButtonText = 'If this is incorrect, use the user management screen to block the user and revoke the sessions
'
}
@@ -184,7 +185,7 @@ function New-CIPPAlertTemplate {
$LocationTable = ($LocationInfo | ConvertTo-Html -Fragment -As List | Out-String).Replace('', ' ')
$IntroText = $IntroText + "The (potential) location information for this IP is as follows:
$LocationTable"
}
- $ButtonUrl = "$CIPPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
+ $ButtonUrl = "$CIPPURL/identity/administration/users?customerId=$($data.OrganizationId)"
$ButtonText = 'User Management'
}
}
@@ -196,8 +197,9 @@ function New-CIPPAlertTemplate {
}
} elseif ($Format -eq 'json') {
return [pscustomobject]@{
- title = $Title
- buttonurl = $ButtonUrl
+ title = $Title
+ buttonurl = $ButtonUrl
+ buttontext = $ButtonText
}
}
}
diff --git a/Modules/CIPPCore/Public/New-CIPPBackup.ps1 b/Modules/CIPPCore/Public/New-CIPPBackup.ps1
new file mode 100644
index 000000000000..3c9acd37e9cd
--- /dev/null
+++ b/Modules/CIPPCore/Public/New-CIPPBackup.ps1
@@ -0,0 +1,89 @@
+function New-CIPPBackup {
+ [CmdletBinding()]
+ param (
+ $backupType,
+ $StorageOutput = 'default',
+ $TenantFilter,
+ $APIName = 'CIPP Backup',
+ $ExecutingUser
+ )
+
+ $BackupData = switch ($backupType) {
+ #If backup type is CIPP, create CIPP backup.
+ 'CIPP' {
+ try {
+ $BackupTables = @(
+ 'bpa'
+ 'Config'
+ 'Domains'
+ 'ExcludedLicenses'
+ 'templates'
+ 'standards'
+ 'SchedulerConfig'
+ )
+ $CSVfile = foreach ($CSVTable in $BackupTables) {
+ $Table = Get-CippTable -tablename $CSVTable
+ Get-CIPPAzDataTableEntity @Table
+ }
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Created backup' -Sev 'Debug'
+ $CSVfile
+ $RowKey = 'CIPPBackup' + '_' + (Get-Date).ToString('yyyy-MM-dd-HHmm')
+ $entity = [PSCustomObject]@{
+ PartitionKey = 'CIPPBackup'
+ RowKey = $RowKey
+ TenantFilter = 'CIPPBackup'
+ Backup = [string]($CSVfile | ConvertTo-Json -Compress -Depth 100)
+ }
+ $Table = Get-CippTable -tablename 'CIPPBackup'
+ try {
+ $Result = Add-CIPPAzDataTableEntity @Table -entity $entity -Force
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Created CIPP Backup' -Sev 'Debug'
+ } catch {
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create backup for CIPP: $($_.Exception.Message)" -Sev 'Error'
+ [pscustomobject]@{'Results' = "Backup Creation failed: $($_.Exception.Message)" }
+ }
+
+ } catch {
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create backup: $($_.Exception.Message)" -Sev 'Error'
+ [pscustomobject]@{'Results' = "Backup Creation failed: $($_.Exception.Message)" }
+ }
+ }
+
+ #If Backup type is ConditionalAccess, create Conditional Access backup.
+ 'ConditionalAccess' {
+ $ConditionalAccessPolicyOutput = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $tenantfilter
+ $AllNamedLocations = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -tenantid $tenantfilter
+ switch ($StorageOutput) {
+ 'default' {
+ [PSCustomObject]@{
+ ConditionalAccessPolicies = $ConditionalAccessPolicyOutput
+ NamedLocations = $AllNamedLocations
+ }
+ }
+ 'table' {
+ #Store output in tablestorage for Recovery
+ $RowKey = $TenantFilter + '_' + (Get-Date).ToString('yyyy-MM-dd-HHmm')
+ $entity = [PSCustomObject]@{
+ PartitionKey = 'ConditionalAccessBackup'
+ RowKey = $RowKey
+ TenantFilter = $TenantFilter
+ Policies = [string]($ConditionalAccessPolicyOutput | ConvertTo-Json -Compress -Depth 10)
+ NamedLocations = [string]($AllNamedLocations | ConvertTo-Json -Compress -Depth 10)
+ }
+ $Table = Get-CippTable -tablename 'ConditionalAccessBackup'
+ try {
+ $Result = Add-CIPPAzDataTableEntity @Table -entity $entity -Force
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Created backup for Conditional Access Policies' -Sev 'Debug'
+ $Result
+ } catch {
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to create backup for Conditional Access Policies: $($_.Exception.Message)" -Sev 'Error'
+ [pscustomobject]@{'Results' = "Backup Creation failed: $($_.Exception.Message)" }
+ }
+ }
+ }
+ }
+
+ }
+ return $BackupData
+}
+
diff --git a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
index f7d0eb366389..535156115d0b 100644
--- a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
+++ b/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1
@@ -55,12 +55,12 @@ function New-CIPPGraphSubscription {
return @{ success = $true; message = "Webhook exists for $($TenantFilter) for the log $($EventType)" }
Write-LogMessage -user $ExecutingUser -API $APIName -message "Webhook subscription for $($TenantFilter) already exists" -Sev 'Info' -tenant $TenantFilter
} else {
- Remove-AzDataTableEntity @WebhookTable -Entity @{ PartitionKey = $TenantFilter; RowKey = $CIPPID } | Out-Null
+ Remove-AzDataTableEntity @WebhookTable -Entity @{ PartitionKey = $TenantFilter; RowKey = [string]$CIPPID } | Out-Null
Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter
return @{ success = $false; message = "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" }
}
}
-
+
} elseif ($PartnerCenter.IsPresent) {
$WebhookFilter = "PartitionKey eq '$($env:TenantId)'"
$ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
diff --git a/Modules/CIPPCore/Public/SAMManifest.json b/Modules/CIPPCore/Public/SAMManifest.json
index 4fce3279465c..b6b291da57b4 100644
--- a/Modules/CIPPCore/Public/SAMManifest.json
+++ b/Modules/CIPPCore/Public/SAMManifest.json
@@ -155,9 +155,11 @@
{ "id": "84bccea3-f856-4a8a-967b-dbe0a3d53a64", "type": "Scope" },
{ "id": "280b3b69-0437-44b1-bc20-3b2fca1ee3e9", "type": "Scope" },
{ "id": "885f682f-a990-4bad-a642-36736a74b0c7", "type": "Scope" },
- { "id": "913b9306-0ce1-42b8-9137-6a7df690a760", "type": "Role"},
- { "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope"},
- { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope"}
+ { "id": "913b9306-0ce1-42b8-9137-6a7df690a760", "type": "Role" },
+ { "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope" },
+ { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" },
+ { "id": "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", "type": "Role" },
+ { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" }
]
},
{
diff --git a/Modules/CIPPCore/Public/Send-CIPPAlert.ps1 b/Modules/CIPPCore/Public/Send-CIPPAlert.ps1
index 59395211a55a..8fc9e31f7bdf 100644
--- a/Modules/CIPPCore/Public/Send-CIPPAlert.ps1
+++ b/Modules/CIPPCore/Public/Send-CIPPAlert.ps1
@@ -53,12 +53,20 @@ function Send-CIPPAlert {
if ($PSCmdlet.ShouldProcess($Config.webhook, 'Sending webhook')) {
switch -wildcard ($config.webhook) {
'*webhook.office.com*' {
- $JSonBody = "{`"text`": `"You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log.
$JSONContent`"}"
+ $JSONBody = "{`"text`": `"You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log.
$JSONContent`"}"
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
}
-
'*discord.com*' {
- $JSonBody = "{`"content`": `"You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log. $JSONContent`"}"
+ $JSONBody = "{`"content`": `"You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log. $JSONContent`"}"
+ Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
+ }
+ '*slack.com*' {
+ $SlackBlocks = Get-SlackAlertBlocks -JSONBody $JSONContent
+ if ($SlackBlocks.blocks) {
+ $JSONBody = $SlackBlocks | ConvertTo-Json -Depth 10 -Compress
+ } else {
+ $JSONBody = "{`"text`": `"You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log. $JSONContent`"}"
+ }
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
}
default {
diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1
index 1aabf9920b17..15ecab0ea749 100644
--- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1
+++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1
@@ -5,6 +5,7 @@ function Set-CIPPAssignedPolicy {
$PolicyId,
$Type,
$TenantFilter,
+ $PlatformType = 'deviceManagement',
$APIName = 'Assign Policy',
$ExecutingUser
)
@@ -69,12 +70,12 @@ function Set-CIPPAssignedPolicy {
assignments = @($assignmentsObject)
}
if ($PSCmdlet.ShouldProcess($GroupName, "Assigning policy $PolicyId")) {
- $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body ($assignmentsObject | ConvertTo-Json -Depth 10)
+ $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body ($assignmentsObject | ConvertTo-Json -Depth 10)
Write-LogMessage -user $ExecutingUser -API $APIName -message "Assigned Policy to $($GroupName)" -Sev 'Info' -tenant $TenantFilter
}
- return "Assigned policy to $($GroupName)"
+ return "Assigned policy to $($GroupName) Policy ID is $($PolicyId)."
} catch {
- Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to assign Policy to $GroupName" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
- return "Could not assign policy to $GroupName. Error: $($_.Exception.Message)"
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to assign Policy to $GroupName. Policy ID is $($PolicyId)." -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
+ return "Could not assign policy to $GroupName. Policy ID is $($PolicyId). Error: $($_.Exception.Message)"
}
}
diff --git a/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1
index d953ee938285..07f2646a7243 100644
--- a/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1
+++ b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1
@@ -15,6 +15,7 @@ function Set-CIPPDefaultAPDeploymentProfile {
$hideTerms,
$Autokeyboard,
$ExecutingUser,
+ $Language = 'os-default',
$APIName = 'Add Default Enrollment Status Page'
)
try {
@@ -23,7 +24,7 @@ function Set-CIPPDefaultAPDeploymentProfile {
'displayName' = "$($displayname)"
'description' = "$($description)"
'deviceNameTemplate' = "$($DeviceNameTemplate)"
- 'language' = 'os-default'
+ 'language' = "$($Language)"
'enableWhiteGlove' = $([bool]($allowWhiteGlove))
'deviceType' = 'windowsPc'
'extractHardwareHash' = $([bool]($CollectHash))
diff --git a/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1 b/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1
index 5d75e787f233..798dfdb71553 100644
--- a/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1
+++ b/Modules/CIPPCore/Public/Set-CIPPDefaultAPEnrollment.ps1
@@ -20,7 +20,7 @@ function Set-CIPPDefaultAPEnrollment {
'displayName' = 'All users and all devices'
'description' = 'This is the default enrollment status screen configuration applied with the lowest priority to all users and all devices regardless of group membership.'
'showInstallationProgress' = [bool]$ShowProgress
- 'blockDeviceSetupRetryByUser' = [bool]$blockDevice
+ 'blockDeviceSetupRetryByUser' = ![bool]$blockDevice
'allowDeviceResetOnInstallFailure' = [bool]$AllowReset
'allowLogCollectionOnInstallFailure' = [bool]$EnableLog
'customErrorMessage' = "$ErrorMessage"
diff --git a/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1 b/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1
new file mode 100644
index 000000000000..1c92a5e9c5d2
--- /dev/null
+++ b/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1
@@ -0,0 +1,69 @@
+function Set-CIPPPerUserMFA {
+ <#
+ .SYNOPSIS
+ Change Per-User MFA State for a User
+
+ .DESCRIPTION
+ Change the Per-User MFA State for a user via the /users/{id}/authentication/requirements endpoint
+
+ .PARAMETER TenantFilter
+ Tenant where the user resides
+
+ .PARAMETER userId
+ One or more User IDs to set the MFA state for (GUID or UserPrincipalName)
+
+ .PARAMETER State
+ State to set the user to (enabled, disabled, enforced)
+
+ .PARAMETER executingUser
+ User executing the command
+
+ .EXAMPLE
+ Set-CIPPPerUserMFA -TenantFilter 'contoso.onmicrosoft.com' -userId user@contoso.onmicrosoft.com -State 'disabled' -executingUser 'mspuser@partner.com'
+ #>
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]$TenantFilter,
+ [Parameter(Mandatory = $true)]
+ [string[]]$userId,
+ [ValidateSet('enabled', 'disabled', 'enforced')]
+ $State = 'enabled',
+ [string]$executingUser = 'CIPP'
+ )
+ try {
+ $int = 0
+ $Body = @{
+ perUserMFAstate = $State
+ }
+ $Requests = foreach ($id in $userId) {
+ @{
+ id = $int++
+ method = 'PATCH'
+ url = "users/$id/authentication/requirements"
+ body = $Body
+ 'headers' = @{
+ 'Content-Type' = 'application/json'
+ }
+ }
+ }
+
+
+ $Requests = New-GraphBulkRequest -tenantid $tenantfilter -scope 'https://graph.microsoft.com/.default' -Requests @($Requests) -asapp $true
+ "Successfully set Per user MFA State for $userId"
+
+ $Users = foreach ($id in $userId) {
+ @{
+ userId = $id
+ Properties = @{
+ perUserMfaState = $State
+ }
+ }
+ }
+ Set-CIPPUserSchemaProperties -TenantFilter $TenantFilter -Users $Users
+ Write-LogMessage -user $executingUser -API 'Set-CIPPPerUserMFA' -message "Successfully set Per user MFA State to $State for $id" -Sev 'Info' -tenant $TenantFilter
+ } catch {
+ "Failed to set MFA State for $id : $_"
+ Write-LogMessage -user $executingUser -API 'Set-CIPPPerUserMFA' -message "Failed to set MFA State to $State for $id : $_" -Sev 'Error' -tenant $TenantFilter
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1
index 6128fd2af888..aff8463210be 100644
--- a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1
+++ b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1
@@ -3,26 +3,31 @@ function Set-CIPPResetPassword {
param(
$userid,
$tenantFilter,
- $APIName = "Reset Password",
+ $APIName = 'Reset Password',
$ExecutingUser,
[bool]$forceChangePasswordNextSignIn = $true
)
- try {
+ try {
$password = New-passwordString
$passwordProfile = @{
- "passwordProfile" = @{
- "forceChangePasswordNextSignIn" = $forceChangePasswordNextSignIn
- "password" = $password
+ 'passwordProfile' = @{
+ 'forceChangePasswordNextSignIn' = $forceChangePasswordNextSignIn
+ 'password' = $password
}
} | ConvertTo-Json -Compress
- $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($userid)" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose
- Write-LogMessage -user $ExecutingUser -API $APIName -message "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn" -Sev "Info" -tenant $TenantFilter
+ $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($userid)" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose
+
+ #PWPush
+ $PasswordLink = New-PwPushLink -Payload $password
+ if ($PasswordLink) {
+ $password = $PasswordLink
+ }
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn" -Sev 'Info' -tenant $TenantFilter
return "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password"
- }
- catch {
- Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not reset password for $($userid)" -Sev "Error" -tenant $TenantFilter
+ } catch {
+ Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not reset password for $($userid)" -Sev 'Error' -tenant $TenantFilter
return "Could not reset password for $($userid). Error: $($_.Exception.Message)"
}
}
diff --git a/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1 b/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1
new file mode 100644
index 000000000000..692b6c4828ef
--- /dev/null
+++ b/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1
@@ -0,0 +1,129 @@
+function Set-CIPPUserJITAdmin {
+ <#
+ .SYNOPSIS
+ Just-in-time admin management
+
+ .DESCRIPTION
+ Just-in-time admin management for CIPP. This function can create users, add roles, remove roles, delete, or disable a user.
+
+ .PARAMETER TenantFilter
+ Tenant to manage for JIT admin
+
+ .PARAMETER User
+ User object to manage JIT admin roles, required property UserPrincipalName - If user is being created we also require FirstName and LastName
+
+ .PARAMETER Roles
+ List of Role GUIDs to add or remove
+
+ .PARAMETER Action
+ Action to perform: Create, AddRoles, RemoveRoles, DeleteUser, DisableUser
+
+ .PARAMETER Expiration
+ DateTime for expiration
+
+ .EXAMPLE
+ Set-CIPPUserJITAdmin -TenantFilter 'contoso.onmicrosoft.com' -User @{UserPrincipalName = 'jit@contoso.onmicrosoft.com'} -Roles @('62e90394-69f5-4237-9190-012177145e10') -Action 'AddRoles' -Expiration (Get-Date).AddDays(1)
+
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ Param(
+ [Parameter(Mandatory = $true)]
+ [string]$TenantFilter,
+
+ [Parameter(Mandatory = $true)]
+ [hashtable]$User,
+
+ [string[]]$Roles,
+
+ [Parameter(Mandatory = $true)]
+ [ValidateSet('Create', 'AddRoles', 'RemoveRoles', 'DeleteUser', 'DisableUser')]
+ [string]$Action,
+
+ [datetime]$Expiration
+ )
+
+ if ($PSCmdlet.ShouldProcess("User: $($User.UserPrincipalName)", "Action: $Action")) {
+ if ($Action -ne 'Create') {
+ $UserObj = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/users/$($User.UserPrincipalName)" -tenantid $TenantFilter
+ }
+
+ switch ($Action) {
+ 'Create' {
+ $Password = New-passwordString
+ $Body = @{
+ givenName = $User.FirstName
+ surname = $User.LastName
+ accountEnabled = $true
+ displayName = $User.FirstName + ' ' + $User.LastName
+ userPrincipalName = $User.UserPrincipalName
+ mailNickname = $User.UserPrincipalName.Split('@')[0]
+ passwordProfile = @{
+ forceChangePasswordNextSignIn = $true
+ forceChangePasswordNextSignInWithMfa = $false
+ password = $Password
+ }
+ }
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Body
+ try {
+ $NewUser = New-GraphPOSTRequest -type POST -Uri 'https://graph.microsoft.com/beta/users' -Body $Json -tenantid $TenantFilter
+ #PWPush
+ $PasswordLink = New-PwPushLink -Payload $Password
+ if ($PasswordLink) {
+ $Password = $PasswordLink
+ }
+ [PSCustomObject]@{
+ id = $NewUser.id
+ userPrincipalName = $NewUser.userPrincipalName
+ password = $Password
+ }
+ } catch {
+ Write-Information "Error creating user: $($_.Exception.Message)"
+ throw $_.Exception.Message
+ }
+ }
+ 'AddRoles' {
+ $Roles = $Roles | ForEach-Object {
+ try {
+ $Body = @{
+ '@odata.id' = "https://graph.microsoft.com/v1.0/directoryObjects/$($UserObj.id)"
+ }
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Body
+ $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/directoryRoles(roleTemplateId='$($_)')/members/`$ref" -tenantid $TenantFilter -body $Json -ErrorAction SilentlyContinue
+ } catch {}
+ }
+ Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $UserObj.id -Enabled -Expiration $Expiration | Out-Null
+ return "Added admin roles to user $($UserObj.displayName) ($($UserObj.userPrincipalName))"
+ }
+ 'RemoveRoles' {
+ $Roles = $Roles | ForEach-Object {
+ try {
+ $null = New-GraphPOSTRequest -type DELETE -uri "https://graph.microsoft.com/beta/directoryRoles(roleTemplateId='$($_)')/members/$($UserObj.id)/`$ref" -tenantid $TenantFilter
+ } catch {}
+ }
+ Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $UserObj.id -Clear | Out-Null
+ return "Removed admin roles from user $($UserObj.displayName)"
+ }
+ 'DeleteUser' {
+ try {
+ $null = New-GraphPOSTRequest -type DELETE -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $TenantFilter
+ return "Deleted user $($UserObj.displayName) ($($UserObj.userPrincipalName)) with id $($UserObj.id)"
+ } catch {
+ return "Error deleting user $($UserObj.displayName) ($($UserObj.userPrincipalName)): $($_.Exception.Message)"
+ }
+ }
+ 'DisableUser' {
+ $Body = @{
+ accountEnabled = $false
+ }
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Body
+ try {
+ New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $TenantFilter -body $Json
+ Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $UserObj.id -Enabled:$false | Out-Null
+ return "Disabled user $($UserObj.displayName) ($($UserObj.userPrincipalName))"
+ } catch {
+ return "Error disabling user $($UserObj.displayName) ($($UserObj.userPrincipalName)): $($_.Exception.Message)"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Set-CIPPUserJITAdminProperties.ps1 b/Modules/CIPPCore/Public/Set-CIPPUserJITAdminProperties.ps1
new file mode 100644
index 000000000000..c6203128f2f9
--- /dev/null
+++ b/Modules/CIPPCore/Public/Set-CIPPUserJITAdminProperties.ps1
@@ -0,0 +1,31 @@
+function Set-CIPPUserJITAdminProperties {
+ [CmdletBinding()]
+ Param(
+ [string]$TenantFilter,
+ [string]$UserId,
+ [switch]$Enabled,
+ $Expiration,
+ [switch]$Clear
+ )
+
+ $Schema = Get-CIPPSchemaExtensions | Where-Object { $_.id -match '_cippUser' }
+ if ($Clear.IsPresent) {
+ $Body = [PSCustomObject]@{
+ "$($Schema.id)" = @{
+ jitAdminEnabled = $null
+ jitAdminExpiration = $null
+ }
+ }
+ } else {
+ $Body = [PSCustomObject]@{
+ "$($Schema.id)" = @{
+ jitAdminEnabled = $Enabled.IsPresent
+ jitAdminExpiration = $Expiration.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
+ }
+ }
+ }
+
+ $Json = ConvertTo-Json -Depth 5 -InputObject $Body
+ Write-Information $Json
+ New-GraphPOSTRequest -type PATCH -Uri "https://graph.microsoft.com/beta/users/$UserId" -Body $Json -tenantid $TenantFilter | Out-Null
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Set-CIPPUserSchemaProperties.ps1 b/Modules/CIPPCore/Public/Set-CIPPUserSchemaProperties.ps1
new file mode 100644
index 000000000000..b006a27069ef
--- /dev/null
+++ b/Modules/CIPPCore/Public/Set-CIPPUserSchemaProperties.ps1
@@ -0,0 +1,46 @@
+function Set-CIPPUserSchemaProperties {
+ <#
+ .SYNOPSIS
+ Set Schema Properties for a user
+
+ .DESCRIPTION
+ Uses scheam extensions to set properties for a user
+
+ .PARAMETER TenantFilter
+ Tenant for user
+
+ .PARAMETER UserId
+ One or more user ids to set properties for
+
+ .PARAMETER Properties
+ Hashtable of properties to set
+
+ #>
+ [CmdletBinding(SupportsShouldProcess = $true)]
+ Param(
+ [Parameter(Mandatory = $true)]
+ [string]$TenantFilter,
+ [Parameter(Mandatory = $true)]
+ [object]$Users
+ )
+
+ $Schema = Get-CIPPSchemaExtensions | Where-Object { $_.id -match '_cippUser' }
+ $int = 0
+ $Requests = foreach ($User in $Users) {
+ @{
+ id = $int++
+ method = 'PATCH'
+ url = "users/$($User.userId)"
+ body = @{
+ "$($Schema.id)" = $User.Properties
+ }
+ 'headers' = @{
+ 'Content-Type' = 'application/json'
+ }
+ }
+ }
+
+ if ($PSCmdlet.ShouldProcess("User: $($Users.userId -join ', ')", 'Set Schema Properties')) {
+ $Requests = New-GraphBulkRequest -tenantid $tenantfilter -Requests @($Requests)
+ }
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
index 5b73e19eae98..6e941c7608cd 100644
--- a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
+++ b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1
@@ -43,7 +43,7 @@ function Get-CIPPStandards {
if ($StandardsTenant.Standards.OverrideAllTenants.remediate -ne $true) {
#Write-Host 'AllTenant Standards apply to this tenant.'
foreach ($StandardName in $StandardsAllTenants.Standards.PSObject.Properties.Name) {
- $CurrentStandard = $StandardsAllTenants.Standards.$StandardName
+ $CurrentStandard = $StandardsAllTenants.Standards.$StandardName.PSObject.Copy()
#Write-Host ($CurrentStandard | ConvertTo-Json -Depth 10)
if ($CurrentStandard.remediate -eq $true -or $CurrentStandard.alert -eq $true -or $CurrentStandard.report -eq $true) {
#Write-Host "AllTenant Standard $StandardName"
@@ -54,16 +54,16 @@ function Get-CIPPStandards {
foreach ($StandardName in $StandardsTenant.Standards.PSObject.Properties.Name) {
if ($StandardName -eq 'OverrideAllTenants') { continue }
- $CurrentStandard = $StandardsTenant.Standards.$StandardName
+ $CurrentStandard = $StandardsTenant.Standards.$StandardName.PSObject.Copy()
if ($CurrentStandard.remediate -eq $true -or $CurrentStandard.alert -eq $true -or $CurrentStandard.report -eq $true) {
- #Write-Host "`r`nTenant: $StandardName"
+ # Write-Host "`r`nTenant: $StandardName"
if (!$ComputedStandards[$StandardName] ) {
#Write-Host "Applying tenant level $StandardName"
$ComputedStandards[$StandardName] = $CurrentStandard
} else {
foreach ($Setting in $CurrentStandard.PSObject.Properties.Name) {
- #Write-Host "$Setting - Current: $($CurrentStandard.$Setting) | Computed: $($ComputedStandards[$StandardName].$($Setting))"
+ # Write-Host "$Setting - Current: $($CurrentStandard.$Setting) | Computed: $($ComputedStandards[$StandardName].$($Setting))"
if ($CurrentStandard.$Setting -ne $false -and $CurrentStandard.$Setting -ne $ComputedStandards[$StandardName].$($Setting) -and ![string]::IsNullOrEmpty($CurrentStandard.$Setting)) {
#Write-Host "Overriding $Setting for $StandardName at tenant level"
if ($ComputedStandards[$StandardName].PSObject.Properties.Name -contains $Setting) {
@@ -76,12 +76,13 @@ function Get-CIPPStandards {
}
}
}
- }
- foreach ($Standard in $ComputedStandards.Keys) {
- [pscustomobject]@{
- Tenant = $Tenant.defaultDomainName
- Standard = $Standard
- Settings = $ComputedStandards.$Standard
+
+ foreach ($Standard in $ComputedStandards.Keys) {
+ [pscustomobject]@{
+ Tenant = $Tenant.defaultDomainName
+ Standard = $Standard
+ Settings = $ComputedStandards.$Standard
+ }
}
}
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1
index 6311c6680421..b6ffea3946d5 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1
@@ -12,7 +12,7 @@ function Invoke-CIPPStandardAPConfig {
Write-Host $($settings | ConvertTo-Json -Depth 100)
if ($settings.NotLocalAdmin -eq $true) { $usertype = 'Standard' } else { $usertype = 'Administrator' }
$DeploymentMode = if ($settings.DeploymentMode -eq 'true') { 'shared' } else { 'singleUser' }
- Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $settings.DisplayName -description $settings.Description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $settings.Assignto -devicenameTemplate $Settings.DeviceNameTemplate -allowWhiteGlove $Settings.allowWhiteGlove -CollectHash $Settings.CollectHash -hideChangeAccount $Settings.HideChangeAccount -hidePrivacy $Settings.HidePrivacy -hideTerms $Settings.HideTerms -Autokeyboard $Settings.Autokeyboard
+ Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $settings.DisplayName -description $settings.Description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $settings.Assignto -devicenameTemplate $Settings.DeviceNameTemplate -allowWhiteGlove $Settings.allowWhiteGlove -CollectHash $Settings.CollectHash -hideChangeAccount $Settings.HideChangeAccount -hidePrivacy $Settings.HidePrivacy -hideTerms $Settings.HideTerms -Autokeyboard $Settings.Autokeyboard -Language $Settings.languages.value
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
#Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create Default Autopilot config: $ErrorMessage" -sev 'Error'
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1
index 90d632232fe6..29d1862ecb01 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1
@@ -4,41 +4,61 @@ function Invoke-CIPPStandardActivityBasedTimeout {
Internal
#>
param($Tenant, $Settings)
- $State = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $tenant).id
+
+ if ($Settings.timeout -eq 'Select a value') {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'No value selected for Activity Based Timeout' -sev Error
+ Exit
+ }
+
+ # Backwards compatibility for v5.7.0 and older
+ if ($null -eq $Settings.timeout ) { $Settings.timeout = '01:00:00' }
+
+ $State = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $tenant
+ $StateIsCorrect = $State.definition -like "*$($Settings.timeout)*"
If ($Settings.remediate -eq $true) {
try {
- if (!$State) {
- $body = @'
-{
- "displayName": "DefaultTimeoutPolicy",
- "isOrganizationDefault": true,
- "definition":["{\"ActivityBasedTimeoutPolicy\":{\"Version\":1,\"ApplicationPolicies\":[{\"ApplicationId\":\"default\",\"WebSessionIdleTimeout\":\"01:00:00\"}]}}"]
-}
-'@
+ if (!$StateIsCorrect) {
+ $PolicyTemplate = @{
+ displayName = 'DefaultTimeoutPolicy'
+ isOrganizationDefault = $true
+ definition = @(
+ "{`"ActivityBasedTimeoutPolicy`":{`"Version`":1,`"ApplicationPolicies`":[{`"ApplicationId`":`"default`",`"WebSessionIdleTimeout`":`"$($Settings.timeout)`"}]}}"
+ )
+ }
+ $body = ConvertTo-Json -InputObject $PolicyTemplate -Depth 10 -Compress
- New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -Type POST -Body $body -ContentType 'application/json'
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled Activity Based Timeout of one hour' -sev Info
+ # Switch between parameter sets if the policy already exists
+ if ($null -eq $State.id) {
+ $RequestType = 'POST'
+ $URI = 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies'
+ } else {
+ $RequestType = 'PATCH'
+ $URI = "https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies/$($State.id)"
+ }
+ New-GraphPostRequest -tenantid $tenant -Uri $URI -Type $RequestType -Body $body -ContentType 'application/json'
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Enabled Activity Based Timeout with a value of $($Settings.timeout)" -sev Info
} else {
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Activity Based Timeout is already enabled' -sev Info
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is already enabled and set to $($Settings.timeout)" -sev Info
}
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Activity Based Timeout $ErrorMessage" -sev Error
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Activity Based Timeout a value of $($Settings.timeout). Error: $ErrorMessage" -sev Error
}
}
if ($Settings.alert -eq $true) {
- if ($State) {
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Activity Based Timeout is enabled' -sev Info
+ if ($StateIsCorrect) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is enabled and set to $($Settings.timeout)" -sev Info
} else {
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Activity Based Timeout is not enabled' -sev Alert
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is not set to $($Settings.timeout)" -sev Alert
}
}
if ($Settings.report -eq $true) {
- Add-CIPPBPAField -FieldName 'ActivityBasedTimeout' -FieldValue $state -StoreAs bool -Tenant $tenant
+
+ Add-CIPPBPAField -FieldName 'ActivityBasedTimeout' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant
}
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1
index b4673244d148..d4b8bd35166c 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1
@@ -5,7 +5,7 @@ function Invoke-CIPPStandardAddDKIM {
#>
param($Tenant, $Settings)
- $AllDomains = (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains?$top=999' -tenantid $Tenant | Where-Object { $_.supportedServices -contains 'Email' }).id
+ $AllDomains = (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains?$top=999' -tenantid $Tenant | Where-Object { $_.supportedServices -contains 'Email' -or $_.id -like '*mail.onmicrosoft.com' }).id
$DKIM = (New-ExoRequest -tenantid $tenant -cmdlet 'Get-DkimSigningConfig') | Select-Object Domain, Enabled, Status
# List of domains for each way to enable DKIM
@@ -18,6 +18,8 @@ function Invoke-CIPPStandardAddDKIM {
Write-LogMessage -API 'Standards' -tenant $tenant -message 'DKIM is already enabled for all available domains.' -sev Info
} else {
$ErrorCounter = 0
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Trying to enable DKIM for:$($NewDomains -join ', ' ) $($SetDomains.Domain -join ', ')" -sev Info
+
# New-domains
$Request = $NewDomains | ForEach-Object {
@{
@@ -27,8 +29,7 @@ function Invoke-CIPPStandardAddDKIM {
}
}
}
-
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) -useSystemMailbox $true
+ if ($null -ne $Request) { $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) -useSystemMailbox $true }
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorCounter ++
@@ -36,29 +37,31 @@ function Invoke-CIPPStandardAddDKIM {
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable DKIM. Error: $ErrorMessage" -sev Error
}
}
+
# Set-domains
$Request = $SetDomains | ForEach-Object {
@{
CmdletInput = @{
CmdletName = 'Set-DkimSigningConfig'
- Parameters = @{ Identity = $Domain.Domain; Enabled = $true }
+ Parameters = @{ Identity = $_.Domain; Enabled = $true }
}
}
}
-
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) -useSystemMailbox $true
+ if ($null -ne $Request) { $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) -useSystemMailbox $true }
$BatchResults | ForEach-Object {
if ($_.error) {
+ $ErrorCounter ++
$ErrorMessage = Get-NormalizedError -Message $_.error
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set DKIM. Error: $ErrorMessage" -sev Error
- $ErrorCounter ++
}
+ }
- if ($ErrorCounter -eq 0) {
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled DKIM for all domains in tenant' -sev Info
- } else {
- Write-LogMessage -API 'Standards' -tenant $tenant -message 'Failed to enable DKIM for all domains in tenant' -sev Error
- }
+ if ($ErrorCounter -eq 0) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled DKIM for all domains in tenant' -sev Info
+ } elseif ($ErrorCounter -gt 0 -and $ErrorCounter -lt ($NewDomains.Count + $SetDomains.Count)) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Failed to enable DKIM for some domains in tenant' -sev Error
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Failed to enable DKIM for all domains in tenant' -sev Error
}
}
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1
index b96e9f47ec89..1eeb304a0768 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1
@@ -1,80 +1,119 @@
-function Invoke-CIPPStandardAntiPhishPolicy {
- <#
- .FUNCTIONALITY
- Internal
- #>
-
- param($Tenant, $Settings)
- $PolicyName = 'Default Anti-Phishing Policy'
-
- $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishPolicy' |
- Where-Object -Property Name -EQ $PolicyName |
- Select-Object Name, Enabled, PhishThresholdLevel, EnableMailboxIntelligence, EnableMailboxIntelligenceProtection, EnableSpoofIntelligence, EnableFirstContactSafetyTips, EnableSimilarUsersSafetyTips, EnableSimilarDomainsSafetyTips, EnableUnusualCharactersSafetyTips, EnableUnauthenticatedSender, EnableViaTag, MailboxIntelligenceProtectionAction, MailboxIntelligenceQuarantineTag
-
- $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and
- ($CurrentState.Enabled -eq $true) -and
- ($CurrentState.PhishThresholdLevel -eq $Settings.PhishThresholdLevel) -and
- ($CurrentState.EnableMailboxIntelligence -eq $true) -and
- ($CurrentState.EnableMailboxIntelligenceProtection -eq $true) -and
- ($CurrentState.EnableSpoofIntelligence -eq $true) -and
- ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and
- ($CurrentState.EnableSimilarUsersSafetyTips -eq $Settings.EnableSimilarUsersSafetyTips) -and
- ($CurrentState.EnableSimilarDomainsSafetyTips -eq $Settings.EnableSimilarDomainsSafetyTips) -and
- ($CurrentState.EnableUnusualCharactersSafetyTips -eq $Settings.EnableUnusualCharactersSafetyTips) -and
- ($CurrentState.EnableUnauthenticatedSender -eq $true) -and
- ($CurrentState.EnableViaTag -eq $true) -and
- ($CurrentState.MailboxIntelligenceProtectionAction -eq $Settings.MailboxIntelligenceProtectionAction) -and
- ($CurrentState.MailboxIntelligenceQuarantineTag -eq $Settings.MailboxIntelligenceQuarantineTag)
-
- if ($Settings.remediate -eq $true) {
- if ($StateIsCorrect -eq $true) {
- Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy already correctly configured' -sev Info
- } else {
- $cmdparams = @{
- Enabled = $true
- PhishThresholdLevel = $Settings.PhishThresholdLevel
- EnableMailboxIntelligence = $true
- EnableMailboxIntelligenceProtection = $true
- EnableSpoofIntelligence = $true
- EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips
- EnableSimilarUsersSafetyTips = $Settings.EnableSimilarUsersSafetyTips
- EnableSimilarDomainsSafetyTips = $Settings.EnableSimilarDomainsSafetyTips
- EnableUnusualCharactersSafetyTips = $Settings.EnableUnusualCharactersSafetyTips
- EnableUnauthenticatedSender = $true
- EnableViaTag = $true
- MailboxIntelligenceProtectionAction = $Settings.MailboxIntelligenceProtectionAction
- MailboxIntelligenceQuarantineTag = $Settings.MailboxIntelligenceQuarantineTag
- }
-
- try {
- if ($CurrentState.Name -eq $PolicyName) {
- $cmdparams.Add('Identity', $PolicyName)
- New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishPolicy' -cmdparams $cmdparams
- Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Anti-phishing Policy' -sev Info
- } else {
- $cmdparams.Add('Name', $PolicyName)
- New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishPolicy' -cmdparams $cmdparams
- Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created Anti-phishing Policy' -sev Info
- }
- } catch {
- $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing Policy. Error: $ErrorMessage" -sev Error
- }
- }
- }
-
-
- if ($Settings.alert -eq $true) {
-
- if ($StateIsCorrect -eq $true) {
- Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy is enabled' -sev Info
- } else {
- Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy is not enabled' -sev Alert
- }
- }
-
- if ($Settings.report -eq $true) {
- Add-CIPPBPAField -FieldName 'AntiPhishPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant
- }
-
-}
\ No newline at end of file
+function Invoke-CIPPStandardAntiPhishPolicy {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+
+ param($Tenant, $Settings)
+ $PolicyName = 'Default Anti-Phishing Policy'
+
+ $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishPolicy' |
+ Where-Object -Property Name -EQ $PolicyName |
+ Select-Object Name, Enabled, PhishThresholdLevel, EnableMailboxIntelligence, EnableMailboxIntelligenceProtection, EnableSpoofIntelligence, EnableFirstContactSafetyTips, EnableSimilarUsersSafetyTips, EnableSimilarDomainsSafetyTips, EnableUnusualCharactersSafetyTips, EnableUnauthenticatedSender, EnableViaTag, MailboxIntelligenceProtectionAction, MailboxIntelligenceQuarantineTag
+
+ $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and
+ ($CurrentState.Enabled -eq $true) -and
+ ($CurrentState.PhishThresholdLevel -eq $Settings.PhishThresholdLevel) -and
+ ($CurrentState.EnableMailboxIntelligence -eq $true) -and
+ ($CurrentState.EnableMailboxIntelligenceProtection -eq $true) -and
+ ($CurrentState.EnableSpoofIntelligence -eq $true) -and
+ ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and
+ ($CurrentState.EnableSimilarUsersSafetyTips -eq $Settings.EnableSimilarUsersSafetyTips) -and
+ ($CurrentState.EnableSimilarDomainsSafetyTips -eq $Settings.EnableSimilarDomainsSafetyTips) -and
+ ($CurrentState.EnableUnusualCharactersSafetyTips -eq $Settings.EnableUnusualCharactersSafetyTips) -and
+ ($CurrentState.EnableUnauthenticatedSender -eq $true) -and
+ ($CurrentState.EnableViaTag -eq $true) -and
+ ($CurrentState.MailboxIntelligenceProtectionAction -eq $Settings.MailboxIntelligenceProtectionAction) -and
+ ($CurrentState.MailboxIntelligenceQuarantineTag -eq $Settings.MailboxIntelligenceQuarantineTag) -and
+ ($CurrentState.TargetedUserProtectionAction -eq $Settings.TargetedUserProtectionAction) -and
+ ($CurrentState.TargetedDomainProtectionAction -eq $Settings.TargetedDomainProtectionAction) -and
+ ($CurrentState.EnableOrganizationDomainsProtection -eq $true)
+
+ $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain'
+
+ $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' |
+ Where-Object -Property Name -EQ "CIPP $PolicyName" |
+ Select-Object Name, AntiPhishPolicy, Priority, RecipientDomainIs
+
+ $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and
+ ($RuleState.AntiPhishPolicy -eq $PolicyName) -and
+ ($RuleState.Priority -eq 0) -and
+ (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name))
+
+ if ($Settings.remediate -eq $true) {
+ if ($StateIsCorrect -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy already correctly configured' -sev Info
+ } else {
+ $cmdparams = @{
+ Enabled = $true
+ PhishThresholdLevel = $Settings.PhishThresholdLevel
+ EnableMailboxIntelligence = $true
+ EnableMailboxIntelligenceProtection = $true
+ EnableSpoofIntelligence = $true
+ EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips
+ EnableSimilarUsersSafetyTips = $Settings.EnableSimilarUsersSafetyTips
+ EnableSimilarDomainsSafetyTips = $Settings.EnableSimilarDomainsSafetyTips
+ EnableUnusualCharactersSafetyTips = $Settings.EnableUnusualCharactersSafetyTips
+ EnableUnauthenticatedSender = $true
+ EnableViaTag = $true
+ MailboxIntelligenceProtectionAction = $Settings.MailboxIntelligenceProtectionAction
+ MailboxIntelligenceQuarantineTag = $Settings.MailboxIntelligenceQuarantineTag
+ TargetedUserProtectionAction = $Settings.TargetedUserProtectionAction
+ TargetedDomainProtectionAction = $Settings.TargetedDomainProtectionAction
+ EnableOrganizationDomainsProtection = $true
+ }
+
+ try {
+ if ($CurrentState.Name -eq $PolicyName) {
+ $cmdparams.Add('Identity', $PolicyName)
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishPolicy' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Anti-phishing Policy' -sev Info
+ } else {
+ $cmdparams.Add('Name', $PolicyName)
+ New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishPolicy' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created Anti-phishing Policy' -sev Info
+ }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing Policy. Error: $ErrorMessage" -sev Error
+ }
+ }
+
+ if ($RuleStateIsCorrect -eq $false) {
+ $cmdparams = @{
+ AntiPhishPolicy = $PolicyName
+ Priority = 0
+ RecipientDomainIs = $AcceptedDomains.Name
+ }
+
+ try {
+ if ($RuleState.Name -eq "CIPP $PolicyName") {
+ $cmdparams.Add('Identity', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated AntiPhish Rule' -sev Info
+ } else {
+ $cmdparams.Add('Name', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created AntiPhish Rule' -sev Info
+ }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create AntiPhish Rule. Error: $ErrorMessage" -sev Error
+ }
+ }
+ }
+
+ if ($Settings.alert -eq $true) {
+
+ if ($StateIsCorrect -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy is enabled' -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing Policy is not enabled' -sev Alert
+ }
+ }
+
+ if ($Settings.report -eq $true) {
+ Add-CIPPBPAField -FieldName 'AntiPhishPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant
+ }
+
+}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1
new file mode 100644
index 000000000000..24d4a7c0ee3b
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1
@@ -0,0 +1,48 @@
+function Invoke-CIPPStandardBookings {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param($Tenant, $Settings)
+
+ # Input validation
+ if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'BookingsEnabled: Invalid state parameter set' -sev Error
+ Exit
+ }
+
+ $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').BookingsEnabled
+ $WantedState = if ($Settings.state -eq 'true') { $true } else { $false }
+ $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false }
+
+ if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
+ if ($StateIsCorrect -eq $false) {
+ try {
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ BookingsEnabled = $WantedState } -useSystemMailbox $true
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant Bookings state to $($Settings.state)" -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant Bookings state to $($Settings.state). Error: $ErrorMessage" -sev Error
+ }
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings state is already set correctly to $($Settings.state)" -sev Info
+ }
+
+ }
+
+ if ($Settings.alert -eq $true) {
+ if ($StateIsCorrect -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings is set correctly to $($Settings.state)" -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings is not set correctly to $($Settings.state)" -sev Alert
+ }
+ }
+
+ if ($Settings.report -eq $true) {
+ # Default is not set, not set means it's enabled
+ if ($null -eq $CurrentState ) { $CurrentState = $true }
+ Add-CIPPBPAField -FieldName 'BookingsState' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant
+ }
+
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1
new file mode 100644
index 000000000000..4994b6cf91c1
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1
@@ -0,0 +1,48 @@
+function Invoke-CIPPStandardCloudMessageRecall {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param($Tenant, $Settings)
+
+ # Input validation
+ if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'MessageRecallEnabled: Invalid state parameter set' -sev Error
+ Exit
+ }
+
+ $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').MessageRecallEnabled
+ $WantedState = if ($Settings.state -eq 'true') { $true } else { $false }
+ $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false }
+
+ if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
+ if ($StateIsCorrect -eq $false) {
+ try {
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ MessageRecallEnabled = $WantedState } -useSystemMailbox $true
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant Message Recall state to $($Settings.state)" -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant Message Recall state to $($Settings.state). Error: $ErrorMessage" -sev Error
+ }
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall state is already set correctly to $($Settings.state)" -sev Info
+ }
+
+ }
+
+ if ($Settings.alert -eq $true) {
+ if ($StateIsCorrect -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall is set correctly to $($Settings.state)" -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall is not set correctly to $($Settings.state)" -sev Alert
+ }
+ }
+
+ if ($Settings.report -eq $true) {
+ # Default is not set, not set means it's enabled
+ if ($null -eq $CurrentState ) { $CurrentState = $true }
+ Add-CIPPBPAField -FieldName 'MessageRecall' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant
+ }
+
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1
index 0407d9b3555e..b8ee94aafe9b 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1
@@ -6,12 +6,13 @@ function Invoke-CIPPStandardDelegateSentItems {
param($Tenant, $Settings)
$Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ RecipientTypeDetails = @('UserMailbox', 'SharedMailbox') } |
Where-Object { $_.MessageCopyForSendOnBehalfEnabled -eq $false -or $_.MessageCopyForSentAsEnabled -eq $false }
-
+ Write-Host "Mailboxes: $($Mailboxes.count)"
If ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
if ($Mailboxes) {
try {
- $Request = $mailboxes | ForEach-Object {
+ $Request = $Mailboxes | ForEach-Object {
@{
CmdletInput = @{
CmdletName = 'Set-Mailbox'
@@ -19,7 +20,7 @@ function Invoke-CIPPStandardDelegateSentItems {
}
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray $Request
+ $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorMessage = Get-NormalizedError -Message $_.error
@@ -27,6 +28,7 @@ function Invoke-CIPPStandardDelegateSentItems {
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Delegate Sent Items Style to $($_.error.target) Error: $ErrorMessage" -sev Error
}
}
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style applied for $($Mailboxes.count - $BatchResults.Error.Count) mailboxes" -sev Info
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Delegate Sent Items Style. Error: $ErrorMessage" -sev Error
@@ -38,7 +40,7 @@ function Invoke-CIPPStandardDelegateSentItems {
}
if ($Settings.alert -eq $true) {
if ($Mailboxes) {
- Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style is not enabled for $($mailboxes.count) mailboxes" -sev Alert
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style is not enabled for $($Mailboxes.count) mailboxes" -sev Alert
} else {
Write-LogMessage -API 'Standards' -tenant $tenant -message 'Delegate Sent Items Style is enabled' -sev Info
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1
index a7d8bd090172..b5741d27ac4d 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1
@@ -7,6 +7,7 @@ function Invoke-CIPPStandardEnableCustomerLockbox {
$CustomerLockboxStatus = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').CustomerLockboxEnabled
if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
try {
if ($CustomerLockboxStatus) {
@@ -17,7 +18,11 @@ function Invoke-CIPPStandardEnableCustomerLockbox {
}
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Customer Lockbox. Error: $ErrorMessage" -sev Error
+ if ($ErrorMessage -match 'Ex5E8EA4') {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Customer Lockbox. E5 license required. Error: $ErrorMessage" -sev Error
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Customer Lockbox. Error: $ErrorMessage" -sev Error
+ }
}
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1
index 516af7e005ed..05ab9cfbd117 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1
@@ -14,7 +14,7 @@ function Invoke-CIPPStandardEnableMailTips {
Write-LogMessage -API 'Standards' -tenant $Tenant -message 'All MailTips are already enabled.' -sev Info
} else {
try {
- New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdparams @{ MailTipsAllTipsEnabled = $true; MailTipsExternalRecipientsTipsEnabled = $true; MailTipsGroupMetricsEnabled = $true; MailTipsLargeAudienceThreshold = $Settings.MailTipsLargeAudienceThreshold }
+ New-ExoRequest -useSystemMailbox $true -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdparams @{ MailTipsAllTipsEnabled = $true; MailTipsExternalRecipientsTipsEnabled = $true; MailTipsGroupMetricsEnabled = $true; MailTipsLargeAudienceThreshold = $Settings.MailTipsLargeAudienceThreshold }
Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Enabled all MailTips' -sev Info
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1
index 460569529242..9181ae888e66 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1
@@ -32,7 +32,7 @@ function Invoke-CIPPStandardEnableMailboxAuditing {
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray $Request
+ $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorMessage = Get-NormalizedError -Message $_.error
@@ -53,7 +53,7 @@ function Invoke-CIPPStandardEnableMailboxAuditing {
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray $Request
+ $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorMessage = Get-NormalizedError -Message $_.error
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1
index 92e387dc07ef..3c3dbd004c45 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1
@@ -26,7 +26,7 @@ function Invoke-CIPPStandardEnableOnlineArchiving {
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray $Request
+ $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorMessage = Get-NormalizedError -Message $_.error
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1
new file mode 100644
index 000000000000..56d5c8a1815e
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1
@@ -0,0 +1,52 @@
+function Invoke-CIPPStandardEnablePronouns {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param ($Tenant, $Settings)
+
+ $Uri = 'https://graph.microsoft.com/v1.0/admin/people/pronouns'
+ try {
+ $CurrentState = New-GraphGetRequest -Uri $Uri -tenantid $Tenant
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not get CurrentState for Pronouns. Error: $ErrorMessage" -sev Error
+ Exit
+ }
+ Write-Host $CurrentState
+
+ if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
+
+ if ($CurrentState.isEnabledInOrganization -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Pronouns are already enabled.' -sev Info
+ } else {
+ $CurrentState.isEnabledInOrganization = $true
+ try {
+ $Body = ConvertTo-Json -InputObject $CurrentState -Depth 10 -Compress
+ New-GraphPostRequest -Uri $Uri -tenantid $Tenant -Body $Body -type PATCH
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled pronouns.' -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable pronouns. Error: $ErrorMessage" -sev Error
+ }
+ }
+ }
+
+ if ($Settings.alert -eq $true) {
+
+ if ($CurrentState.isEnabledInOrganization -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Pronouns are enabled.' -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Pronouns are not enabled.' -sev Alert
+ }
+
+ }
+
+ if ($Settings.report -eq $true) {
+
+ Add-CIPPBPAField -FieldName 'PronounsEnabled' -FieldValue $CurrentState.isEnabledInOrganization -StoreAs bool -Tenant $tenant
+
+ }
+
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1
index 5a78adfa373a..9263b386bb23 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1
@@ -60,7 +60,7 @@ function Invoke-CIPPStandardIntuneTemplate {
$DeleteJson.added = @()
$DeleteJson = ConvertTo-Json -Depth 10 -InputObject $DeleteJson
$DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $DeleteJson
- $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($Displayname) to template defaults" -Sev 'info'
} else {
@@ -98,6 +98,19 @@ function Invoke-CIPPStandardIntuneTemplate {
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info'
}
}
+ 'windowsDriverUpdateProfiles' {
+ $TemplateTypeURL = 'windowsDriverUpdateProfiles'
+ $PolicyName = ($RawJSON | ConvertFrom-Json).Name
+ $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant
+ if ($PolicyName -in $CheckExististing.name) {
+ $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON
+
+ } else {
+ $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON
+ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info'
+ }
+ }
}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1
index 178c5b048861..d9ae65ac222f 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1
@@ -9,11 +9,12 @@ function Invoke-CIPPStandardMalwareFilterPolicy {
$CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterPolicy' |
Where-Object -Property Name -EQ $PolicyName |
- Select-Object Name, EnableFileFilter, FileTypeAction, ZapEnabled, QuarantineTag, EnableInternalSenderAdminNotifications, InternalSenderAdminAddress, EnableExternalSenderAdminNotifications, ExternalSenderAdminAddress
+ Select-Object Name, EnableFileFilter, FileTypeAction, FileTypes, ZapEnabled, QuarantineTag, EnableInternalSenderAdminNotifications, InternalSenderAdminAddress, EnableExternalSenderAdminNotifications, ExternalSenderAdminAddress
$StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and
($CurrentState.EnableFileFilter -eq $true) -and
($CurrentState.FileTypeAction -eq $Settings.FileTypeAction) -and
+ ($null -ne $CurrentState.FileTypes) -and
($CurrentState.ZapEnabled -eq $true) -and
($CurrentState.QuarantineTag -eq $Settings.QuarantineTag) -and
($CurrentState.EnableInternalSenderAdminNotifications -eq $Settings.EnableInternalSenderAdminNotifications) -and
@@ -21,6 +22,17 @@ function Invoke-CIPPStandardMalwareFilterPolicy {
($CurrentState.EnableExternalSenderAdminNotifications -eq $Settings.EnableExternalSenderAdminNotifications) -and
(($null -eq $Settings.ExternalSenderAdminAddress) -or ($CurrentState.ExternalSenderAdminAddress -eq $Settings.ExternalSenderAdminAddress))
+ $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain'
+
+ $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' |
+ Where-Object -Property Name -EQ "CIPP $PolicyName" |
+ Select-Object Name, MalwareFilterPolicy, Priority, RecipientDomainIs
+
+ $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and
+ ($RuleState.MalwareFilterPolicy -eq $PolicyName) -and
+ ($RuleState.Priority -eq 0) -and
+ (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name))
+
if ($Settings.remediate -eq $true) {
if ($StateIsCorrect -eq $true) {
@@ -37,6 +49,12 @@ function Invoke-CIPPStandardMalwareFilterPolicy {
ExternalSenderAdminAddress = $Settings.ExternalSenderAdminAddress
}
+ if ($null -eq $CurrentState.FileTypes) {
+ $cmdparams.Add('FileTypes', @('ace', 'ani', 'apk', 'app', 'appx', 'arj', 'bat', 'cab', 'cmd', 'com', 'deb', 'dex', 'dll', 'docm', 'elf', 'exe', 'hta', 'img', 'iso', 'jar', 'jnlp', 'kext', 'lha', 'lib', 'library', 'lnk', 'lzh', 'macho', 'msc', 'msi', 'msix', 'msp', 'mst', 'pif', 'ppa', 'ppam', 'reg', 'rev', 'scf', 'scr', 'sct', 'sys', 'uif', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', 'xll', 'xz', 'z'))
+ } else {
+ $cmdparams.Add('FileTypes', $CurrentState.FileTypes)
+ }
+
try {
if ($CurrentState.Name -eq $PolicyName) {
$cmdparams.Add('Identity', $PolicyName)
@@ -52,6 +70,29 @@ function Invoke-CIPPStandardMalwareFilterPolicy {
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter Policy. Error: $ErrorMessage" -sev Error
}
}
+
+ if ($RuleStateIsCorrect -eq $false) {
+ $cmdparams = @{
+ MalwareFilterPolicy = $PolicyName
+ Priority = 0
+ RecipientDomainIs = $AcceptedDomains.Name
+ }
+
+ try {
+ if ($RuleState.Name -eq "CIPP $PolicyName") {
+ $cmdparams.Add('Identity', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Malware Filter Rule' -sev Info
+ } else {
+ $cmdparams.Add('Name', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'New-MalwareFilterRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created Malware Filter Rule' -sev Info
+ }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter Rule. Error: $ErrorMessage" -sev Error
+ }
+ }
}
if ($Settings.alert -eq $true) {
@@ -67,4 +108,4 @@ function Invoke-CIPPStandardMalwareFilterPolicy {
Add-CIPPBPAField -FieldName 'MalwareFilterPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant
}
-}
\ No newline at end of file
+}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1
index 473a75ab15c7..e3c7d190e072 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1
@@ -8,7 +8,7 @@ function Invoke-CIPPStandardNudgeMFA {
$State = if ($CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq 'enabled') { $true } else { $false }
If ($Settings.remediate -eq $true) {
-
+ $StateName = $Settings.state.Substring(0, 1).ToUpper() + $Settings.state.Substring(1)
if ($Settings.state -ne $CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -or $Settings.snoozeDurationInDays -ne $CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays) {
try {
$Body = $CurrentInfo
@@ -17,12 +17,12 @@ function Invoke-CIPPStandardNudgeMFA {
$body = ConvertTo-Json -Depth 10 -InputObject ($body | Select-Object registrationEnforcement)
New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -Type patch -Body $body -ContentType 'application/json'
- Write-LogMessage -API 'Standards' -tenant $tenant -message "$($Settings.state) Authenticator App Nudge with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "$StateName Authenticator App Nudge with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info
$CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state = $Settings.state
$CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays = $Settings.snoozeDurationInDays
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
- Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to $($Settings.state) Authenticator App Nudge: $ErrorMessage" -sev Error
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set Authenticator App Nudge to $($Settings.state): $ErrorMessage" -sev Error
}
} else {
Write-LogMessage -API 'Standards' -tenant $tenant -message "Authenticator App Nudge is already set to $($Settings.state) with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1
index 235feac18ab3..d62e02a3a223 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1
@@ -8,9 +8,9 @@ function Invoke-CIPPStandardOauthConsent {
$StateIsCorrect = if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -eq 'managePermissionGrantsForSelf.cipp-consent-policy') { $true } else { $false }
If ($Settings.remediate -eq $true) {
- $AllowedAppIdsForTenant = $Settings.AllowedApps -split ','
+ $AllowedAppIdsForTenant = $settings.AllowedApps -split ','
try {
- if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('ManagePermissionGrantsForSelf.cipp-1sent-policy')) {
+ if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.cipp-consent-policy')) {
$Existing = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/' -tenantid $tenant) | Where-Object -Property id -EQ 'cipp-consent-policy'
if (!$Existing) {
New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies' -Type POST -Body '{ "id":"cipp-consent-policy", "displayName":"Application Consent Policy", "description":"This policy controls the current application consent policies."}' -ContentType 'application/json'
@@ -27,9 +27,7 @@ function Invoke-CIPPStandardOauthConsent {
}
New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.cipp-consent-policy"]}' -ContentType 'application/json'
}
- if ($AllowedAppIdsForTenant) {
- }
-
+
Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode has been enabled.' -sev Info
} catch {
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1
new file mode 100644
index 000000000000..c83204529423
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1
@@ -0,0 +1,41 @@
+function Invoke-CIPPStandardPerUserMFA {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param($Tenant, $Settings)
+
+ $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=UserPrincipalName,accountEnabled" -scope 'https://graph.microsoft.com/.default' -tenantid $Tenant | Where-Object { $_.AccountEnabled -EQ $true }
+ $int = 0
+ $Requests = foreach ($id in $GraphRequest.userPrincipalName) {
+ @{
+ id = $int++
+ method = 'GET'
+ url = "/users/$id/authentication/requirements"
+ }
+ }
+ $UsersWithoutMFA = (New-GraphBulkRequest -tenantid $tenant -scope 'https://graph.microsoft.com/.default' -Requests @($Requests) -asapp $true).body | Where-Object { $_.perUserMfaState -ne 'enforced' } | Select-Object peruserMFAState, @{Name = 'UserPrincipalName'; Expression = { [System.Web.HttpUtility]::UrlDecode($_.'@odata.context'.split("'")[1]) } }
+
+ If ($Settings.remediate -eq $true) {
+ if ($UsersWithoutMFA) {
+ try {
+ $MFAMessage = Set-CIPPPeruserMFA -TenantFilter $Tenant -UserId $UsersWithoutMFA.UserPrincipalName -State 'enforced'
+ Write-LogMessage -API 'Standards' -tenant $tenant -message $MFAMessage -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enforce MFA for all users: $ErrorMessage" -sev Error
+ }
+ }
+ }
+ if ($Settings.alert -eq $true) {
+
+ if ($UsersWithoutMFA) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The following accounts do not have Legacy MFA Enforced: $($UsersWithoutMFA.UserPrincipalName -join ', ')" -sev Alert
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'No accounts do not have legacy per user MFA Enforced' -sev Info
+ }
+ }
+ if ($Settings.report -eq $true) {
+ Add-CIPPBPAField -FieldName 'LegacyMFAUsers' -FieldValue $UsersWithoutMFA -StoreAs json -Tenant $tenant
+ }
+}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1
index 24d6c424d036..1973cb4efc10 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1
@@ -17,6 +17,17 @@ function Invoke-CIPPStandardSafeAttachmentPolicy {
($CurrentState.Redirect -eq $Settings.Redirect) -and
(($null -eq $Settings.RedirectAddress) -or ($CurrentState.RedirectAddress -eq $Settings.RedirectAddress))
+ $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain'
+
+ $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' |
+ Where-Object -Property Name -EQ "CIPP $PolicyName" |
+ Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs
+
+ $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and
+ ($RuleState.SafeAttachmentPolicy -eq $PolicyName) -and
+ ($RuleState.Priority -eq 0) -and
+ (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name))
+
if ($Settings.remediate -eq $true) {
if ($StateIsCorrect -eq $true) {
@@ -44,6 +55,29 @@ function Invoke-CIPPStandardSafeAttachmentPolicy {
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment Policy. Error: $ErrorMessage" -sev Error
}
}
+
+ if ($RuleStateIsCorrect -eq $false) {
+ $cmdparams = @{
+ SafeAttachmentPolicy = $PolicyName
+ Priority = 0
+ RecipientDomainIs = $AcceptedDomains.Name
+ }
+
+ try {
+ if ($RuleState.Name -eq "CIPP $PolicyName") {
+ $cmdparams.Add('Identity', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated SafeAttachment Rule' -sev Info
+ } else {
+ $cmdparams.Add('Name', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeAttachmentRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created SafeAttachment Rule' -sev Info
+ }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeAttachment Rule. Error: $ErrorMessage" -sev Error
+ }
+ }
}
if ($Settings.alert -eq $true) {
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1
index 65471148d7c8..bd353b32e485 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1
@@ -23,6 +23,17 @@ function Invoke-CIPPStandardSafeLinksPolicy {
($CurrentState.DisableUrlRewrite -eq $Settings.DisableUrlRewrite) -and
($CurrentState.EnableOrganizationBranding -eq $Settings.EnableOrganizationBranding)
+ $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain'
+
+ $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' |
+ Where-Object -Property Name -EQ "CIPP $PolicyName" |
+ Select-Object Name, SafeLinksPolicy, Priority, RecipientDomainIs
+
+ $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and
+ ($RuleState.SafeLinksPolicy -eq $PolicyName) -and
+ ($RuleState.Priority -eq 0) -and
+ (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name))
+
if ($Settings.remediate -eq $true) {
if ($StateIsCorrect -eq $true) {
@@ -56,6 +67,29 @@ function Invoke-CIPPStandardSafeLinksPolicy {
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink Policy. Error: $ErrorMessage" -sev Error
}
}
+
+ if ($RuleStateIsCorrect -eq $false) {
+ $cmdparams = @{
+ SafeLinksPolicy = $PolicyName
+ Priority = 0
+ RecipientDomainIs = $AcceptedDomains.Name
+ }
+
+ try {
+ if ($RuleState.Name -eq "CIPP $PolicyName") {
+ $cmdparams.Add('Identity', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated SafeLink Rule' -sev Info
+ } else {
+ $cmdparams.Add('Name', "CIPP $PolicyName")
+ New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeLinksRule' -cmdparams $cmdparams
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Created SafeLink Rule' -sev Info
+ }
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink Rule. Error: $ErrorMessage" -sev Error
+ }
+ }
}
if ($Settings.alert -eq $true) {
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1
index 4f01cbc8b55f..d70fe30cef99 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1
@@ -20,7 +20,7 @@ function Invoke-CIPPStandardSafeSendersDisable {
}
}
- $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray $Request
+ $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
$BatchResults | ForEach-Object {
if ($_.error) {
$ErrorMessage = Get-NormalizedError -Message $_.error
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1
new file mode 100644
index 000000000000..4946b64e8b4b
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1
@@ -0,0 +1,57 @@
+function Invoke-CIPPStandardShortenMeetings {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param($Tenant, $Settings)
+
+ # Input validation
+ if ([Int32]$Settings.DefaultMinutesToReduceShortEventsBy -lt 0 -or [Int32]$Settings.DefaultMinutesToReduceShortEventsBy -gt 29) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Invalid shorten meetings settings specified. DefaultMinutesToReduceShortEventsBy must be an integer between 0 and 29' -sev Error
+ Exit
+ }
+ if ([Int32]$Settings.DefaultMinutesToReduceLongEventsBy -lt 0 -or [Int32]$Settings.DefaultMinutesToReduceLongEventsBy -gt 29) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Invalid shorten meetings settings specified. DefaultMinutesToReduceLongEventsBy must be an integer between 0 and 29' -sev Error
+ Exit
+ }
+
+ $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' |
+ Select-Object -Property ShortenEventScopeDefault, DefaultMinutesToReduceShortEventsBy, DefaultMinutesToReduceLongEventsBy
+ $CorrectState = if ($CurrentState.ShortenEventScopeDefault -eq $Settings.ShortenEventScopeDefault -and
+ $CurrentState.DefaultMinutesToReduceShortEventsBy -eq $Settings.DefaultMinutesToReduceShortEventsBy -and
+ $CurrentState.DefaultMinutesToReduceLongEventsBy -eq $Settings.DefaultMinutesToReduceLongEventsBy) { $true } else { $false }
+
+ if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
+
+ if ($CorrectState -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'Shorten meetings settings are already in the correct state. ' -sev Info
+ } else {
+ try {
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ShortenEventScopeDefault = $Settings.ShortenEventScopeDefault; DefaultMinutesToReduceShortEventsBy = $Settings.DefaultMinutesToReduceShortEventsBy; DefaultMinutesToReduceLongEventsBy = $Settings.DefaultMinutesToReduceLongEventsBy }
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings have been set to the following state. State: $($Settings.ShortenEventScopeDefault), Short:$($Settings.DefaultMinutesToReduceShortEventsBy), Long: $($Settings.DefaultMinutesToReduceLongEventsBy)" -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set shorten meetings settings. Error: $ErrorMessage" -sev Error
+ }
+ }
+ }
+
+ if ($Settings.alert -eq $true) {
+
+ if ($CorrectState -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings are already in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings are not in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Alert
+ }
+ }
+
+ if ($Settings.report -eq $true) {
+
+ if ($CorrectState -eq $true) {
+ Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CorrectState -StoreAs bool -Tenant $tenant
+ } else {
+ Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CurrentState -StoreAs json -Tenant $tenant
+ }
+ }
+}
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1
new file mode 100644
index 000000000000..86509c52564b
--- /dev/null
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1
@@ -0,0 +1,48 @@
+function Invoke-CIPPStandardTeamsMeetingsByDefault {
+ <#
+ .FUNCTIONALITY
+ Internal
+ #>
+ param($Tenant, $Settings)
+
+ # Input validation
+ if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message 'TeamsMeetingsByDefault: Invalid state parameter set' -sev Error
+ Exit
+ }
+
+ $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').OnlineMeetingsByDefaultEnabled
+ $WantedState = if ($Settings.state -eq 'true') { $true } else { $false }
+ $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false }
+
+ if ($Settings.remediate -eq $true) {
+ Write-Host 'Time to remediate'
+ if ($StateIsCorrect -eq $false) {
+ try {
+ New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ OnlineMeetingsByDefaultEnabled = $WantedState } -useSystemMailbox $true
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant TeamsMeetingsByDefault state to $($Settings.state)" -sev Info
+ } catch {
+ $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant TeamsMeetingsByDefault state to $($Settings.state). Error: $ErrorMessage" -sev Error
+ }
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault state is already set correctly to $($Settings.state)" -sev Info
+ }
+
+ }
+
+ if ($Settings.alert -eq $true) {
+ if ($StateIsCorrect -eq $true) {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault is set correctly to $($Settings.state)" -sev Info
+ } else {
+ Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault is not set correctly to $($Settings.state)" -sev Alert
+ }
+ }
+
+ if ($Settings.report -eq $true) {
+ # Default is not set, not set means it's enabled
+ if ($null -eq $CurrentState ) { $CurrentState = $true }
+ Add-CIPPBPAField -FieldName 'TeamsMeetingsByDefault' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant
+ }
+
+}
\ No newline at end of file
diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1
index 83372682cbac..c0c6e0d17db3 100644
--- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1
+++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1
@@ -18,11 +18,11 @@ function Invoke-CIPPStandardTransportRuleTemplate {
if ($Existing) {
Write-Host 'Found existing'
$RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity
- $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications) -useSystemMailbox $true
+ $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true
Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set transport rule for $tenant" -sev 'Info'
} else {
Write-Host 'Creating new'
- $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications) -useSystemMailbox $true
+ $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true
Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully created transport rule for $tenant" -sev 'Info'
}
diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1
index 014218b3cc16..842b4f4b66aa 100644
--- a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1
+++ b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1
@@ -22,9 +22,6 @@ function Test-CIPPAccessTenant {
$Tenants = ($TenantCSV).split(',')
if (!$Tenants) { $results = 'Could not load the tenants list from cache. Please run permissions check first, or visit the tenants page.' }
$TenantList = Get-Tenants
- $TenantIds = foreach ($Tenant in $Tenants) {
- ($TenantList | Where-Object { $_.defaultDomainName -eq $Tenant }).customerId
- }
$results = foreach ($tenant in $Tenants) {
$AddedText = ''
@@ -32,9 +29,9 @@ function Test-CIPPAccessTenant {
$TenantId = ($TenantList | Where-Object { $_.defaultDomainName -eq $tenant }).customerId
$BulkRequests = $ExpectedRoles | ForEach-Object { @(
@{
- id = "roleManagement_$($_.id)"
+ id = "roleManagement_$($_.Id)"
method = 'GET'
- url = "roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($_.id)'&`$expand=principal"
+ url = "roleManagement/directory/roleAssignments?`$filter=roleDefinitionId eq '$($_.Id)'&`$expand=principal"
}
)
}
diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1
index 800fd3618526..994dab0633bf 100644
--- a/Modules/CippEntrypoints/CippEntrypoints.psm1
+++ b/Modules/CippEntrypoints/CippEntrypoints.psm1
@@ -1,20 +1,44 @@
using namespace System.Net
function Receive-CippHttpTrigger {
- Param($Request, $TriggerMetadata)
- #force path to CIPP-API
- Set-Location (Get-Item $PSScriptRoot).Parent.Parent.FullName
- Write-Information (Get-Item $PSScriptRoot).Parent.Parent.FullName
- $APIName = $TriggerMetadata.FunctionName
+ <#
+ .FUNCTIONALITY
+ Entrypoint
+ #>
+ Param(
+ $Request,
+ $TriggerMetadata
+ )
- $FunctionName = 'Invoke-{0}' -f $APIName
+ Set-Location (Get-Item $PSScriptRoot).Parent.Parent.FullName
+ $FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint
+ Write-Host "Function: $($Request.Params.CIPPEndpoint)"
$HttpTrigger = @{
Request = $Request
TriggerMetadata = $TriggerMetadata
}
- & $FunctionName @HttpTrigger
+ if (Get-Command -Name $FunctionName -ErrorAction SilentlyContinue) {
+ try {
+ $Access = Test-CIPPAccess -Request $Request
+ Write-Information "Access: $Access"
+ if ($Access) {
+ & $FunctionName @HttpTrigger
+ }
+ } catch {
+ Write-Information $_.Exception.Message
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::Forbidden
+ Body = $_.Exception.Message
+ })
+ }
+ } else {
+ Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
+ StatusCode = [HttpStatusCode]::NotFound
+ Body = 'Endpoint not found'
+ })
+ }
}
function Receive-CippQueueTrigger {
diff --git a/Modules/CippExtensions/NinjaOne/Get-NinjaOneOrgMapping.ps1 b/Modules/CippExtensions/NinjaOne/Get-NinjaOneOrgMapping.ps1
index 8f9e3d89936b..a0274cb0d16f 100644
--- a/Modules/CippExtensions/NinjaOne/Get-NinjaOneOrgMapping.ps1
+++ b/Modules/CippExtensions/NinjaOne/Get-NinjaOneOrgMapping.ps1
@@ -13,14 +13,14 @@ function Get-NinjaOneOrgMapping {
$Mappings | Add-Member -NotePropertyName $_.RowKey -NotePropertyValue @{ label = "$($_.NinjaOneName)"; value = "$($_.NinjaOne)" }
}
#Get Available Tenants
-
+
#Get available Ninja clients
$Table = Get-CIPPTable -TableName Extensionsconfig
$Configuration = ((Get-AzDataTableEntity @Table).config | ConvertFrom-Json -ea stop).NinjaOne
-
-
+
+
$Token = Get-NinjaOneToken -configuration $Configuration
-
+
$After = 0
$PageSize = 1000
$NinjaOrgs = do {
@@ -29,16 +29,16 @@ function Get-NinjaOneOrgMapping {
$ResultCount = ($Result.id | Measure-Object -Maximum)
$After = $ResultCount.maximum
- } while ($ResultCount.count -eq $PageSize)
-
+ } while ($ResultCount.count -eq $PageSize)
+
} catch {
$Message = if ($_.ErrorDetails.Message) {
Get-NormalizedError -Message $_.ErrorDetails.Message
} else {
$_.Exception.message
}
-
- $NinjaOrgs = @(@{ name = $Message })
+
+ $NinjaOrgs = @(@{ name = 'Could not get NinjaOne Orgs, check your API credentials and try again.'; value = '-1' })
}
$MappingObj = [PSCustomObject]@{
diff --git a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1 b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1
index ebf491cec05a..9828682c6348 100644
--- a/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1
+++ b/Modules/CippExtensions/NinjaOne/Invoke-NinjaOneTenantSync.ps1
@@ -267,7 +267,7 @@ function Invoke-NinjaOneTenantSync {
@{
id = 'Users'
method = 'GET'
- url = '/users'
+ url = '/users?$top=999'
},
@{
id = 'TenantDetails'
@@ -292,7 +292,7 @@ function Invoke-NinjaOneTenantSync {
@{
id = 'Devices'
method = 'GET'
- url = '/deviceManagement/managedDevices'
+ url = '/deviceManagement/managedDevices?$top=999'
},
@{
id = 'DeviceCompliancePolicies'
@@ -317,12 +317,12 @@ function Invoke-NinjaOneTenantSync {
@{
id = 'SecureScore'
method = 'GET'
- url = '/security/secureScores'
+ url = '/security/secureScores?$top=999'
},
@{
id = 'SecureScoreControlProfiles'
method = 'GET'
- url = '/security/secureScoreControlProfiles'
+ url = '/security/secureScoreControlProfiles?$top=999'
},
@{
id = 'Subscriptions'
diff --git a/Modules/CippExtensions/Private/Get-HaloMapping.ps1 b/Modules/CippExtensions/Private/Get-HaloMapping.ps1
index 8391252ae065..fcae99cfd5d1 100644
--- a/Modules/CippExtensions/Private/Get-HaloMapping.ps1
+++ b/Modules/CippExtensions/Private/Get-HaloMapping.ps1
@@ -32,7 +32,7 @@ function Get-HaloMapping {
}
Write-LogMessage -Message "Could not get HaloPSA Clients, error: $Message " -Level Error -tenant 'CIPP' -API 'HaloMapping'
- $RawHaloClients = @(@{name = "Could not get HaloPSA Clients, error: $Message" })
+ $RawHaloClients = @(@{name = "Could not get HaloPSA Clients, error: $Message"; value = '-1' })
}
$HaloClients = $RawHaloClients | ForEach-Object {
[PSCustomObject]@{
diff --git a/Modules/CippExtensions/Private/Set-PwPushConfig.ps1 b/Modules/CippExtensions/Private/Set-PwPushConfig.ps1
new file mode 100644
index 000000000000..d43ffa888575
--- /dev/null
+++ b/Modules/CippExtensions/Private/Set-PwPushConfig.ps1
@@ -0,0 +1,23 @@
+function Set-PwPushConfig {
+ param(
+ $Configuration
+ )
+ $InitParams = @{}
+ if ($Configuration.BaseUrl) {
+ $InitParams.BaseUrl = $Configuration.BaseUrl
+ }
+ if ($Configuration.EmailAddress) {
+ if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') {
+ $DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets'
+ $ApiKey = (Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'PWPush' and RowKey eq 'PWPush'").APIKey
+ } else {
+ $null = Connect-AzAccount -Identity
+ $ApiKey = Get-AzKeyVaultSecret -VaultName $ENV:WEBSITE_DEPLOYMENT_ID -Name 'PWPush' -AsPlainText
+ }
+ if ($ApiKey) {
+ $InitParams.APIKey = $ApiKey
+ $InitParams.EmailAddress = $Configuration.EmailAddress
+ }
+ }
+ Initialize-PassPushPosh @InitParams
+}
\ No newline at end of file
diff --git a/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1 b/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1
index 2a0e718402f4..242d4dd86390 100644
--- a/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1
+++ b/Modules/CippExtensions/Public/Get-ExtensionRateLimit.ps1
@@ -24,7 +24,6 @@ function Get-ExtensionRateLimit($ExtensionName, $ExtensionPartitionKey, $RateLim
}
if (($ActiveJobs | Measure-Object).count -ge $RateLimit) {
Write-Host "Rate Limiting. Currently $($ActiveJobs.count) Active Jobs"
- Start-Sleep -Seconds $WaitTime
$CurrentMap = Get-ExtensionRateLimit -ExtensionName $ExtensionName -ExtensionPartitionKey $ExtensionPartitionKey -RateLimit $RateLimit -WaitTime $WaitTime
}
diff --git a/Modules/CippExtensions/Public/New-PwPushLink.ps1 b/Modules/CippExtensions/Public/New-PwPushLink.ps1
new file mode 100644
index 000000000000..a8739f39c9b6
--- /dev/null
+++ b/Modules/CippExtensions/Public/New-PwPushLink.ps1
@@ -0,0 +1,24 @@
+function New-PwPushLink {
+ [CmdletBinding()]
+ Param(
+ $Payload
+ )
+ $Table = Get-CIPPTable -TableName Extensionsconfig
+ $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).PWPush
+ if ($Configuration.Enabled) {
+ Set-PwPushConfig -Configuration $Configuration
+ $PushParams = @{
+ Payload = $Payload
+ }
+ if ($Configuration.ExpireAfterDays) { $PushParams.ExpireAfterDays = $Configuration.ExpireAfterDays }
+ if ($Configuration.ExpireAfterViews) { $PushParams.ExpireAfterViews = $Configuration.ExpireAfterViews }
+ if ($Configuration.DeletableByViewer) { $PushParams.DeletableByViewer = $Configuration.DeletableByViewer }
+ $Link = New-Push @PushParams | Select-Object Link, LinkRetrievalStep
+ if ($Configuration.RetrievalStep) {
+ $Link.Link = $Link.LinkRetrievalStep
+ }
+ $Link | Select-Object -ExpandProperty Link
+ } else {
+ return $false
+ }
+}
\ No newline at end of file
diff --git a/Modules/PassPushPosh/0.2.3/PSGetModuleInfo.xml b/Modules/PassPushPosh/0.2.3/PSGetModuleInfo.xml
new file mode 100644
index 000000000000..00cc59d45a7d
--- /dev/null
+++ b/Modules/PassPushPosh/0.2.3/PSGetModuleInfo.xml
@@ -0,0 +1,142 @@
+
+
+
+ Microsoft.PowerShell.Commands.PSRepositoryItemInfo
+ System.Management.Automation.PSCustomObject
+ System.Object
+
+
+ PassPushPosh
+ 0.2.3
+ Module
+ *PassPushPosh* is a PowerShell Module for interfacing with the Password Pusher secure password / string sharing application, primarily through pwpush.com. It supports creating, retrieving, and deleting anonymous and authenticated pushes, links in any supported language, and getting Push and Dashboard data for authenticated users._x000D__x000A__x000D__x000A_Cmdlets provide clear responses to errors, support additional messaging via -Debug and -Verbose, transaction testing via -Whatif and -Confirm, and in general try to be as "Powershell-y" as possible.
+ Adam Burley
+ AdamBurley
+ Adam Burley, 2022
+ 2023-03-05T00:10:36-05:00
+
+
+ https://www.gnu.org/licenses/gpl-3.0.en.html
+ https://github.com/adamburley/PassPushPosh
+
+
+
+ System.Object[]
+ System.Array
+ System.Object
+
+
+ PSEdition_Desktop
+ PSEdition_Core
+ Windows
+ Linux
+ MacOS
+ Password
+ PSModule
+
+
+
+
+ System.Collections.Hashtable
+ System.Object
+
+
+
+ DscResource
+
+
+
+
+
+
+ Cmdlet
+
+
+
+ Function
+
+
+
+ ConvertTo-PasswordPush
+ Get-Dashboard
+ Get-Push
+ Get-PushAuditLog
+ Get-SecretLink
+ Initialize-PassPushPosh
+ New-PasswordPush
+ New-Push
+ Remove-Push
+
+
+
+
+ Workflow
+
+
+
+ RoleCapability
+
+
+
+ Command
+
+
+
+ ConvertTo-PasswordPush
+ Get-Dashboard
+ Get-Push
+ Get-PushAuditLog
+ Get-SecretLink
+ Initialize-PassPushPosh
+ New-PasswordPush
+ New-Push
+ Remove-Push
+
+
+
+
+
+
+ 0.2.3 - Bug fixing in New-Push. See PR #1_x000D__x000A_ 0.2.2 - Fixed issue with Get-Dashboard returning error referencing -JsonIsArray parameter_x000D__x000A_ General - Module is generally functional but has not been extensively bug-tested. Reccomend not implementing into a production environment at this time.
+
+
+
+
+ https://www.powershellgallery.com/api/v2
+ PSGallery
+ NuGet
+
+
+ System.Management.Automation.PSCustomObject
+ System.Object
+
+
+ Adam Burley, 2022
+ *PassPushPosh* is a PowerShell Module for interfacing with the Password Pusher secure password / string sharing application, primarily through pwpush.com. It supports creating, retrieving, and deleting anonymous and authenticated pushes, links in any supported language, and getting Push and Dashboard data for authenticated users._x000D__x000A__x000D__x000A_Cmdlets provide clear responses to errors, support additional messaging via -Debug and -Verbose, transaction testing via -Whatif and -Confirm, and in general try to be as "Powershell-y" as possible.
+ False
+ 0.2.3 - Bug fixing in New-Push. See PR #1_x000D__x000A_ 0.2.2 - Fixed issue with Get-Dashboard returning error referencing -JsonIsArray parameter_x000D__x000A_ General - Module is generally functional but has not been extensively bug-tested. Reccomend not implementing into a production environment at this time.
+ True
+ True
+ 44
+ 76
+ 15168
+ 3/5/2023 12:10:36 AM -05:00
+ 3/5/2023 12:10:36 AM -05:00
+ 5/23/2024 10:57:25 AM -04:00
+ PSEdition_Desktop PSEdition_Core Windows Linux MacOS Password PSModule PSFunction_ConvertTo-PasswordPush PSCommand_ConvertTo-PasswordPush PSFunction_Get-Dashboard PSCommand_Get-Dashboard PSFunction_Get-Push PSCommand_Get-Push PSFunction_Get-PushAuditLog PSCommand_Get-PushAuditLog PSFunction_Get-SecretLink PSCommand_Get-SecretLink PSFunction_Initialize-PassPushPosh PSCommand_Initialize-PassPushPosh PSFunction_New-PasswordPush PSCommand_New-PasswordPush PSFunction_New-Push PSCommand_New-Push PSFunction_Remove-Push PSCommand_Remove-Push PSIncludes_Function
+ False
+ 2024-05-23T10:57:25Z
+ 0.2.3
+ Adam Burley
+ false
+ Module
+ PassPushPosh.nuspec|PassPushPosh.psd1|PassPushPosh.psm1
+ 5d8a1afd-a912-440f-a9b9-e79f42a05f21
+ 5.1
+ Burley.dev
+
+
+ C:\GitHub\CIPP Workspace\CIPP-API\Modules\PassPushPosh\0.2.3
+
+
+
diff --git a/Modules/PassPushPosh/0.2.3/PassPushPosh.psd1 b/Modules/PassPushPosh/0.2.3/PassPushPosh.psd1
new file mode 100644
index 000000000000..1c911df9d9de
--- /dev/null
+++ b/Modules/PassPushPosh/0.2.3/PassPushPosh.psd1
@@ -0,0 +1,140 @@
+#
+# Module manifest for module 'PassPushPosh'
+#
+# Generated by: Adam Burley
+#
+# Generated on: 3/4/2023
+#
+
+@{
+
+# Script module or binary module file associated with this manifest.
+RootModule = 'PassPushPosh.psm1'
+
+# Version number of this module.
+ModuleVersion = '0.2.3'
+
+# Supported PSEditions
+# CompatiblePSEditions = @()
+
+# ID used to uniquely identify this module
+GUID = '5d8a1afd-a912-440f-a9b9-e79f42a05f21'
+
+# Author of this module
+Author = 'Adam Burley'
+
+# Company or vendor of this module
+CompanyName = 'Burley.dev'
+
+# Copyright statement for this module
+Copyright = 'Adam Burley, 2022'
+
+# Description of the functionality provided by this module
+Description = '*PassPushPosh* is a PowerShell Module for interfacing with the Password Pusher secure password / string sharing application, primarily through pwpush.com. It supports creating, retrieving, and deleting anonymous and authenticated pushes, links in any supported language, and getting Push and Dashboard data for authenticated users.
+
+Cmdlets provide clear responses to errors, support additional messaging via -Debug and -Verbose, transaction testing via -Whatif and -Confirm, and in general try to be as "Powershell-y" as possible.'
+
+# Minimum version of the PowerShell engine required by this module
+PowerShellVersion = '5.1'
+
+# Name of the PowerShell host required by this module
+# PowerShellHostName = ''
+
+# Minimum version of the PowerShell host required by this module
+# PowerShellHostVersion = ''
+
+# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# DotNetFrameworkVersion = ''
+
+# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# ClrVersion = ''
+
+# Processor architecture (None, X86, Amd64) required by this module
+# ProcessorArchitecture = ''
+
+# Modules that must be imported into the global environment prior to importing this module
+# RequiredModules = @()
+
+# Assemblies that must be loaded prior to importing this module
+# RequiredAssemblies = @()
+
+# Script files (.ps1) that are run in the caller's environment prior to importing this module.
+# ScriptsToProcess = @()
+
+# Type files (.ps1xml) to be loaded when importing this module
+# TypesToProcess = @()
+
+# Format files (.ps1xml) to be loaded when importing this module
+# FormatsToProcess = @()
+
+# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
+# NestedModules = @()
+
+# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
+FunctionsToExport = 'ConvertTo-PasswordPush', 'Get-Dashboard', 'Get-Push',
+ 'Get-PushAuditLog', 'Get-SecretLink', 'Initialize-PassPushPosh',
+ 'New-PasswordPush', 'New-Push', 'Remove-Push'
+
+# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
+CmdletsToExport = @()
+
+# Variables to export from this module
+VariablesToExport = '*'
+
+# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
+AliasesToExport = 'Get-PushPreview'
+
+# DSC resources to export from this module
+# DscResourcesToExport = @()
+
+# List of all modules packaged with this module
+# ModuleList = @()
+
+# List of all files packaged with this module
+# FileList = @()
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
+PrivateData = @{
+
+ PSData = @{
+
+ # Tags applied to this module. These help with module discovery in online galleries.
+ Tags = 'PSEdition_Desktop','PSEdition_Core','Windows','Linux','MacOS','Password'
+
+ # A URL to the license for this module.
+ LicenseUri = 'https://www.gnu.org/licenses/gpl-3.0.en.html'
+
+ # A URL to the main website for this project.
+ ProjectUri = 'https://github.com/adamburley/PassPushPosh'
+
+ # A URL to an icon representing this module.
+ # IconUri = ''
+
+ # ReleaseNotes of this module
+ ReleaseNotes = @"
+ 0.2.3 - Bug fixing in New-Push. See PR #1
+ 0.2.2 - Fixed issue with Get-Dashboard returning error referencing -JsonIsArray parameter
+ General - Module is generally functional but has not been extensively bug-tested. Reccomend not implementing into a production environment at this time.
+"@
+
+ # Prerelease string of this module
+ # Prerelease = ''
+
+ # Flag to indicate whether the module requires explicit user acceptance for install/update/save
+ # RequireLicenseAcceptance = $false
+
+ # External dependent modules of this module
+ # ExternalModuleDependencies = @()
+
+ } # End of PSData hashtable
+
+ } # End of PrivateData hashtable
+
+# HelpInfo URI of this module
+HelpInfoURI = 'https://github.com/adamburley/PassPushPosh/blob/main/Docs'
+
+# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+# DefaultCommandPrefix = ''
+
+}
+
diff --git a/Modules/PassPushPosh/0.2.3/PassPushPosh.psm1 b/Modules/PassPushPosh/0.2.3/PassPushPosh.psm1
new file mode 100644
index 000000000000..e159d6a80d3d
--- /dev/null
+++ b/Modules/PassPushPosh/0.2.3/PassPushPosh.psm1
@@ -0,0 +1,1012 @@
+class PasswordPush {
+ [string]$Payload
+ [string] hidden $__UrlToken
+ [string] hidden $__LinkBase
+ [string]$Language
+ [bool]$RetrievalStep
+ [bool]$IsExpired
+ [bool]$IsDeleted
+ [bool]$IsDeletableByViewer
+ [int]$ExpireAfterDays
+ [int]$DaysRemaining
+ [int]$ExpireAfterViews
+ [int]$ViewsRemaining
+ [DateTime]$DateCreated
+ [DateTime]$DateUpdated
+ [DateTime]$DateExpired
+ # Added by constructors:
+ #[string]$URLToken
+ #[string]$Link
+ #[string]$LinkDirect
+ #[string]$LinkRetrievalStep
+
+ PasswordPush() {
+ # Blank constructor
+ }
+
+ # Constructor to allow casting or explicit import from a PSObject Representing the result of an API call
+ PasswordPush([PSCustomObject]$APIresponseObject) {
+ throw NotImplementedException
+ }
+
+ # Allow casting or explicit import from the raw Content of an API call
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope = 'Function', Justification = 'Global variables are used for module session helpers.')]
+ PasswordPush([string]$JsonResponse) {
+ Write-Debug 'New PasswordPush object instantiated from JsonResponse string'
+ Initialize-PassPushPosh # Initialize the module if not yet done.
+
+ $_j = $JsonResponse | ConvertFrom-Json
+ $this.Payload = $_j.payload
+ $this.IsExpired = $_j.expired
+ $this.IsDeleted = $_j.deleted
+ $this.IsDeletableByViewer = $_j.deletable_by_viewer
+ $this.ExpireAfterDays = $_j.expire_after_days
+ $this.DaysRemaining = $_j.days_remaining
+ $this.ExpireAfterViews = $_j.expire_after_views
+ $this.ViewsRemaining = $_j.views_remaining
+ $this.DateCreated = $_j.created_at
+ $this.DateUpdated = $_j.updated_at
+ $this.DateExpired = if ($_j.expired_on) { $_j.expired_on } else { [DateTime]0 }
+
+ $this.Language = $Global:PPPLanguage
+
+ $this | Add-Member -Name 'UrlToken' -MemberType ScriptProperty -Value {
+ return $this.__UrlToken
+ } -SecondValue {
+ $this.__UrlToken = $_
+ $this.__LinkBase = "$Global:PPPBaseUrl/$($this.Language)/p/$($this.__UrlToken)"
+ }
+ $this.__UrlToken = $_j.url_token
+ $this.__LinkBase = "$Global:PPPBaseUrl/$($this.Language)/p/$($this.__UrlToken)"
+ $this | Add-Member -Name 'LinkDirect' -MemberType ScriptProperty -Value { return $this.__LinkBase } -SecondValue {
+ Write-Warning 'LinkDirect is a read-only calculated member.'
+ Write-Debug 'Link* members are calculated based on the Global BaseUrl and Language and Push Retrieval Step values'
+ }
+ $this | Add-Member -Name 'LinkRetrievalStep' -MemberType ScriptProperty -Value { return "$($this.__LinkBase)/r" } -SecondValue {
+ Write-Warning 'LinkRetrievalStep is a read-only calculated member.'
+ Write-Debug 'Link* members are calculated based on the Global BaseUrl and Language and Push Retrieval Step values'
+ }
+ $this | Add-Member -Name 'Link' -MemberType ScriptProperty -Value {
+ $_Link = if ($this.RetrievalStep) { $this.LinkRetrievalStep } else { $this.LinkDirect }
+ Write-Debug "Presented Link: $_link"
+ return $_Link
+ } -SecondValue {
+ Write-Warning 'Link is a read-only calculated member.'
+ Write-Debug 'Link* members are calculated based on the Global BaseUrl and Language and Push Retrieval Step values'
+ }
+ }
+}
+
+function ConvertTo-PasswordPush {
+ <#
+ .SYNOPSIS
+ Convert API call response to a PasswordPush object
+
+ .DESCRIPTION
+ Accepts a JSON string returned from the Password Pusher API and converts it to a [PasswordPush] object.
+ This allows calculated push retrieval URLs, language enumeration, and a more "PowerShell" experience.
+ Generally you won't need to use this directly, it's automatically invoked within Register-Push and Request-Push.
+
+ .INPUTS
+ [string]
+
+ .OUTPUTS
+ [PasswordPush] for single object
+ [PasswordPush[]] for Json array data
+
+ .EXAMPLE
+ # Common usage - from within the Register-Push cmdlet
+ PS> $myPush = Register-Push -Payload "This is my secret!"
+ PS> $myPush.Link # The link parameter always presents the URL as it would appear with the same settings selected on pwpush.com
+
+ https://pwpush.com/en/p/rz6nryvl-d4
+
+ .EXAMPLE
+ # Manually invoking the API
+ PS> $rawJson = Invoke-WebRequest `
+ -Uri https://pwpush.com/en/p.json `
+ -Method Post `
+ -Body '{"password": { "payload": "This is my secret!"}}' `
+ -ContentType 'application/json' |
+ Select-Object -ExpandProperty Content
+ PS> $rawJson
+ {"expire_after_days":7,"expire_after_views":5,"expired":false,"url_token":"rz6nryvl-d4","created_at":"2022-11-18T14:16:29.821Z","updated_at":"2022-11-18T14:16:29.821Z","deleted":false,"deletable_by_viewer":true,"retrieval_step":false,"expired_on":null,"days_remaining":7,"views_remaining":5}
+ PS> $rawJson | ConvertTo-PasswordPush
+ UrlToken : rz6nryvl-d4
+ LinkDirect : https://pwpush.com/en/p/rz6nryvl-d4
+ LinkRetrievalStep : https://pwpush.com/en/p/rz6nryvl-d4/r
+ Link : https://pwpush.com/en/p/rz6nryvl-d4
+ Payload :
+ Language : en
+ RetrievalStep : False
+ IsExpired : False
+ IsDeleted : False
+ IsDeletableByViewer : True
+ ExpireAfterDays : 7
+ DaysRemaining : 7
+ ExpireAfterViews : 5
+ ViewsRemaining : 5
+ DateCreated : 11/18/2022 2:16:29 PM
+ DateUpdated : 11/18/2022 2:16:29 PM
+ DateExpired : 1/1/0001 12:00:00 AM
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/ConvertTo-PasswordPush.md
+
+ .NOTES
+ Needs a rewrite / cleanup
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', Justification = 'Creates a new object, no risk of overwriting data.')]
+ [CmdletBinding()]
+ [OutputType([PasswordPush])]
+ param(
+ # The string result of an API call from the Password Pusher application
+ [parameter(Mandatory, ValueFromPipeline)]
+ [ValidateNotNullOrEmpty()]
+ [string]$JsonResponse
+ )
+ process {
+ try {
+ $jsonObject = $JsonResponse | ConvertFrom-Json
+ foreach ($o in $jsonObject) {
+ [PasswordPush]($o | ConvertTo-Json) # TODO fix this mess
+ }
+ }
+ catch {
+ Write-Debug 'Error in ConvertTo-PasswordPush coercing JSON object to PasswordPush object'
+ Write-Debug "JsonResponse parameter value: [[$JsonResponse]]"
+ Write-Error $_
+ }
+ }
+}
+function Get-Dashboard {
+ <#
+ .SYNOPSIS
+ Get a list of active or expired Pushes for an authenticated user
+
+ .DESCRIPTION
+ Retrieves a list of Pushes - active or expired - for an authenticated user.
+ Active and Expired are different endpoints, so to get both you'll need to make
+ two calls.
+
+ .INPUTS
+ [string] 'Active' or 'Expired'
+
+ .OUTPUTS
+ [PasswordPush[]] Array of pushes with data
+ [string] raw response body from API call
+
+ .EXAMPLE
+ Get-Dashboard
+
+ .EXAMPLE
+ Get-Dashboard Active
+
+ .EXAMPLE
+ Get-Dashboard -Dashboard Expired
+
+ .EXAMPLE
+ Get-Dashboard -Raw
+ [{"expire_after_days":1,"expire_after_views":5,"expired":false,"url_token":"xm3q7czvtdpmyg","created_at":"2022-11-19T18:10:42.055Z","updated_at":"2022-11-19T18:10:42.055Z","deleted":false,"deletable_by_viewer":true,"retrieval_step":false,"expired_on":null,"note":null,"days_remaining":1,"views_remaining":3}]
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Get-Dashboard.md
+
+ .LINK
+ https://pwpush.com/api/1.0/dashboard.en.html
+
+ .LINK
+ Get-PushAuditLog
+
+ .NOTES
+ TODO update Invoke-Webrequest flow and error-handling to match other functions
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope = 'Function', Justification = 'Global variables are used for module session helpers.')]
+ [CmdletBinding()]
+ [OutputType([PasswordPush[]],[string])]
+ param(
+ # URL Token from a secret
+ [parameter(Position=0)]
+ [ValidateSet('Active','Expired')]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Dashboard = 'Active',
+
+ # Return content of API call directly
+ [Parameter()]
+ [switch]
+ $Raw
+ )
+ if (-not $Global:PPPHeaders) { Write-Error 'Dashboard access requires authentication. Run Initialize-PassPushPosh and pass your email address and API key before retrying.' -ErrorAction Stop -Category AuthenticationError }
+ try {
+ $uri = "$Global:PPPBaseUrl/d/"
+ if ($Dashboard -eq 'Active') { $uri += 'active.json' }
+ elseif ($Dashboard -eq 'Expired') { $uri += 'expired.json' }
+ Write-Debug "Requesting $uri"
+ $response = Invoke-WebRequest -Uri $uri -Method Get -Headers $Global:PPPHeaders -ErrorAction Stop
+ if ($Raw) { return $response.Content }
+ else {
+ return $response.Content | ConvertTo-PasswordPush
+ }
+ } catch {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name 'PPPLastError' -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ }
+ throw # Re-throw the error
+ }
+}
+function Get-Push {
+ <#
+ .SYNOPSIS
+ Retrieve the secret contents of a Push
+
+ .DESCRIPTION
+ Accepts a URL Token string, returns the contents of a Push along with
+ metadata regarding that Push. Note, Get-Push will return data on an expired
+ Push (datestamps, etc) even if it does not return the Push contents.
+
+ .INPUTS
+ [string]
+
+ .OUTPUTS
+ [PasswordPush] or [string]
+
+ .EXAMPLE
+ Get-Push -URLToken gzv65wiiuciy
+
+ .EXAMPLE
+ Get-Push -URLToken gzv65wiiuciy -Raw
+ {"payload":"I am your payload!","expired":false,"deleted":false,"expired_on":"","expire_after_days":1,"expire_after_views":4,"url_token":"bwzehzem_xu-","created_at":"2022-11-21T13:20:08.635Z","updated_at":"2022-11-21T13:23:45.342Z","deletable_by_viewer":true,"retrieval_step":false,"days_remaining":1,"views_remaining":4}
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Get-Push.md
+
+ .LINK
+ https://pwpush.com/api/1.0/passwords/show.en.html
+
+ .LINK
+ New-Push
+
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars','',Scope='Function',Justification='Global variables are used for module session helpers.')]
+ [CmdletBinding()]
+ [OutputType([PasswordPush])]
+ param(
+ # URL Token for the secret
+ [parameter(Mandatory,ValueFromPipeline,Position=0)]
+ [ValidateNotNullOrEmpty()]
+ [Alias('Token')]
+ $URLToken,
+
+ # Return the raw response body from the API call
+ [Parameter()]
+ [switch]
+ $Raw
+ )
+ begin { Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference }
+
+ process {
+ try {
+ $iwrSplat = @{
+ 'Method' = 'Get'
+ 'ContentType' = 'application/json'
+ 'Uri' = "$Global:PPPBaseUrl/p/$URLToken.json"
+ 'UserAgent' = $Global:PPPUserAgent
+ }
+ if ($Global:PPPHeaders) { $iwrSplat['Headers'] = $Global:PPPHeaders }
+ Write-Verbose "Sending HTTP request: $($iwrSplat | Out-String)"
+ $response = Invoke-WebRequest @iwrSplat -ErrorAction Stop
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastCall -Value $response
+ Write-Debug 'Response to Invoke-WebRequest set to PPPLastCall Global variable'
+ }
+ if ($Raw) {
+ Write-Debug "Returning raw object:`n$($response.Content)"
+ return $response.Content
+ }
+ return $response.Content | ConvertTo-PasswordPush
+ } catch {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastError -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ }
+ }
+ }
+}
+function Get-PushAuditLog {
+ <#
+ .SYNOPSIS
+ Get the view log of an authenticated Push
+
+ .DESCRIPTION
+ Retrieves the view log of a Push created under an authenticated session.
+ Returns an array of custom objects with view data. If the query is
+ successful but there are no results, it returns an empty array.
+ If there's an error, a single object is returned with information.
+ See "handling errors" under NOTES
+
+ .INPUTS
+ [string]
+
+ .OUTPUTS
+ [PsCustomObject[]] Array of entries.
+ [PsCustomObject] If there's an error in the call, it will be returned an object with a property
+ named 'error'. The value of that member will contain more information
+
+ .EXAMPLE
+ Get-PushAuditLog -URLToken 'mytokenfromapush'
+ ip : 75.202.43.56,102.70.135.200
+ user_agent : Mozilla/5.0 (Macintosh; Darwin 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:20:05 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T8101;
+ en-US) PowerShell/7.2.7
+ referrer :
+ successful : True
+ created_at : 11/19/2022 6:32:42 PM
+ updated_at : 11/19/2022 6:32:42 PM
+ kind : 0
+
+ .EXAMPLE
+ # If there are no views, an empty array is returned
+ Get-PushAuditLog -URLToken 'mytokenthatsneverbeenseen'
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Get-PushAuditLog.md
+
+ .LINK
+ https://pwpush.com/api/1.0/passwords/audit.en.html
+
+ .LINK
+ Get-Dashboard
+
+ .NOTES
+ Handling Errors:
+ The API returns different HTTP status codes and results depending where the
+ call fails.
+
+ | HTTP RESPONSE | Error Reason | Response Body | Sample Object Returned | Note |
+ |------------------|---------------------------------|----------------------------------------------|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
+ | 401 UNAUTHORIZED | Invalid API key or email | None | @{ 'Error'= 'Authentication error. Verify email address and API key.'; 'ErrorCode'= 401 } | |
+ | 200 OK | Push created by another account | {"error":"That push doesn't belong to you."} | @{ 'Error'= "That Push doesn't belong to you"; 'ErrorCode'= 403 } | Function transforms error code to 403 to allow easier response management |
+ | 404 NOT FOUND | Invalid URL token | None | @{ 'Error'= 'Invalid token. Verify your Push URL token is correct.'; 'ErrorCode'= 404 } | This is different than the response to a delete Push query - in this case it will only return 404 if the token is invalid. |
+
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope = 'Function', Justification = 'Global variables are used for module session helpers.')]
+ [CmdletBinding()]
+ [OutputType([PSCustomObject[]],[string])]
+ param(
+ # URL Token from a secret
+ [parameter(ValueFromPipeline)]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $URLToken,
+
+ # Return content of API call directly
+ [Parameter()]
+ [switch]
+ $Raw
+ )
+ begin {
+ if (-not $Global:PPPHeaders) { Write-Error 'Retrieving audit logs requires authentication. Run Initialize-PassPushPosh and pass your email address and API key before retrying.' -ErrorAction Stop -Category AuthenticationError }
+ }
+ process {
+ try {
+ $uri = "$Global:PPPBaseUrl/p/$URLToken/audit.json"
+ Write-Debug 'Requesting $uri'
+ $response = Invoke-WebRequest -Uri $uri -Method Get -Headers $Global:PPPHeaders -ErrorAction Stop
+ if ([int]$response.StatusCode -eq 200 -and $response.Content -ieq "{`"error`":`"That push doesn't belong to you.`"}") {
+ $result = [PSCustomObject]@{ 'Error' = "That Push doesn't belong to you"; 'ErrorCode' = 403 }
+ Write-Warning $result.Error
+ return $result
+ }
+ if ($Raw) { return $response.Content } else { return $response.Content | ConvertFrom-Json }
+ }
+ catch {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ([int]$_.Exception.Response.StatusCode -eq 401) { # Could be optimized
+ $result = [PSCustomObject]@{ 'Error' = 'Authentication error. Verify email address and API key.'; 'ErrorCode' = 401 }
+ Write-Warning $result.Error
+ return $result
+ } elseif ([int]$_.Exception.Response.StatusCode -eq 404) {
+ $result = [PSCustomObject]@{ 'Error' = 'Invalid token. Verify your Push URL token is correct.'; 'ErrorCode' = 404 }
+ Write-Warning $result.Error
+ return $result
+ }
+ elseif ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name 'PPPLastError' -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ return [PSCustomObject]@{
+ 'Error' = $_.Exception.Message
+ 'ErrorCode' = [int]$_.Exception.Response.StatusCode
+ 'ErrorMessage' = $_.Exception.Response.ReasonPhrase
+ }
+ }
+ }
+ }
+}
+
+# Invalid API key / email - 401
+# Invalid URL Token - 404
+# Valid token but not mine - 200, content = {"error":"That push doesn't belong to you."}
+# Success but no views - 200, content = : {"views":[]}
+# Success with view history {"views":[{"ip":"75.118.137.58,172.70.135.200","user_agent":"Mozilla/5.0 (Macintosh; Darwin 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:20:05 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T8101; en-US) PowerShell/7.2.7","referrer":"","successful":true,"created_at":"2022-11-19T18:32:42.277Z","updated_at":"2022-11-19T18:32:42.277Z","kind":0}]}
+# Content.Views
+<#
+ip : 75.118.137.58,172.70.135.200
+user_agent : Mozilla/5.0 (Macintosh; Darwin 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:20:05 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T8101;
+en-US) PowerShell/7.2.7
+referrer :
+successful : True
+created_at : 11/19/2022 6:32:42 PM
+updated_at : 11/19/2022 6:32:42 PM
+kind : 0
+#>
+function Get-SecretLink {
+ <#
+ .SYNOPSIS
+ Returns a fully qualified secret link to a push of given URL Token
+
+ .DESCRIPTION
+ Accepts a string value for a URL Token and retrieves a full URL link to the secret.
+ Returned value is a 1-step retrieval link depending on option selected during Push creation.
+ Returns false if URL Token is invalid, however it will return a URL if the token is valid
+ but the Push is expired or deleted.
+
+ .INPUTS
+ [string] URL Token value
+
+ .OUTPUTS
+ [string] Fully qualified URL
+ [bool] $False if Push URL Token is invalid. Note: Expired or deleted Pushes will still return a link.
+
+ .EXAMPLE
+ Get-SecretLink -URLToken gzv65wiiuciy
+ https://pwpush.com/en/p/gzv65wiiuciy/r
+
+ .EXAMPLE
+ # En France
+ PS > Get-SecretLink -URLToken gzv65wiiuciy -Language fr
+ https://pwpush.com/fr/p/gzv65wiiuciy/r
+
+ .EXAMPLE
+ Get-SecretLink -URLToken gzv65wiiuciy -Raw
+ { "url": "https://pwpush.com/es/p/0fkapnbo_pwp4gi8uy0/r" }
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Get-SecretLink.md
+
+ .LINK
+ https://pwpush.com/api/1.0/passwords/preview.en.html
+
+ .NOTES
+ Including this endpoint for completeness - however it is generally unnecessary.
+ The only thing this endpoint does is return a different value depending if "Use 1-click retrieval step"
+ was selected when the Push was created. Since both the 1-click and the direct links are available
+ regardless if that option is selected, the links are calculable and both are included by default in a
+ [PasswordPush] object.
+
+ As it returns false if a Push URL token is not valid you can use it to test if a Push exists without
+ burning a view.
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars','',Scope='Function',Justification='Global variables are used for module session helpers.')]
+ [CmdletBinding()]
+ [Alias('Get-PushPreview')]
+ [OutputType('[string]')]
+ param(
+ # URL Token for the secret
+ [parameter(Mandatory, ValueFromPipeline)]
+ [ValidateLength(5, 256)]
+ [string]$URLToken,
+
+ # Language for returned links. Defaults to system language, can be overridden here.
+ [Parameter()]
+ [string]
+ $Language = $Global:PPPLanguage,
+
+ # Return the raw response body from the API call
+ [Parameter()]
+ [switch]
+ $Raw
+ )
+ begin { Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference }
+ process {
+ try {
+ if ($Language -ine 'en') { $uri += "?push_locale=$Language" }
+ $iwrSplat = @{
+ 'Method' = 'Get'
+ 'ContentType' = 'application/json'
+ 'Uri' = "$Global:PPPBaseUrl/p/$URLToken/preview.json"
+ 'UserAgent' = $Global:PPPUserAgent
+ }
+ if ($Global:PPPHeaders) { $iwrSplat['Headers'] = $Global:PPPHeaders }
+ Write-Verbose "Sending HTTP request: $($iwrSplat | Out-String)"
+ $responseContent = Invoke-WebRequest @iwrSplat | Select-Object -ExpandProperty Content
+ if ($Raw) { return $responseContent }
+ else { return $responseContent | ConvertFrom-Json | Select-Object -ExpandProperty url }
+ }
+ catch {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name 'PPPLastError' -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ }
+ }
+ }
+}
+function Initialize-PassPushPosh {
+ <#
+ .SYNOPSIS
+ Initialize the PassPushPosh module
+
+ .DESCRIPTION
+ Sets global variables to handle the server URL, headers (authentication), and language.
+ Called automatically by module Functions if it is not called explicitly prior, so you don't actually need
+ to call it unless you're going to use the authenticated API or alternate server, etc
+ Default parameters use the pwpush.com domain, anonymous authentication, and whatever language your computer
+ is set to.
+
+ .EXAMPLE
+ # Initialize with default settings
+ PS > Initialize-PassPushPosh
+
+ .EXAMPLE
+ # Initialize with authentication
+ PS > Initialize-PassPushPosh -EmailAddress 'youremail@example.com' -ApiKey '239jf0jsdflskdjf' -Verbose
+
+ VERBOSE: Initializing PassPushPosh. ApiKey: [x-kdjf], BaseUrl: https://pwpush.com
+
+ .EXAMPLE
+ # Initialize with another server with authentication
+ PS > Initialize-PassPushPosh -BaseUrl https://myprivatepwpushinstance.com -EmailAddress 'youremail@example.com' -ApiKey '239jf0jsdflskdjf' -Verbose
+
+ VERBOSE: Initializing PassPushPosh. ApiKey: [x-kdjf], BaseUrl: https://myprivatepwpushinstance.com
+
+ .EXAMPLE
+ # Set a custom User Agent
+ PS > InitializePassPushPosh -UserAgent "I'm a cool dude with a cool script."
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Initialize-PassPushPosh.md
+
+ .NOTES
+ All variables set by this function start with PPP.
+ - PPPHeaders
+ - PPPLanguage
+ - PPPUserAgent
+ - PPPBaseUrl
+
+ -WhatIf setting for Set-Variable -Global is disabled, otherwise -WhatIf
+ calls for other functions would return incorrect data in the case this
+ function has not yet run.
+
+ TODO: Review API key pattern for parameter validation
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars','',Scope='Function',Justification='Global variables are used for module session helpers.')]
+ [CmdletBinding(DefaultParameterSetName='Anonymous')]
+ param (
+ # Email address to use for authenticated calls.
+ [Parameter(Mandatory,Position=0,ParameterSetName='Authenticated')]
+ [ValidatePattern('.+\@.+\..+')]
+ [string]$EmailAddress,
+
+ # API Key for authenticated calls.
+ [Parameter(Mandatory,Position=1,ParameterSetName='Authenticated')]
+ [ValidateLength(5,256)]
+ [string]$ApiKey,
+
+ # Base URL for API calls. Allows use of module with private instances of Password Pusher
+ # Default: https://pwpush.com
+ [Parameter(Position=0,ParameterSetName='Anonymous')]
+ [Parameter(Position=2,ParameterSetName='Authenticated')]
+ [ValidatePattern('^https?:\/\/[a-zA-Z0-9-_]+.[a-zA-Z0-9]+')]
+ [string]$BaseUrl,
+
+ # Language to render resulting links in. Defaults to host OS language, or English if
+ # host OS language is not available
+ [Parameter()]
+ [string]
+ $Language,
+
+ # Set a specific user agent. Default user agent is a combination of the
+ # module info, what your OS reports itself as, and a hash based on
+ # your username + workstation or domain name. This way the UA can be
+ # semi-consistent across sessions but not identifying.
+ [Parameter()]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $UserAgent,
+
+ # Force setting new information. If module is already initialized you can use this to
+ # Re-initialize with default settings. Implied if either ApiKey or BaseUrl is provided.
+ [Parameter()][switch]$Force
+ )
+ if ($Global:PPPBaseURL -and $true -inotin $Force, [bool]$ApiKey, [bool]$BaseUrl, [bool]$UserAgent) { Write-Debug -Message 'PassPushPosh is already initialized.' }
+ else {
+ $defaultBaseUrl = 'https://pwpush.com'
+ $apiKeyOutput = if ($ApiKey) { 'x-' + $ApiKey.Substring($ApiKey.Length-4) } else { 'None' }
+
+ if (-not $Global:PPPBaseURL) { # Not initialized
+ if (-not $BaseUrl) { $BaseUrl = $defaultBaseUrl }
+ Write-Verbose "Initializing PassPushPosh. ApiKey: [$apiKeyOutput], BaseUrl: $BaseUrl"
+ } elseif ($Force -or $ApiKey -or $BaseURL) {
+ if (-not $BaseUrl) { $BaseUrl = $defaultBaseUrl }
+ $oldApiKeyOutput = if ($Global:PPPApiKey) { 'x-' + $Global:PPPApiKey.Substring($Global:PPPApiKey.Length-4) } else { 'None' }
+ Write-Verbose "Re-initializing PassPushPosh. Old ApiKey: [$oldApiKeyOutput] New ApiKey: [$apiKeyOutput], Old BaseUrl: $Global:PPPBaseUrl New BaseUrl: $BaseUrl"
+ }
+ if ($PSCmdlet.ParameterSetName -eq 'Authenticated') {
+ Set-Variable -Scope Global -Name PPPHeaders -WhatIf:$false -Value @{
+ 'X-User-Email' = $EmailAddress
+ 'X-User-Token' = $ApiKey
+ }
+ } elseif ($Global:PPPHeaders) { # Remove if present - covers case where module is reinitialized from an authenticated to an anonymous session
+ Remove-Variable -Scope Global -Name PPPHeaders -WhatIf:$false
+ }
+ $availableLanguages = ('en','ca','cs','da','de','es','fi','fr','hu','it','nl','no','pl','pt-BR','sr','sv')
+ if (-not $Language) {
+ $Culture = Get-Culture
+ Write-Debug "Detected Culture: $($Culture.DisplayName)"
+ $matchedLanguage = $Culture.TwoLetterISOLanguageName, $Culture.IetfLanguageTag |
+ Foreach-Object { if ($_ -iin $availableLanguages) { $_ } } |
+ Select-Object -First 1
+ if ($matchedLanguage) {
+ Write-Debug "Language is supported in Password Pusher."
+ $Language = $matchedLanguage
+ } else { Write-Warning "Detected language $($Culture.DisplayName) is not supported in PasswordPusher. Defaulting to English." }
+ } else {
+ if ($Language -iin $availableLanguages) {
+ Write-Debug "Language [$Language] is available in PasswordPusher."
+ } else
+ {
+ Write-Warning "Language [$Language] is not available in PasswordPusher. Defaulting to english."
+ $Language = 'en'
+ }
+ }
+
+ if (-not $UserAgent) {
+ $osVersion = [System.Environment]::OSVersion
+ $userAtDomain = "{0}@{1}" -f [System.Environment]::UserName, [System.Environment]::UserDomainName
+ $uAD64 = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($userAtDomain))
+ Write-Debug "$userAtDomain transformed to $uAD64. First 20 characters $($uAD64.Substring(0,20))"
+ $UserAgent = "PassPushPosh/$((Get-Module -Name PassPushPosh).Version.ToString()) $Language $osVersion/$($uAD64.Substring(0,20))"
+ Write-Verbose "Generated user agent: $UserAgent"
+ } else {
+ Write-Verbose "Using specified user agent: $UserAgent"
+ }
+
+ Set-Variable -WhatIf:$false -Scope Global -Name PPPBaseURL -Value $BaseUrl.TrimEnd('/')
+ Set-Variable -WhatIf:$false -Scope Global -Name PPPLanguage -Value $Language
+ Set-Variable -WhatIf:$false -Scope Global -Name PPPUserAgent -Value $UserAgent
+ }
+}
+function New-PasswordPush {
+ <#
+ .SYNOPSIS
+ Create a new blank Password Push object.
+
+ .DESCRIPTION
+ Creates a blank [PasswordPush].
+ Generally not needed, use ConvertTo-PasswordPush
+ See New-Push if you're trying to create a new secret to send
+
+ .INPUTS
+ None
+
+ .OUTPUTS
+ [PasswordPush]
+
+ .EXAMPLE
+ New-PasswordPush
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/New-PasswordPush.md
+
+ .NOTES
+ TODO Rewrite - make this work including read-only properties
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', Justification = 'Creates a new object, no risk of overwriting data.')]
+ [CmdletBinding()]
+ param ()
+ return [PasswordPush]::new()
+}
+function New-Push {
+ <#
+ .SYNOPSIS
+ Create a new Password Push
+
+ .DESCRIPTION
+ Create a new Push on the specified Password Pusher instance. The
+ programmatic equivalent of going to pwpush.com and entering info.
+ Returns [PasswordPush] object. Link member is a link created based on
+ 1-step setting and language specified, however both 1-step and direct links
+ are always provided at LinkRetrievalStep and LinkDirect.
+
+ .EXAMPLE
+ $myPush = New-Push "Here's my secret!"
+ PS > $myPush | Select-Object Link, LinkRetrievalStep, LinkDirect
+
+ Link : https://pwpush.com/en/p/gzv65wiiuciy # Requested style
+ LinkRetrievalStep : https://pwpush.com/en/p/gzv65wiiuciy/r # 1-step
+ LinkDirect : https://pwpush.com/en/p/gzv65wiiuciy # Direct
+
+ .EXAMPLE
+ "Super secret secret" | New-Push -RetrievalStep | Select-Object -ExpandProperty Link
+
+ https://pwpush.com/en/p/gzv65wiiuciy/r
+
+
+ .EXAMPLE
+ # "Burn after reading" style Push
+ PS > New-Push -Payload "Still secret text!" -ExpireAfterViews 1 -RetrievalStep
+
+ .INPUTS
+ [string]
+
+ .OUTPUTS
+ [PasswordPush] Push object
+ [string] Raw result of API call
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/New-Push.md
+
+ .LINK
+ https://pwpush.com/api/1.0/passwords/create.en.html
+
+ .LINK
+ Get-Push
+
+ .NOTES
+ Maximum for -ExpireAfterDays and -ExpireAfterViews is based on the default
+ values for Password Pusher and what's used on the public instance
+ (pwpush.com). If you're using this with a private instance and want to
+ override that value you'll need to fork this module.
+
+ TODO: Support [PasswordPush] input objects, testing
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars','',Scope='Function',Justification='Global variables are used for module session helpers.')]
+ [CmdletBinding(SupportsShouldProcess,ConfirmImpact='Low',DefaultParameterSetName='Anonymous')]
+ [OutputType([PasswordPush],[string],[bool])] # Returntype should be [PasswordPush] but I've yet to find a way to add class access to a function on a module...
+ param(
+ # The password or secret text to share.
+ [Parameter(Mandatory=$true,ValueFromPipeline,Position=0)]
+ [Alias('Password')]
+ [ValidateNotNullOrEmpty()]
+ [string]$Payload,
+
+ # Label for this Push (requires Authenticated session)
+ [Parameter(ParameterSetName='RequiresAuthentication')]
+ [ValidateNotNullOrEmpty()]
+ [string]$Note,
+
+ # Expire secret link and delete after this many days.
+ [Parameter()]
+ [ValidateRange(1,90)]
+ [int]
+ $ExpireAfterDays,
+
+ # Expire secret link after this many views.
+ [Parameter()]
+ [ValidateRange(1,100)]
+ [int]
+ $ExpireAfterViews,
+
+ # Allow the recipient of a Push to delete it.
+ [Parameter()]
+ [switch]
+ $DeletableByViewer,
+
+ # Require recipient click an extra link to view Push payload.
+ # Helps to avoid chat systems and URL scanners from eating up views.
+ # Note that the retrieval step URL is always available for a push. This
+ # parameter changes if the 1-click link is used in the Link parameter
+ # and returned from the secret link helper (Get-SecretLink)
+ [Parameter()]
+ [switch]
+ $RetrievalStep,
+
+ # Override Language. Useful if sending to someone who speaks a
+ # different language. You can change this after the fact by changing
+ # the URL by hand or by requesting a link for the given token from the
+ # preview helper endpoint ( See Request-SecretLink )
+ [Parameter()]
+ [string]
+ $Language,
+
+ # Return the raw response body from the API call
+ [Parameter()]
+ [switch]
+ $Raw
+ )
+
+ begin {
+ Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference
+ }
+
+ process {
+ if ($PSCmdlet.ParameterSetName -eq 'RequiresAuthentication' -and -not $Global:PPPHeaders.'X-User-Token') { Write-Error -Message 'Setting a note requires an authenticated call.'; return $false }
+
+ $body = @{
+ 'password' = @{
+ 'payload' = $Payload
+ }
+ }
+ $shouldString = 'Submit {0} push with Payload of length {1}' -f $PSCmdlet.ParameterSetName, $Payload.Length
+ if ($Note) {
+ $body.password.note = $note
+ $shouldString += " with note $note"
+ }
+ if ($ExpireAfterDays) {
+ $body.password.expire_after_days = $ExpireAfterDays
+ $shouldString += ', expire after {0} days' -f $ExpireAfterDays
+ }
+ if ($ExpireAfterViews) {
+ $body.password.expire_after_views = $ExpireAfterViews
+ $shouldString += ', expire after {0} views' -f $ExpireAfterViews
+ }
+ $body.password.deletable_by_viewer = if ($DeletableByViewer) {
+ $shouldString += ', deletable by viewer'
+ $true
+ } else {
+ $shouldString += ', NOT deletable by viewer'
+ $false
+ }
+ $body.password.retrieval_step = if ($RetrievalStep) {
+ $shouldString += ', with a 1-click retrieval step'
+ $true
+ } else {
+ $shouldString += ', with a direct link'
+ $false
+ }
+ if (-not $Language) { $Language = $Global:PPPLanguage }
+ $shouldString += ' in language "{0}"' -f $Language
+ if ($VerbosePreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ # Sanitize input so we're not logging or outputting the payload
+ $vBody = $body.Clone()
+ $vBody.password.payload = "A payload of length $($body.password.payload.Length.ToString())"
+ $vBs = $vBody | ConvertTo-Json | Out-String
+ Write-Verbose "Call Body (sanitized): $vBs"
+ }
+
+ $iwrSplat = @{
+ 'Method' = 'Post'
+ 'ContentType' = 'application/json'
+ 'Body' = ($body | ConvertTo-Json)
+ 'Uri' = "$Global:PPPBaseUrl/$Language/p.json"
+ 'UserAgent' = $Global:PPPUserAgent
+ }
+ if ($Global:PPPHeaders.'X-User-Token') { $iwrSplat['Headers'] = $Global:PPPHeaders }
+ Write-Verbose "Sending HTTP request (minus body): $($iwrSplat | Select-Object Method,ContentType,Uri,UserAgent,Headers | Out-String)"
+ if ($PSCmdlet.ShouldProcess($shouldString, $iwrSplat.Uri, 'Submit new Push')) {
+ try {
+ $response = Invoke-WebRequest @iwrSplat
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastCall -Value $response
+ Write-Debug 'Response to Invoke-WebRequest set to PPPLastCall Global variable'
+ }
+ if ($Raw) {
+ Write-Debug "Returning raw object: $($response.Content)"
+ return $response.Content
+ }
+ return $response.Content | ConvertTo-PasswordPush
+ } catch {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastError -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ }
+ }
+ }
+ }
+}
+function Remove-Push {
+ <#
+ .SYNOPSIS
+ Remove a Push
+
+ .DESCRIPTION
+ Remove (invalidate) an active push. Requires the Push be either set as
+ deletable by viewer, or that you are authenticated as the creator of the
+ Push.
+
+ If you have authorization to delete a push (deletable by viewer TRUE or
+ you are the Push owner) the endpoint will always return 200 OK with a Push
+ object, regardless if the Push was previously deleted or expired.
+
+ If the Push URL Token is invalid OR you are not authorized to delete the
+ Push, the endpoint returns 404 and this function returns $false
+
+ .INPUTS
+ [string] URL Token
+ [PasswordPush] representing the Push to remove
+
+ .OUTPUTS
+ [bool] True on success, otherwise False
+
+ .EXAMPLE
+ Remove-Push -URLToken bwzehzem_xu-
+
+ .EXAMPLE
+ Remove-Push -URLToken -Raw
+ {"expired":true,"deleted":true,"expired_on":"2022-11-21T13:23:45.341Z","expire_after_days":1,"expire_after_views":4,"url_token":"bwzehzem_xu-","created_at":"2022-11-21T13:20:08.635Z","updated_at":"2022-11-21T13:23:45.342Z","deletable_by_viewer":true,"retrieval_step":false,"days_remaining":1,"views_remaining":4}
+
+ .LINK
+ https://github.com/adamburley/PassPushPosh/blob/main/Docs/Remove-Push.md
+
+ .LINK
+ https://pwpush.com/api/1.0/passwords/destroy.en.html
+
+ .NOTES
+ TODO testing and debugging
+ #>
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars','',Scope='Function',Justification='Global variables are used for module session helpers.')]
+ [CmdletBinding(SupportsShouldProcess,DefaultParameterSetName='Token')]
+ [OutputType([PasswordPush],[string],[bool])]
+ param(
+ # URL Token for the secret
+ [parameter(ValueFromPipeline,ParameterSetName='Token')]
+ [ValidateNotNullOrEmpty()]
+ [Alias('Token')]
+ [string]
+ $URLToken,
+
+ # PasswordPush object
+ [Parameter(ValueFromPipeline,ParameterSetName='Object')]
+ [PasswordPush]
+ $PushObject,
+
+ # Return the raw response body from the API call
+ [parameter()]
+ [switch]
+ $Raw
+ )
+ process {
+ try {
+ if ($PSCmdlet.ParameterSetName -eq 'Object') {
+ Write-Debug -Message "Remove-Push was passed a PasswordPush object with URLToken: [$($PushObject.URLToken)]"
+ if (-not $PushObject.IsDeletableByViewer -and -not $Global:PPPHeaders) { #Pre-qualify if this will succeed
+ Write-Warning -Message 'Unable to remove Push. Push is not marked as deletable by viewer and you are not authenticated.'
+ return $false
+ }
+ if ($PushObject.IsDeletableByViewer) {
+ Write-Verbose "Push is flagged as deletable by viewer, should be deletable."
+ } else { Write-Verbose "In an authenticated API session. Push will be deletable if it was created by authenticated user." }
+ $URLToken = $PushObject.URLToken
+ } else {
+ Write-Debug -Message "Remove-Push was passed a URLToken: [$URLToken]"
+ }
+ Write-Verbose -Message "Push with URL Token [$URLToken] will be deleted if 'Deletable by viewer' was enabled or you are the creator of the push and are authenticated."
+ $iwrSplat = @{
+ 'Method' = 'Delete'
+ 'ContentType' = 'application/json'
+ 'Uri' = "$Global:PPPBaseUrl/p/$URLToken.json"
+ 'UserAgent' = $Global:PPPUserAgent
+ }
+ if ($Global:PPPHeaders) { $iwrSplat['Headers'] = $Global:PPPHeaders }
+ Write-Verbose "Sending HTTP request: $($iwrSplat | Out-String)"
+ if ($PSCmdlet.ShouldProcess('Delete',"Push with token [$URLToken]")) {
+ $response = Invoke-WebRequest @iwrSplat
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastCall -Value $response
+ Write-Debug 'Response to Invoke-WebRequest set to PPPLastCall Global variable'
+ }
+ if ($Raw) {
+ Write-Debug "Returning raw object: $($response.Content)"
+ return $response.Content
+ }
+ return $response.Content | ConvertTo-PasswordPush
+ }
+ } catch {
+ if ($_.Exception.Response.StatusCode -eq 404) {
+ Write-Warning "Failed to delete Push. This can indicate an invalid URL Token, that the password was not marked deletable, or that you are not the owner."
+ return $false
+ } else {
+ Write-Verbose "An exception was caught: $($_.Exception.Message)"
+ if ($DebugPreference -eq [System.Management.Automation.ActionPreference]::Continue) {
+ Set-Variable -Scope Global -Name PPPLastError -Value $_
+ Write-Debug -Message 'Response object set to global variable $PPPLastError'
+ }
+ $_
+ }
+ }
+ }
+}
diff --git a/SendStats/run.ps1 b/SendStats/run.ps1
index b4427d230338..2e30b113ab55 100644
--- a/SendStats/run.ps1
+++ b/SendStats/run.ps1
@@ -17,6 +17,7 @@ $SendingObject = [PSCustomObject]@{
SetupComplete = $SetupComplete
RunningVersionAPI = $APIVersion.trim()
CountOfTotalTenants = $tenantcount
+ uid = $env:TenantID
} | ConvertTo-Json
Invoke-RestMethod -Uri 'https://management.cipp.app/api/stats' -Method POST -Body $SendingObject -ContentType 'application/json'
\ No newline at end of file
diff --git a/profile.ps1 b/profile.ps1
index 1aa6a00d98c6..f72dcd0c4c7d 100644
--- a/profile.ps1
+++ b/profile.ps1
@@ -46,6 +46,24 @@ try {
Write-LogMessage -message 'Could not retrieve keys from Keyvault' -LogData (Get-CippException -Exception $_) -Sev 'debug'
}
+Set-Location -Path $PSScriptRoot
+$CurrentVersion = (Get-Content .\version_latest.txt).trim()
+$Table = Get-CippTable -tablename 'Version'
+$LastStartup = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'Version' and RowKey eq 'Version'"
+if ($CurrentVersion -ne $LastStartup.Version) {
+ Write-Host "Version has changed from $($LastStartup.Version) to $CurrentVersion"
+ Clear-CippDurables
+ if ($LastStartup) {
+ $LastStartup.Version = $CurrentVersion
+ } else {
+ $LastStartup = [PSCustomObject]@{
+ PartitionKey = 'Version'
+ RowKey = 'Version'
+ Version = $CurrentVersion
+ }
+ }
+ Update-AzDataTableEntity @Table -Entity $LastStartup
+}
# Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell.
# Enable-AzureRmAlias
diff --git a/version_latest.txt b/version_latest.txt
index 3b867ccd76c3..a94a88fbb889 100644
--- a/version_latest.txt
+++ b/version_latest.txt
@@ -1 +1 @@
-5.7.0
\ No newline at end of file
+5.8.5
\ No newline at end of file