Skip to content

Commit c2cc6a8

Browse files
authored
Merge pull request #597 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 96d9813 + 5d4d0c4 commit c2cc6a8

File tree

7 files changed

+165
-70
lines changed

7 files changed

+165
-70
lines changed

Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,56 @@ function Get-CIPPAlertNewAppApproval {
1212
$TenantFilter,
1313
$Headers
1414
)
15-
try {
16-
$Approvals = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests?`$filter=userConsentRequests/any (u:u/status eq 'InProgress')" -tenantid $TenantFilter
17-
if ($Approvals.count -gt 0) {
18-
$TenantGUID = (Get-Tenants -TenantFilter $TenantFilter -SkipDomains).customerId
19-
$AlertData = [System.Collections.Generic.List[PSCustomObject]]::new()
20-
foreach ($App in $Approvals) {
21-
$userConsentRequests = New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identityGovernance/appConsent/appConsentRequests/$($App.id)/userConsentRequests" -tenantid $TenantFilter
22-
$userConsentRequests | ForEach-Object {
23-
$consentUrl = if ($App.consentType -eq 'Static') {
24-
# if something is going wrong here you've probably stumbled on a fourth variation - rvdwegen
25-
"https://login.microsoftonline.com/$($TenantFilter)/adminConsent?client_id=$($App.appId)&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
26-
} elseif ($App.pendingScopes.displayName) {
27-
"https://login.microsoftonline.com/$($TenantFilter)/v2.0/adminConsent?client_id=$($App.appId)&scope=$($App.pendingScopes.displayName -Join(' '))&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
28-
} else {
29-
"https://login.microsoftonline.com/$($TenantFilter)/adminConsent?client_id=$($App.appId)&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
15+
16+
Measure-CippTask -TaskName 'NewAppApprovalAlert' -EventName 'CIPP.AlertProfile' -Script {
17+
try {
18+
$Approvals = Measure-CippTask -TaskName 'GetAppConsentRequests' -EventName 'CIPP.AlertProfile' -Script {
19+
New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests?`$top=100&`$filter=userConsentRequests/any (u:u/status eq 'InProgress')" -tenantid $TenantFilter
20+
}
21+
22+
if ($Approvals.count -gt 0) {
23+
Measure-CippTask -TaskName 'ProcessApprovals' -EventName 'CIPP.AlertProfile' -Script {
24+
$TenantGUID = (Get-Tenants -TenantFilter $TenantFilter -SkipDomains).customerId
25+
$AlertData = [System.Collections.Generic.List[PSCustomObject]]::new()
26+
27+
foreach ($App in $Approvals) {
28+
$userConsentRequests = Measure-CippTask -TaskName 'GetUserConsentRequests' -EventName 'CIPP.AlertProfile' -Script {
29+
New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identityGovernance/appConsent/appConsentRequests/$($App.id)/userConsentRequests" -tenantid $TenantFilter
30+
}
31+
32+
$userConsentRequests | ForEach-Object {
33+
$consentUrl = if ($App.consentType -eq 'Static') {
34+
# if something is going wrong here you've probably stumbled on a fourth variation - rvdwegen
35+
"https://login.microsoftonline.com/$($TenantFilter)/adminConsent?client_id=$($App.appId)&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
36+
} elseif ($App.pendingScopes.displayName) {
37+
"https://login.microsoftonline.com/$($TenantFilter)/v2.0/adminConsent?client_id=$($App.appId)&scope=$($App.pendingScopes.displayName -Join(' '))&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
38+
} else {
39+
"https://login.microsoftonline.com/$($TenantFilter)/adminConsent?client_id=$($App.appId)&bf_id=$($App.id)&redirect_uri=https://entra.microsoft.com/TokenAuthorize"
40+
}
41+
42+
$Message = [PSCustomObject]@{
43+
RequestId = $_.id
44+
AppName = $App.appDisplayName
45+
RequestUser = $_.createdBy.user.userPrincipalName
46+
Reason = $_.reason
47+
RequestDate = $_.createdDateTime
48+
Status = $_.status # Will allways be InProgress as we filter to only get these but this will reduce confusion when an alert is generated
49+
AppId = $App.appId
50+
Scopes = ($App.pendingScopes.displayName -join ', ')
51+
ConsentURL = $consentUrl
52+
Tenant = $TenantFilter
53+
TenantId = $TenantGUID
54+
}
55+
$AlertData.Add($Message)
56+
}
3057
}
3158

32-
$Message = [PSCustomObject]@{
33-
RequestId = $_.id
34-
AppName = $App.appDisplayName
35-
RequestUser = $_.createdBy.user.userPrincipalName
36-
Reason = $_.reason
37-
RequestDate = $_.createdDateTime
38-
Status = $_.status # Will allways be InProgress as we filter to only get these but this will reduce confusion when an alert is generated
39-
AppId = $App.appId
40-
Scopes = ($App.pendingScopes.displayName -join ', ')
41-
ConsentURL = $consentUrl
42-
Tenant = $TenantFilter
43-
TenantId = $TenantGUID
59+
Measure-CippTask -TaskName 'WriteAlertTrace' -EventName 'CIPP.AlertProfile' -Script {
60+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
4461
}
45-
$AlertData.Add($Message)
4662
}
4763
}
48-
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
64+
} catch {
4965
}
50-
} catch {
5166
}
5267
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
function Get-CIPPAlertQuarantineReleaseRequests {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
[CmdletBinding()]
7+
param (
8+
[Parameter(Mandatory = $false)]
9+
[Alias('input')]
10+
$InputValue,
11+
$TenantFilter
12+
)
13+
14+
$HasLicense = Test-CIPPStandardLicense -StandardName 'QuarantineReleaseRequests' -TenantFilter $TenantFilter -RequiredCapabilities @(
15+
'EXCHANGE_S_STANDARD',
16+
'EXCHANGE_S_ENTERPRISE',
17+
'EXCHANGE_S_STANDARD_GOV',
18+
'EXCHANGE_S_ENTERPRISE_GOV',
19+
'EXCHANGE_LITE'
20+
)
21+
22+
if (-not $HasLicense) {
23+
return
24+
}
25+
26+
try {
27+
$RequestedReleases = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-QuarantineMessage' -cmdParams @{ PageSize = 1000; ReleaseStatus = 'Requested' } -ErrorAction Stop | Select-Object -ExcludeProperty *data.type*
28+
29+
if ($RequestedReleases) {
30+
# Get the CIPP URL for the Quarantine link
31+
$CippConfigTable = Get-CippTable -tablename Config
32+
$CippConfig = Get-CIPPAzDataTableEntity @CippConfigTable -Filter "PartitionKey eq 'InstanceProperties' and RowKey eq 'CIPPURL'"
33+
$CIPPUrl = 'https://{0}' -f $CippConfig.Value
34+
35+
$AlertData = foreach ($Message in $RequestedReleases) {
36+
[PSCustomObject]@{
37+
Identity = $Message.Identity
38+
MessageId = $Message.MessageId
39+
Subject = $Message.Subject
40+
SenderAddress = $Message.SenderAddress
41+
RecipientAddress = $Message.RecipientAddress
42+
Type = $Message.Type
43+
PolicyName = $Message.PolicyName
44+
ReleaseStatus = $Message.ReleaseStatus
45+
ReceivedTime = $Message.ReceivedTime
46+
QuarantineViewUrl = "$CIPPUrl/email/administration/quarantine?tenantFilter=$TenantFilter"
47+
Tenant = $TenantFilter
48+
}
49+
}
50+
51+
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
52+
}
53+
} catch {
54+
Write-AlertMessage -tenant $TenantFilter -message "QuarantineReleaseRequests: $(Get-NormalizedError -message $_.Exception.Message)"
55+
}
56+
}

Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,21 @@ function New-GraphGetRequest {
8787
$RequestSuccessful = $true
8888

8989
if ($ReturnRawResponse) {
90-
if (Test-Json -Json $Data.Content) {
91-
$Content = $Data.Content | ConvertFrom-Json
92-
} else {
90+
try {
91+
if ($Data.Content -and (Test-Json -Json $Data.Content -ErrorAction Stop)) {
92+
$Content = $Data.Content | ConvertFrom-Json
93+
} else {
94+
$Content = $Data.Content
95+
}
96+
} catch {
9397
$Content = $Data.Content
9498
}
9599

96-
$Data | Select-Object -Property StatusCode, StatusDescription, @{Name = 'Content'; Expression = { $Content } }
100+
[PSCustomObject]@{
101+
StatusCode = $Data.StatusCode
102+
StatusDescription = $Data.StatusDescription
103+
Content = $Content
104+
}
97105
$nextURL = $null
98106
} elseif ($CountOnly) {
99107
$Data.'@odata.count'

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

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ function Invoke-CIPPStandardAddDMARCToMOERA {
5151

5252
$CurrentInfo = $Domains | ForEach-Object {
5353
# Get current DNS records that matches _dmarc hostname and TXT type
54-
$CurrentRecords = New-GraphGetRequest -scope 'https://admin.microsoft.com/.default' -TenantID $Tenant -Uri "https://admin.microsoft.com/admin/api/Domains/Records?domainName=$($_.Name)" | Select-Object -ExpandProperty DnsRecords | Where-Object { $_.HostName -eq $RecordModel.HostName -and $_.Type -eq $RecordModel.Type }
54+
$RecordsResponse = New-GraphGetRequest -scope 'https://admin.microsoft.com/.default' -TenantID $Tenant -Uri "https://admin.microsoft.com/admin/api/Domains/Records?domainName=$($_.Name)" -extraHeaders @{'User-Agent' = 'CIPP/1.0' }
55+
$AllRecords = $RecordsResponse | Select-Object -ExpandProperty DnsRecords
56+
$CurrentRecords = $AllRecords | Where-Object { $_.HostName -eq '_dmarc' -and $_.Type -eq 'TXT' }
57+
Write-Information "Found $($CurrentRecords.count) DMARC records for domain $($_.Name)"
5558

5659
if ($CurrentRecords.count -eq 0) {
5760
#record not found, return a model with Match set to false
@@ -87,8 +90,8 @@ function Invoke-CIPPStandardAddDMARCToMOERA {
8790
}
8891
}
8992
}
90-
# Check if match is true and there is only one DMARC record for the domain
91-
$StateIsCorrect = $false -notin $CurrentInfo.Match -and $CurrentInfo.Count -eq 1
93+
# Check if match is true and there is only one DMARC record for each domain
94+
$StateIsCorrect = $false -notin $CurrentInfo.Match -and $CurrentInfo.Count -eq $Domains.Count
9295
} catch {
9396
$ErrorMessage = Get-CippException -Exception $_
9497
if ($_.Exception.Message -like '*403*') {
@@ -107,13 +110,29 @@ function Invoke-CIPPStandardAddDMARCToMOERA {
107110
# Loop through each domain and set the DMARC record, existing misconfigured records and duplicates will be deleted
108111
foreach ($Domain in ($CurrentInfo | Sort-Object -Property DomainName -Unique)) {
109112
try {
110-
foreach ($Record in ($CurrentInfo | Where-Object -Property DomainName -EQ $Domain.DomainName)) {
113+
$DomainRecords = @($CurrentInfo | Where-Object -Property DomainName -EQ $Domain.DomainName)
114+
$HasMatchingRecord = $false
115+
116+
# First, delete any non-matching records
117+
foreach ($Record in $DomainRecords) {
111118
if ($Record.CurrentRecord) {
112-
New-GraphPOSTRequest -tenantid $tenant -scope 'https://admin.microsoft.com/.default' -Uri "https://admin.microsoft.com/admin/api/Domains/Record?domainName=$($Domain.DomainName)" -Body ($Record.CurrentRecord | ConvertTo-Json -Compress) -AddedHeaders @{'x-http-method-override' = 'Delete' }
113-
Write-LogMessage -API 'Standards' -tenant $tenant -message "Deleted incorrect DMARC record for domain $($Domain.DomainName)" -sev Info
119+
if ($Record.Match -eq $false) {
120+
# Delete incorrect record
121+
New-GraphPOSTRequest -tenantid $tenant -scope 'https://admin.microsoft.com/.default' -Uri "https://admin.microsoft.com/admin/api/Domains/Record?domainName=$($Domain.DomainName)" -Body ($Record.CurrentRecord | ConvertTo-Json -Compress) -AddedHeaders @{'x-http-method-override' = 'Delete' }
122+
Write-LogMessage -API 'Standards' -tenant $tenant -message "Deleted incorrect DMARC record for domain $($Domain.DomainName)" -sev Info
123+
} else {
124+
# Record already matches, no need to add
125+
$HasMatchingRecord = $true
126+
}
114127
}
128+
}
129+
130+
# Only add the record if we don't already have a matching one
131+
if (-not $HasMatchingRecord) {
115132
New-GraphPOSTRequest -tenantid $tenant -scope 'https://admin.microsoft.com/.default' -type 'PUT' -Uri "https://admin.microsoft.com/admin/api/Domains/Record?domainName=$($Domain.DomainName)" -Body (@{RecordModel = $RecordModel } | ConvertTo-Json -Compress)
116133
Write-LogMessage -API 'Standards' -tenant $tenant -message "Set DMARC record for domain $($Domain.DomainName)" -sev Info
134+
} else {
135+
Write-LogMessage -API 'Standards' -tenant $tenant -message "DMARC record already correctly set for domain $($Domain.DomainName)" -sev Info
117136
}
118137
} catch {
119138
$ErrorMessage = Get-CippException -Exception $_

Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ function Invoke-CIPPStandardEnableMailboxAuditing {
4949

5050
try {
5151
$AuditState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').AuditDisabled
52-
}
53-
catch {
52+
} catch {
5453
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
5554
Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the EnableMailboxAuditing state for $Tenant. Error: $ErrorMessage" -Sev Error
5655
return
@@ -71,25 +70,30 @@ function Invoke-CIPPStandardEnableMailboxAuditing {
7170
$LogMessage = 'Tenant level mailbox audit already enabled. '
7271
}
7372

74-
# Check for mailbox audit on all mailboxes. Enable for all that it's not enabled for
75-
$Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{filter = "auditenabled -eq 'False'" } -useSystemMailbox $true -Select 'AuditEnabled,UserPrincipalName'
76-
$Request = $mailboxes | ForEach-Object {
77-
@{
78-
CmdletInput = @{
79-
CmdletName = 'Set-Mailbox'
80-
Parameters = @{Identity = $_.UserPrincipalName; AuditEnabled = $true }
81-
}
82-
}
83-
}
73+
# Commented out because MS recommends NOT doing this anymore. From docs: https://learn.microsoft.com/en-us/purview/audit-mailboxes#verify-mailbox-auditing-on-by-default-is-turned-on
74+
# When you turn on mailbox auditing on by default for the organization, the AuditEnabled property for affected mailboxes doesn't change from False to True. In other words, mailbox auditing on by default ignores the AuditEnabled property on mailboxes.
75+
# Auditing is automatically turned on when you create a new mailbox. You don't need to manually enable mailbox auditing for new users.
76+
# You don't need to manage the mailbox actions that are audited. A predefined set of mailbox actions are audited by default for each sign-in type (Admin, Delegate, and Owner).
77+
# When Microsoft releases a new mailbox action, the action might be added automatically to the list of mailbox actions that are audited by default (subject to the user having the appropriate license). This result means you don't need to add new actions on mailboxes as they're released.
78+
# You have a consistent mailbox auditing policy across your organization because you're auditing the same actions for all mailboxes.
79+
#$Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{filter = "auditenabled -eq 'False'" } -useSystemMailbox $true -Select 'AuditEnabled,UserPrincipalName'
80+
#$Request = $mailboxes | ForEach-Object {
81+
# @{
82+
# CmdletInput = @{
83+
# CmdletName = 'Set-Mailbox'
84+
# Parameters = @{Identity = $_.UserPrincipalName; AuditEnabled = $true }
85+
# }
86+
#}
87+
#}
8488

85-
$BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
86-
$BatchResults | ForEach-Object {
87-
if ($_.error) {
88-
$ErrorMessage = Get-NormalizedError -Message $_.error
89-
Write-Host "Failed to enable user level mailbox audit for $($_.target). Error: $ErrorMessage"
90-
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to enable user level mailbox audit for $($_.target). Error: $ErrorMessage" -sev Error
91-
}
92-
}
89+
#$BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request)
90+
#$BatchResults | ForEach-Object {
91+
# if ($_.error) {
92+
# $ErrorMessage = Get-NormalizedError -Message $_.error
93+
# Write-Host "Failed to enable user level mailbox audit for $($_.target). Error: $ErrorMessage"
94+
# Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to enable user level mailbox audit for $($_.target). Error: $ErrorMessage" -sev Error
95+
# }
96+
#}
9397

9498
# Disable audit bypass for all mailboxes that have it enabled
9599

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"CIPP-API",
1515
"CIPPCPV",
1616
"CIPPGDAP",
17+
"CIPPURL",
1718
"Connectwise",
1819
"CPIM",
1920
"Datto",

host.json

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"functionTimeout": "00:10:00",
1111
"extensions": {
1212
"durableTask": {
13-
"maxConcurrentActivityFunctions": 5,
14-
"maxConcurrentOrchestratorFunctions": 2,
13+
"maxConcurrentActivityFunctions": 1,
14+
"maxConcurrentOrchestratorFunctions": 5,
1515
"tracing": {
1616
"distributedTracingEnabled": false,
1717
"version": "None"
@@ -20,13 +20,5 @@
2020
"versionMatchStrategy": "Strict",
2121
"versionFailureStrategy": "Fail"
2222
}
23-
},
24-
"logging": {
25-
"logLevel": {
26-
"default": "None"
27-
},
28-
"console": {
29-
"isEnabled": false
30-
}
3123
}
3224
}

0 commit comments

Comments
 (0)