Skip to content

Commit 1dd59c5

Browse files
authored
Merge pull request #46 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 6c1da76 + 9ced3b8 commit 1dd59c5

151 files changed

Lines changed: 1097 additions & 96 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ function Get-GraphRequestList {
8080
[string]$ReverseTenantLookupProperty = 'tenantId',
8181
[boolean]$AsApp = $false,
8282
[string]$Caller = 'Get-GraphRequestList',
83-
[switch]$UseBatchExpand
83+
[switch]$UseBatchExpand,
84+
[switch]$RawJsonArray
8485
)
8586

8687
$SingleTenantThreshold = 8000
@@ -423,6 +424,22 @@ function Get-GraphRequestList {
423424
}
424425
}
425426
} else {
427+
if ($RawJsonArray.IsPresent) {
428+
# Fast path: concatenate raw JSON strings without deserialization. This is much faster and uses less memory when no post-processing is needed, especially for large datasets.
429+
$JsonParts = [System.Collections.Generic.List[string]]::new()
430+
foreach ($Row in $Rows) {
431+
if ($Row.Data) {
432+
$d = $Row.Data.Trim()
433+
if ($d.Length -gt 2 -and $d[0] -eq '[' -and $d[-1] -eq ']') {
434+
$JsonParts.Add($d.Substring(1, $d.Length - 2))
435+
} elseif ($d.Length -gt 0 -and $d -ne '[]') {
436+
$JsonParts.Add($d)
437+
}
438+
}
439+
}
440+
return '[' + ($JsonParts -join ',') + ']'
441+
}
442+
426443
foreach ($Row in $Rows) {
427444
if ($Row.Data) {
428445
try {

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,38 @@ function Invoke-ListGraphRequest {
122122

123123
$Metadata = $GraphRequestParams
124124

125+
# Use raw JSON passthrough for AllTenants cached results when no post-processing is needed.
126+
$UseRawJson = $Request.Query.TenantFilter -eq 'AllTenants' -and
127+
-not $Request.Query.ListProperties -and
128+
-not $Request.Query.Sort -and
129+
-not $Request.Query.QueueId
130+
125131
try {
132+
if ($UseRawJson) {
133+
$GraphRequestParams.RawJsonArray = $true
134+
}
126135
$Results = Get-GraphRequestList @GraphRequestParams
127136

128137
if ($script:LastGraphResponseHeaders) {
129138
$Metadata.GraphHeaders = $script:LastGraphResponseHeaders
130139
}
131140

141+
# RawJsonArray returns a JSON string directly — skip object-level processing
142+
if ($UseRawJson -and $Results -is [string] -and $Results.StartsWith('[')) {
143+
if ($Request.Headers.'x-ms-coldstart' -eq 1) {
144+
$Metadata.ColdStart = $true
145+
}
146+
$MetadataJson = ConvertTo-Json -InputObject $Metadata -Depth 5 -Compress
147+
$GraphRequestData = '{"Results":' + $Results + ',"Metadata":' + $MetadataJson + '}'
148+
$StatusCode = [HttpStatusCode]::OK
149+
150+
return ([HttpResponseContext]@{
151+
StatusCode = $StatusCode
152+
ContentType = 'application/json'
153+
Body = $GraphRequestData
154+
})
155+
}
156+
132157
if ($Results | Where-Object { $_.PSObject.Properties.Name -contains 'nextLink' }) {
133158
if (![string]::IsNullOrEmpty($Results.nextLink) -and $Request.Query.TenantFilter -ne 'AllTenants') {
134159
Write-Host "NextLink: $($Results.nextLink | Where-Object { $_ } | Select-Object -Last 1)"

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,53 @@ function Invoke-ExecQuarantineManagement {
1212
# Interact with query parameters or the body of the request.
1313
try {
1414
$TenantFilter = $Request.Body.tenantFilter | Select-Object -First 1
15-
$params = @{
16-
AllowSender = [boolean]$Request.Body.AllowSender
17-
ReleaseToAll = $true
18-
ActionType = ($Request.Body.Type | Select-Object -First 1)
15+
$ActionType = $Request.Body.Type | Select-Object -First 1
16+
$AllowSender = $Request.Body.AllowSender -eq $true
17+
$params = @{}
18+
19+
if ($ActionType -eq 'Release') {
20+
$params['ReleaseToAll'] = $true
21+
} else {
22+
$params['ActionType'] = $ActionType
1923
}
24+
2025
if ($Request.Body.Identity -is [string]) {
2126
$params['Identity'] = $Request.Body.Identity
2227
} else {
2328
$params['Identities'] = $Request.Body.Identity
29+
$params['Identity'] = '000'
2430
}
25-
New-ExoRequest -tenantid $TenantFilter -cmdlet 'Release-QuarantineMessage' -cmdParams $Params
31+
New-ExoRequest -tenantid $TenantFilter -cmdlet 'Release-QuarantineMessage' -cmdParams $params
32+
33+
# AllowSender via HostedContentFilterPolicy since -AllowSender switch fails in REST API
34+
if ($AllowSender) {
35+
try {
36+
$SenderAddress = $Request.Body.SenderAddress
37+
$PolicyName = $Request.Body.PolicyName
38+
if ([string]::IsNullOrEmpty($SenderAddress) -or [string]::IsNullOrEmpty($PolicyName)) {
39+
if ($Request.Body.Identity -is [string]) {
40+
$QuarantineMessage = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-QuarantineMessage' -cmdParams @{ Identity = $Request.Body.Identity }
41+
if ([string]::IsNullOrEmpty($SenderAddress)) { $SenderAddress = $QuarantineMessage.SenderAddress }
42+
if ([string]::IsNullOrEmpty($PolicyName)) { $PolicyName = $QuarantineMessage.PolicyName }
43+
}
44+
}
45+
if (-not [string]::IsNullOrEmpty($SenderAddress) -and -not [string]::IsNullOrEmpty($PolicyName)) {
46+
$CurrentPolicy = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-HostedContentFilterPolicy' -cmdParams @{ Identity = $PolicyName }
47+
$CurrentSenders = @($CurrentPolicy.AllowedSenders.Sender.Address | Where-Object { $_ })
48+
if ($SenderAddress -notin $CurrentSenders) {
49+
$UpdatedSenders = @($CurrentSenders + $SenderAddress)
50+
New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-HostedContentFilterPolicy' -cmdParams @{
51+
Identity = $PolicyName
52+
AllowedSenders = $UpdatedSenders
53+
}
54+
}
55+
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message "Added $SenderAddress to allowed senders on policy $PolicyName" -Sev 'Info'
56+
}
57+
} catch {
58+
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message "Failed to add sender to allow list: $($_.Exception.Message)" -Sev 'Error' -LogData $_
59+
}
60+
}
61+
2662
$Results = [pscustomobject]@{'Results' = "Successfully processed $($Request.Body.Identity)" }
2763
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message "Successfully processed Quarantine ID $($Request.Body.Identity)" -Sev 'Info'
2864
} catch {

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ function Invoke-CIPPStandardActivityBasedTimeout {
1616
"CIS M365 5.0 (1.3.2)"
1717
"spo_idle_session_timeout"
1818
"NIST CSF 2.0 (PR.AA-03)"
19+
"ZTNA21813"
20+
"ZTNA21814"
21+
"ZTNA21815"
1922
EXECUTIVETEXT
2023
Automatically logs out inactive users from Microsoft 365 applications after a specified time period to prevent unauthorized access to company data on unattended devices. This security measure protects against data breaches when employees leave workstations unlocked.
2124
ADDEDCOMPONENT

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ function Invoke-CIPPStandardAddDKIM {
1414
Exchange Standards
1515
TAG
1616
"CIS M365 5.0 (2.1.9)"
17+
"ORCA108"
18+
"CISAMSEXO31"
1719
EXECUTIVETEXT
1820
Enables email authentication technology that digitally signs outgoing emails to verify they actually came from your organization. This prevents email spoofing, improves email deliverability, and protects the company's reputation by ensuring recipients can trust emails from your domains.
1921
ADDEDCOMPONENT
@@ -26,6 +28,12 @@ function Invoke-CIPPStandardAddDKIM {
2628
RECOMMENDEDBY
2729
"CIS"
2830
"CIPP"
31+
REQUIREDCAPABILITIES
32+
"EXCHANGE_S_STANDARD"
33+
"EXCHANGE_S_ENTERPRISE"
34+
"EXCHANGE_S_STANDARD_GOV"
35+
"EXCHANGE_S_ENTERPRISE_GOV"
36+
"EXCHANGE_LITE"
2937
UPDATECOMMENTBLOCK
3038
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
3139
.LINK

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAddDMARCToMOERA.ps1

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ function Invoke-CIPPStandardAddDMARCToMOERA {
77
.SYNOPSIS
88
(Label) Enables DMARC on MOERA (onmicrosoft.com) domains
99
.DESCRIPTION
10-
(Helptext) Note: requires 'Domain Name Administrator' GDAP role. This should be enabled even if the MOERA (onmicrosoft.com) domains is not used for sending. Enabling this prevents email spoofing. The default value is 'v=DMARC1; p=reject;' recommended because the domain is only used within M365 and reporting is not needed. Omitting pct tag default to 100%
11-
(DocsDescription) Note: requires 'Domain Name Administrator' GDAP role. Adds a DMARC record to MOERA (onmicrosoft.com) domains. This should be enabled even if the MOERA (onmicrosoft.com) domains is not used for sending. Enabling this prevents email spoofing. The default record is 'v=DMARC1; p=reject;' recommended because the domain is only used within M365 and reporting is not needed. Omitting pct tag default to 100%
10+
(Helptext) ** Remediation is not available ** Note: requires 'Domain Name Administrator' GDAP role. This should be enabled even if the MOERA (onmicrosoft.com) domains is not used for sending. Enabling this prevents email spoofing. The default value is 'v=DMARC1; p=reject;' recommended because the domain is only used within M365 and reporting is not needed. Omitting pct tag default to 100%
11+
(DocsDescription) \*\* Remediation is not available \*\* Note: requires 'Domain Name Administrator' GDAP role. Adds a DMARC record to MOERA (onmicrosoft.com) domains. This should be enabled even if the MOERA (onmicrosoft.com) domains is not used for sending. Enabling this prevents email spoofing. The default record is 'v=DMARC1; p=reject;' recommended because the domain is only used within M365 and reporting is not needed. Omitting pct tag default to 100%
1212
.NOTES
1313
CAT
1414
Global Standards
@@ -29,6 +29,8 @@ function Invoke-CIPPStandardAddDMARCToMOERA {
2929
RECOMMENDEDBY
3030
"CIS"
3131
"Microsoft"
32+
DISABLEDFEATURES
33+
{"remediate":true}
3234
UPDATECOMMENTBLOCK
3335
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
3436
.LINK

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,32 @@ function Invoke-CIPPStandardAntiPhishPolicy {
2222
"mdo_phishthresholdlevel"
2323
"CIS M365 5.0 (2.1.7)"
2424
"NIST CSF 2.0 (DE.CM-09)"
25+
"ORCA104"
26+
"ORCA115"
27+
"ORCA180"
28+
"ORCA220"
29+
"ORCA221"
30+
"ORCA222"
31+
"ORCA223"
32+
"ORCA228"
33+
"ORCA229"
34+
"ORCA230"
35+
"ORCA233"
36+
"ORCA234"
37+
"ORCA235"
38+
"ORCA239"
39+
"ORCA242"
40+
"ORCA243"
41+
"ORCA244"
42+
"ZTNA21784"
43+
"ZTNA21817"
44+
"ZTNA21819"
45+
"CISAMSEXO111"
46+
"CISAMSEXO112"
47+
"CISAMSEXO113"
2548
ADDEDCOMPONENT
2649
{"type":"textField","name":"standards.AntiPhishPolicy.name","label":"Policy Name","required":true,"defaultValue":"CIPP Default Anti-Phishing Policy"}
27-
{"type":"number","label":"Phishing email threshold. (Default 1)","name":"standards.AntiPhishPolicy.PhishThresholdLevel","defaultValue":1}
50+
{"type":"number","label":"Phishing email threshold. (Default 1)","name":"standards.AntiPhishPolicy.PhishThresholdLevel","defaultValue":1,"validators":{"min":{"value":1,"message":"Minimum value is 1"},"max":{"value":4,"message":"Maximum value is 4"}}}
2851
{"type":"switch","label":"Show first contact safety tip","name":"standards.AntiPhishPolicy.EnableFirstContactSafetyTips","defaultValue":true}
2952
{"type":"switch","label":"Show user impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarUsersSafetyTips","defaultValue":true}
3053
{"type":"switch","label":"Show domain impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarDomainsSafetyTips","defaultValue":true}
@@ -45,6 +68,12 @@ function Invoke-CIPPStandardAntiPhishPolicy {
4568
Set-AntiPhishPolicy or New-AntiPhishPolicy
4669
RECOMMENDEDBY
4770
"CIS"
71+
REQUIREDCAPABILITIES
72+
"EXCHANGE_S_STANDARD"
73+
"EXCHANGE_S_ENTERPRISE"
74+
"EXCHANGE_S_STANDARD_GOV"
75+
"EXCHANGE_S_ENTERPRISE_GOV"
76+
"EXCHANGE_LITE"
4877
UPDATECOMMENTBLOCK
4978
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
5079
.LINK

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ function Invoke-CIPPStandardAntiSpamSafeList {
2525
POWERSHELLEQUIVALENT
2626
Set-HostedConnectionFilterPolicy "Default" -EnableSafeList \$true
2727
RECOMMENDEDBY
28+
REQUIREDCAPABILITIES
29+
"EXCHANGE_S_STANDARD"
30+
"EXCHANGE_S_ENTERPRISE"
31+
"EXCHANGE_S_STANDARD_GOV"
32+
"EXCHANGE_S_ENTERPRISE_GOV"
33+
"EXCHANGE_LITE"
2834
UPDATECOMMENTBLOCK
2935
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
3036
.LINK

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAppManagementPolicy.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ function Invoke-CIPPStandardAppManagementPolicy {
1616
EXECUTIVETEXT
1717
Enforces credential restrictions on application registrations and service principals to limit how secrets and certificates are created and how long they remain valid. This reduces the risk of long-lived or unmanaged credentials being used to access your tenant.
1818
ADDEDCOMPONENT
19-
{"type":"autoComplete","multiple":false,"creatable":false,"label":"Password Addition","name":"standards.AppManagementPolicy.passwordCredentialsPasswordAddition","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]}
20-
{"type":"autoComplete","multiple":false,"creatable":false,"label":"Custom Password","name":"standards.AppManagementPolicy.passwordCredentialsCustomPasswordAddition","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]}
21-
{"type":"number","label":"Password Credentials Max Lifetime (Days)","name":"standards.AppManagementPolicy.passwordCredentialsMaxLifetime"}
22-
{"type":"number","label":"Key Credentials Max Lifetime (Days)","name":"standards.AppManagementPolicy.keyCredentialsMaxLifetime"}
19+
{"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AppManagementPolicy.passwordCredentialsPasswordAddition","label":"Disable Password Addition","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]}
20+
{"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AppManagementPolicy.passwordCredentialsCustomPasswordAddition","label":"Disable Custom Password","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]}
21+
{"type":"number","required":false,"name":"standards.AppManagementPolicy.passwordCredentialsMaxLifetime","label":"Password Credentials Max Lifetime (Days)"}
22+
{"type":"number","required":false,"name":"standards.AppManagementPolicy.keyCredentialsMaxLifetime","label":"Key Credentials Max Lifetime (Days)"}
2323
IMPACT
2424
Medium Impact
2525
ADDEDDATE

Modules/CIPPStandards/Public/Standards/Invoke-CIPPStandardAssignmentFilterTemplate.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ function Invoke-CIPPStandardAssignmentFilterTemplate {
2424
Creates standardized assignment filters with predefined settings. These templates ensure consistent assignment filter configurations across the organization, streamlining assignment management.
2525
ADDEDCOMPONENT
2626
{"type":"autoComplete","name":"assignmentFilterTemplate","label":"Select Assignment Filter Template","api":{"url":"/api/ListAssignmentFilterTemplates","labelField":"Displayname","altLabelField":"displayName","valueField":"GUID","queryKey":"ListAssignmentFilterTemplates"}}
27+
REQUIREDCAPABILITIES
28+
"INTUNE_A"
29+
"MDM_Services"
30+
"EMS"
31+
"SCCM"
32+
"MICROSOFTINTUNEPLAN1"
2733
UPDATECOMMENTBLOCK
2834
Run the Tools\Update-StandardsComments.ps1 script to update this comment block
2935
.LINK

0 commit comments

Comments
 (0)