Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
29685d6
feat(api): add license capability presets
kris6673 May 4, 2026
59da6e6
Merge branch 'dev' into testlicense-presets
kris6673 May 11, 2026
5995ad7
Merge branch 'dev' into testlicense-presets
kris6673 May 11, 2026
2152641
fix: add the presets to the rest of the standards
kris6673 May 11, 2026
bc4abb5
feat: add DefenderForOffice365 preset to license tests
kris6673 May 11, 2026
f5702f4
feat: Enhance Invoke-ListIntuneTemplates to include usage tracking fo…
JohnDuprey May 12, 2026
ecbc9a5
fix: Add error handling for missing standard functions in Push-CIPPSt…
JohnDuprey May 12, 2026
57b7de1
fix: Rename 'usedInTemplates' property to 'usage' for clarity in Invo…
JohnDuprey May 12, 2026
7fd7d09
fixes sharepoint response stuff
KelvinTegelaar May 12, 2026
23c8994
fixes defaultr_hidden vs hidden #5990
KelvinTegelaar May 12, 2026
ad0d096
OneDrive Sharing disable
KelvinTegelaar May 12, 2026
2869564
Add AlertUserReportPhising
KelvinTegelaar May 12, 2026
ddb498f
chore: bump version to 10.4.5
JohnDuprey May 12, 2026
3543755
Update Viva standard
Zacgoose May 12, 2026
5f864e3
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
Zacgoose May 12, 2026
7819302
fix name
JohnDuprey May 12, 2026
785e71c
fix user select
KelvinTegelaar May 12, 2026
6a81a08
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
KelvinTegelaar May 12, 2026
2c5d0c9
feat: Add license capability presets (#2040)
KelvinTegelaar May 12, 2026
2dbc480
auth configs
Zacgoose May 12, 2026
3adade4
Featureflag configs and timer changes
Zacgoose May 13, 2026
93c8081
skip replacement if not value set for variable
Zacgoose May 13, 2026
2d33e02
strip return characters
Zacgoose May 13, 2026
d480cf7
Add Apps and SP to universal search
Zacgoose May 13, 2026
9011dd6
Nice CA policy editor and template creator/editor
Zacgoose May 13, 2026
897dfaa
fixed #5997
KelvinTegelaar May 13, 2026
b136300
#5997
KelvinTegelaar May 13, 2026
e060fa2
implements #5981
KelvinTegelaar May 13, 2026
f5f7ae7
fixes duplicate test calls in some cases
Zacgoose May 14, 2026
c097631
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into…
Zacgoose May 14, 2026
b4a5215
Fix tenant group scope cache
Zacgoose May 14, 2026
dbd7fcb
logging improvements
Zacgoose May 14, 2026
bc7de0c
when running a standard manually still process all standards for prec…
Zacgoose May 14, 2026
7ae35c2
post exec tweaks for dedupe queue names
Zacgoose May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions .github/agents/CIPP-Alert-Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,13 @@ When adding or modifying alerts:

When an alert depends on a tenant having certain SKUs or capabilities, you **must**:

- Use `Test-CIPPStandardLicense`
- Use `Test-CIPPStandardLicense`
- Prefer `-Preset` for common capability sets: `Exchange`, `SharePoint`, `Intune`, `Entra`, `EntraP2`, `Teams`, `Compliance`
- Use `-RequiredCapabilities` only when no preset matches, or combine it with `-Preset` for extra edge-case capabilities
- Do **not** manually inspect SKUs, raw license IDs, or raw capability lists.

Example pattern (adapt to the specific feature):

```powershell
$TestResult = Test-CIPPStandardLicense -StandardName 'AutopilotProfile' -TenantFilter $Tenant -RequiredCapabilities @(
'INTUNE_A',
'MDM_Services',
'EMS',
'SCCM',
'MICROSOFTINTUNEPLAN1'
)
$TestResult = Test-CIPPStandardLicense -StandardName 'AutopilotProfile' -TenantFilter $Tenant -Preset Intune
```
1 change: 1 addition & 0 deletions .github/agents/CIPP-Standards-Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ When adding or modifying standards:
- Similar logging and error handling
- Reuse helper functions instead of inlining raw Graph calls or custom HTTP code.
- Keep behaviour predictable.
- If a standard needs license gating, use `Test-CIPPStandardLicense` with `-Preset` for common capability sets (`Exchange`, `SharePoint`, `Intune`, `Entra`, `EntraP2`, `Teams`, `Compliance`). Use `-RequiredCapabilities` only when no preset matches, or combine it with `-Preset` for extra edge-case capabilities.

### 2. Return the code for the frontend.

Expand Down
7 changes: 2 additions & 5 deletions .github/instructions/alerts.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,11 @@ if ($InputValue -is [string] -and $InputValue.Trim().StartsWith('{')) {
If the alert depends on a specific M365 capability (Intune, Exchange, Defender, etc.), gate it early with `Test-CIPPStandardLicense`. Never inspect raw SKU IDs manually.

```powershell
$Licensed = Test-CIPPStandardLicense -StandardName '<AlertName>' -TenantFilter $TenantFilter -RequiredCapabilities @(
'INTUNE_A',
'MDM_Services'
)
$Licensed = Test-CIPPStandardLicense -StandardName '<AlertName>' -TenantFilter $TenantFilter -Preset Intune
if (-not $Licensed) { return }
```

Reference existing alerts in the same domain for common capability strings. The `Test-CIPPStandardLicense` function source documents the capability matching logic.
Use presets for common service families: `Exchange`, `SharePoint`, `Intune`, `Entra`, `EntraP2`, `Teams`, and `Compliance`. Use `-RequiredCapabilities` only when no preset matches, or combine it with `-Preset` when an alert needs a preset plus extra edge-case capabilities.

## Querying data

Expand Down
4 changes: 2 additions & 2 deletions .github/instructions/cippdb.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ function Set-CIPPDBCacheMyNewType {

try {
# 1. Optional license check
$Licensed = Test-CIPPStandardLicense -StandardName 'MyFeature' -TenantFilter $TenantFilter -RequiredCapabilities @('REQUIRED_SKU')
$Licensed = Test-CIPPStandardLicense -StandardName 'MyFeature' -TenantFilter $TenantFilter -Preset Intune
if (-not $Licensed) { return }

# 2. Fetch data from API
Expand All @@ -160,7 +160,7 @@ function Set-CIPPDBCacheMyNewType {

- **Always use `-AddCount`** unless you handle count rows manually
- **Pipeline streaming** for large datasets: pipe directly from `New-GraphGetRequest` into `Add-CIPPDbItem`
- **License gating**: use `Test-CIPPStandardLicense` when the API requires specific SKUs
- **License gating**: use `Test-CIPPStandardLicense -Preset <Name>` for common capability sets (`Exchange`, `SharePoint`, `Intune`, `Entra`, `EntraP2`, `Teams`, `Compliance`); use `-RequiredCapabilities` only for non-preset capabilities or additional edge-case capabilities
- **Conditional `$select`**: expand Graph `$select` fields based on license capabilities
- **Error handling**: catch, log with `Write-LogMessage`, do not rethrow (allows other types in the collection to continue)
- **No explicit return** of data — these functions write to the table as a side effect
Expand Down
8 changes: 4 additions & 4 deletions .github/instructions/standards.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function Invoke-CIPPStandard<Name> {

# 1. License gate (if the data source requires a specific SKU)
$TestResult = Test-CIPPStandardLicense -StandardName '<Name>' -TenantFilter $Tenant `
-RequiredCapabilities @('CAPABILITY_1', 'CAPABILITY_2')
-Preset Exchange
if ($TestResult -eq $false) { return $true }

# 2. Get current state
Expand Down Expand Up @@ -235,13 +235,13 @@ Gate early using `Test-CIPPStandardLicense`. Never inspect raw SKU IDs.

```powershell
$TestResult = Test-CIPPStandardLicense -StandardName '<Name>' -TenantFilter $Tenant `
-RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE')
-Preset Exchange
if ($TestResult -eq $false) { return $true }
```

The function checks tenant capabilities, logs if missing, and automatically sets the `Set-CIPPStandardsCompareField` with `LicenseAvailable = $false`.

Reference existing standards in the same domain for common capability strings. The `Test-CIPPStandardLicense` function source documents the capability matching logic.
Use presets for common service families: `Exchange`, `SharePoint`, `Intune`, `Entra`, `EntraP2`, `Teams`, and `Compliance`. Use `-RequiredCapabilities` only when no preset matches, or combine it with `-Preset` when a standard needs a preset plus extra edge-case capabilities.

## API call patterns

Expand Down Expand Up @@ -337,7 +337,7 @@ The comment-based help `.NOTES` block drives the frontend UI. Each field maps to
| `RECOMMENDEDBY` | `recommendedBy` | `"CIS"`, `"CIPP"`, etc. |
| `MULTIPLE` | `multiple` | `True` for template-based standards (can have multiple instances) |
| `DISABLEDFEATURES` | `disabledFeatures` | JSON object disabling specific action modes |
| `REQUIREDCAPABILITIES` | *(discovery only)* | One capability string per line; parsed for standards metadata/JSON generation. The explicit `Test-CIPPStandardLicense` call in the function body still performs the actual runtime license check. |
| `REQUIREDCAPABILITIES` | *(discovery only)* | One capability string per line; generated from `Test-CIPPStandardLicense -Preset` and/or `-RequiredCapabilities` for standards metadata/JSON generation. The explicit `Test-CIPPStandardLicense` call in the function body still performs the actual runtime license check. |
| `UPDATECOMMENTBLOCK` | *(tooling only)* | Always include with the literal value `Run the Tools\Update-StandardsComments.ps1 script to update this comment block`. Signals the comment-update tooling to regenerate this block. |

### Valid CAT values
Expand Down
9 changes: 9 additions & 0 deletions Config/CIPPTimers.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,5 +264,14 @@
"RunOnProcessor": true,
"TZOffset": true,
"IsSystem": true
},
{
"Id": "a3b4c5d6-e7f8-4a9b-8c1d-2e3f4a5b6c7d",
"Command": "Start-ContainerUpdateCheck",
"Description": "Check for container image updates and optionally auto-restart",
"Cron": "0 0 * * * *",
"Priority": 30,
"RunOnProcessor": false,
"IsSystem": true
}
]
27 changes: 26 additions & 1 deletion Config/FeatureFlags.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,31 @@
"/tenant/standards/bpa-report",
"/tenant/standards/bpa-report/builder",
"/tenant/standards/bpa-report/view"
]
],
"Hidden": false
},
{
"Id": "SuperAdminNG",
"Name": "Super Admin",
"Description": "Additional super admin pages for CIPP instances (CIPP Users, SSO, Container management).",
"Enabled": false,
"AllowUserToggle": false,
"Timers": [],
"Endpoints": [
"ExecCIPPUsers",
"ListCIPPUsers",
"ExecSSOSetup",
"ExecContainerManagement",
"ListContainerLogs",
"ListWorkerHealth"
],
"Pages": [
"/cipp/advanced/super-admin/cipp-users",
"/cipp/advanced/super-admin/sso",
"/cipp/advanced/super-admin/container",
"/cipp/advanced/container-logs",
"/cipp/advanced/worker-health"
],
"Hidden": true
}
]
4 changes: 4 additions & 0 deletions Config/SAMManifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,10 @@
{
"id": "a94a502d-0281-4d15-8cd2-682ac9362c4c",
"type": "Role"
},
{
"id": "d72bdbf4-a59b-405c-8b04-5995895819ac",
"type": "Role"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function Push-CIPPDBCacheApplyBatch {
Write-Information "Aggregated $($AllTasks.Count) cache tasks from all tenants"

# Start a single flat orchestrator to execute all cache tasks
$TenantSuffix = if ($Item.Parameters.TenantFilter) { "_$($Item.Parameters.TenantFilter)" } else { '' }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'CIPPDBCacheExecute'
OrchestratorName = "CIPPDBCacheExecute$TenantSuffix"
Batch = @($AllTasks)
SkipLog = $true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,55 +27,55 @@ function Push-CIPPDBCacheData {
# Check tenant capabilities for license-specific features
$IntuneCapable = $false
try {
$IntuneCapable = Test-CIPPStandardLicense -StandardName 'IntuneLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') -SkipLog
$IntuneCapable = Test-CIPPStandardLicense -StandardName 'IntuneLicenseCheck' -TenantFilter $TenantFilter -Preset Intune -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Intune license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$ConditionalAccessCapable = $false
try {
$ConditionalAccessCapable = Test-CIPPStandardLicense -StandardName 'ConditionalAccessLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('AAD_PREMIUM', 'AAD_PREMIUM_P2') -SkipLog
$ConditionalAccessCapable = Test-CIPPStandardLicense -StandardName 'ConditionalAccessLicenseCheck' -TenantFilter $TenantFilter -Preset Entra -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Conditional Access license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$AzureADPremiumP2Capable = $false
try {
$AzureADPremiumP2Capable = Test-CIPPStandardLicense -StandardName 'AzureADPremiumP2LicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('AAD_PREMIUM_P2') -SkipLog
$AzureADPremiumP2Capable = Test-CIPPStandardLicense -StandardName 'AzureADPremiumP2LicenseCheck' -TenantFilter $TenantFilter -Preset EntraP2 -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Azure AD Premium P2 license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$ExchangeCapable = $false
try {
$ExchangeCapable = Test-CIPPStandardLicense -StandardName 'ExchangeLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_S_STANDARD_GOV', 'EXCHANGE_S_ENTERPRISE_GOV', 'EXCHANGE_LITE') -SkipLog
$ExchangeCapable = Test-CIPPStandardLicense -StandardName 'ExchangeLicenseCheck' -TenantFilter $TenantFilter -Preset Exchange -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Exchange license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$ComplianceCapable = $false
try {
$ComplianceCapable = Test-CIPPStandardLicense -StandardName 'ComplianceLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('RMS_S_PREMIUM', 'RMS_S_PREMIUM2', 'MIP_S_CLP1', 'MIP_S_CLP2') -SkipLog
$ComplianceCapable = Test-CIPPStandardLicense -StandardName 'ComplianceLicenseCheck' -TenantFilter $TenantFilter -Preset Compliance -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Compliance license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$SharePointCapable = $false
try {
$SharePointCapable = Test-CIPPStandardLicense -StandardName 'SharePointLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'SHAREPOINTENTERPRISE_EDU', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') -SkipLog
$SharePointCapable = Test-CIPPStandardLicense -StandardName 'SharePointLicenseCheck' -TenantFilter $TenantFilter -Preset SharePoint -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "SharePoint license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
}

$TeamsCapable = $false
try {
$TeamsCapable = Test-CIPPStandardLicense -StandardName 'TeamsLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1', 'Teams_Room_Standard') -SkipLog
$TeamsCapable = Test-CIPPStandardLicense -StandardName 'TeamsLicenseCheck' -TenantFilter $TenantFilter -Preset Teams -SkipLog
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Teams license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ function Push-OrchestratorBatchItems {
$Entities = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq '$($Item.Parameters.BatchId)'"
$BatchItems = [system.Collections.Generic.List[object]]::new()
$Entities | ForEach-Object {
$Item = $_.BatchItem | ConvertFrom-Json
$BatchItems.Add($Item)
$BatchItem = $_.BatchItem | ConvertFrom-Json
$BatchItems.Add($BatchItem)
}
Write-Information "Retrieved $($BatchItems.Count) batch items for BatchId: $($Item.Parameters.BatchId)"
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ function Push-CIPPStandard {
$StandardInfo.ConditionalAccessTemplateId = $Item.Settings.TemplateList.value
}

if (-not (Get-Command -Name $FunctionName -Module CIPPStandards -ErrorAction SilentlyContinue)) {
Write-LogMessage -tenant $Tenant -message "The standard $Standard was not found. This may have been deprecated or replaced with a new standard." -sev 'Warning' -API 'Standards'
Write-Warning "Function $FunctionName not found"
return
}

# Initialize AsyncLocal storage for thread-safe per-invocation context
# Uses $global: so Write-LogMessage (CIPPCore module) can read it across module boundaries
if (-not $global:CippStandardInfoStorage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function Push-CIPPStandardsList {

if ($IntuneTemplateFound) {
# Perform license check
$TestResult = Test-CIPPStandardLicense -StandardName 'IntuneTemplate_general' -TenantFilter $TenantFilter -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1')
$TestResult = Test-CIPPStandardLicense -StandardName 'IntuneTemplate_general' -TenantFilter $TenantFilter -Preset Intune

if (-not $TestResult) {
# Remove IntuneTemplate standards and set compare fields
Expand Down Expand Up @@ -249,7 +249,7 @@ function Push-CIPPStandardsList {

$CAStandardFound = ($ComputedStandards.Keys.Where({ $_ -like '*ConditionalAccessTemplate*' }, 'First').Count -gt 0)
if ($CAStandardFound) {
$TestResult = Test-CIPPStandardLicense -StandardName 'ConditionalAccessTemplate_general' -TenantFilter $TenantFilter -RequiredCapabilities @('AAD_PREMIUM', 'AAD_PREMIUM_P2')
$TestResult = Test-CIPPStandardLicense -StandardName 'ConditionalAccessTemplate_general' -TenantFilter $TenantFilter -Preset Entra
if (-not $TestResult) {
$CAKeys = @($ComputedStandards.Keys | Where-Object { $_ -like '*ConditionalAccessTemplate*' })
$BulkFields = [System.Collections.Generic.List[object]]::new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ function Push-CIPPTestsApplyBatch {
Write-Information "Aggregated $($AllTasks.Count) test tasks from all tenants"

# Start a single flat orchestrator to execute all test tasks
$TenantSuffix = if ($Item.Parameters.TenantFilter) { "_$($Item.Parameters.TenantFilter)" } else { '' }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'CIPPTestsExecute'
OrchestratorName = "CIPPTestsExecute$TenantSuffix"
Batch = @($AllTasks)
SkipLog = $true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,7 @@ function Get-CIPPAlertIntunePolicyConflicts {
return
}

$HasLicense = Test-CIPPStandardLicense -StandardName 'IntunePolicyStatus' -TenantFilter $TenantFilter -RequiredCapabilities @(
'INTUNE_A',
'MDM_Services',
'EMS',
'SCCM',
'MICROSOFTINTUNEPLAN1'
)

$HasLicense = Test-CIPPStandardLicense -StandardName 'IntunePolicyStatus' -TenantFilter $TenantFilter -Preset Intune
if (-not $HasLicense) {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@
if ($Rerun) {
return
}
$HasLicense = Test-CIPPStandardLicense -StandardName 'QuarantineReleaseRequests' -TenantFilter $TenantFilter -RequiredCapabilities @(
'EXCHANGE_S_STANDARD',
'EXCHANGE_S_ENTERPRISE',
'EXCHANGE_S_STANDARD_GOV',
'EXCHANGE_S_ENTERPRISE_GOV',
'EXCHANGE_LITE'
)
$HasLicense = Test-CIPPStandardLicense -StandardName 'QuarantineReleaseRequests' -TenantFilter $TenantFilter -Preset Exchange

if (-not $HasLicense) {
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
function Get-CIPPAlertUserReportedPhishing {
<#
.FUNCTIONALITY
Entrypoint
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[Alias('input')]
$InputValue,
$TenantFilter
)

try {
[int]$HoursBack = if ($InputValue.HoursBack) { [int]$InputValue.HoursBack } else { 24 }
$Since = (Get-Date).AddHours(-$HoursBack).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')

$Submissions = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/security/threatSubmission/emailThreats?`$filter=createdDateTime ge $Since" -tenantid $TenantFilter -AsApp $true

$AlertData = foreach ($Submission in $Submissions) {
# Only include user-reported submissions
if ($Submission.source -ne 'user') { continue }

[PSCustomObject]@{
ReportedBy = $Submission.createdBy.user.displayName
ReporterEmail = $Submission.createdBy.user.email
Sender = $Submission.sender
Subject = $Submission.emailSubject
Category = $Submission.category
ReceivedDateTime = $Submission.receivedDateTime
ReportedAt = $Submission.createdDateTime
Status = $Submission.status
ResultCategory = $Submission.result.category
ResultDetail = $Submission.result.detail
InternetMsgId = $Submission.internetMessageId
SubmissionId = $Submission.id
Tenant = $TenantFilter
}
}
if ($AlertData) {
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
}
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-AlertMessage -message "User-reported phishing alert failed for $($TenantFilter): $($ErrorMessage.NormalizedError)" -tenant $TenantFilter -LogData $ErrorMessage
}
}
Loading