Skip to content

Commit 578829f

Browse files
authored
Merge pull request #136 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents f881287 + 19c2893 commit 578829f

22 files changed

+344
-324
lines changed

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Function Push-ExecOnboardTenantQueue {
4444
@{ Name = 'Cloud App Security Administrator'; Id = '892c5842-a9a6-463a-8041-72aa08ca3cf6' },
4545
@{ Name = 'Cloud Device Administrator'; Id = '7698a772-787b-4ac8-901f-60d6b08affd2' },
4646
@{ Name = 'Teams Administrator'; Id = '69091246-20e8-4a56-aa4d-066075b2a7a8' },
47-
@{ Name = 'Sharepoint Administrator'; Id = 'f28a1f50-f6e7-4571-818b-6a12f2af6b6c' },
47+
@{ Name = 'SharePoint Administrator'; Id = 'f28a1f50-f6e7-4571-818b-6a12f2af6b6c' },
4848
@{ Name = 'Authentication Policy Administrator'; Id = '0526716b-113d-4c15-b2c8-68e3c22b9f80' },
4949
@{ Name = 'Privileged Role Administrator'; Id = 'e8611ab8-c189-46e8-94e1-60213ab1f814' },
5050
@{ Name = 'Privileged Authentication Administrator'; Id = '7be44c8a-adaf-4e2a-84d6-ab2649e08a13' }

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1

Lines changed: 19 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function Push-SchedulerCIPPNotifications {
66
param (
77
$QueueItem, $TriggerMetadata
88
)
9-
9+
#Add new alert engine.
1010
$Table = Get-CIPPTable -TableName SchedulerConfig
1111
$Filter = "RowKey eq 'CippNotifications' and PartitionKey eq 'CippNotifications'"
1212
$Config = [pscustomobject](Get-CIPPAzDataTableEntity @Table -Filter $Filter)
@@ -30,55 +30,20 @@ function Push-SchedulerCIPPNotifications {
3030
Write-Information "Alerts: $($Currentlog.count) found"
3131
#email try
3232
try {
33-
if ($Config.email -like '*@*') {
34-
$Addresses = $Config.email.split(',').trim()
35-
$Recipients = foreach ($Address in $Addresses) {
36-
[PSCustomObject]@{
37-
EmailAddress = @{
38-
Address = $Address
39-
}
33+
if ($Config.email -like '*@*' -and $null -ne $CurrentLog) {
34+
if ($config.onePerTenant) {
35+
foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) {
36+
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant)
37+
$Subject = "$($Tenant): CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
38+
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table'
39+
Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
4040
}
41-
}
42-
43-
$LogEmails = if ($config.onePerTenant) {
44-
if ($Config.email -like '*@*' -and $null -ne $CurrentLog) {
45-
foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) {
46-
$HTMLLog = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant | ConvertTo-Html -frag) -replace '<table>', '<table class=blueTable>' | Out-String
47-
$Subject = "$($Tenant): CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
48-
[PSCustomObject]@{
49-
HTMLLog = $HTMLLog
50-
Subject = $Subject
51-
}
52-
}
53-
}
54-
5541
} else {
56-
if ($null -ne $CurrentLog) {
57-
$HTMLLog = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | ConvertTo-Html -frag) -replace '<table>', '<table class=blueTable>' | Out-String
58-
$Subject = "CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
59-
[PSCustomObject]@{
60-
HTMLLog = $HTMLLog
61-
Subject = $Subject
62-
}
63-
}
42+
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | ConvertTo-Html -frag)
43+
$Subject = "CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
44+
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table'
45+
Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
6446
}
65-
66-
foreach ($LogEmail in $LogEmails) {
67-
$Email = [PSCustomObject]@{
68-
message = @{
69-
subject = $LogEmail.Subject
70-
body = @{
71-
contentType = 'HTML'
72-
content = "You've setup your alert policies to be alerted whenever specific events happen. We've found some of these events in the log:<br><br><style>table.blueTable { border:1px solid #1C6EA4;background-color:#EEE;width:100%;text-align:left;border-collapse:collapse}table.blueTable td,table.blueTable th{border:1px solid #AAA;padding:3px 2px}table.blueTable tbody td{font-size:13px}table.blueTable tr:nth-child(even){background:#D0E4F5}table.blueTable thead{background:#1C6EA4;background:-moz-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:-webkit-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:linear-gradient(to bottom,#5592bb 0,#327cad 66%,#1C6EA4 100%);border-bottom:2px solid #444}table.blueTable thead th{font-size:15px;font-weight:700;color:#FFF;border-left:2px solid #D0E4F5}table.blueTable thead th:first-child{border-left:none}table.blueTable tfoot{font-size:14px;font-weight:700;color:#FFF;background:#D0E4F5;background:-moz-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:-webkit-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:linear-gradient(to bottom,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);border-top:2px solid #444}table.blueTable tfoot td{font-size:14px}table.blueTable tfoot .links{text-align:right}table.blueTable tfoot .links a{display:inline-block;background:#1C6EA4;color:#FFF;padding:2px 8px;border-radius:5px}</style>$($LogEmail.HTMLLog)"
73-
}
74-
toRecipients = @($Recipients)
75-
}
76-
saveToSentItems = $false
77-
}
78-
$JSONBody = ConvertTo-Json -Depth 10 -Compress -InputObject $Email
79-
New-GraphPostRequest -uri 'https://graph.microsoft.com/v1.0/me/sendMail' -tenantid $env:TenantID -type POST -body $JSONBody
80-
}
81-
Write-LogMessage -API 'Alerts' -message "Sent $(($LogEmails|Measure-Object).Count) alerts to: $($Addresses -join ', ')" -sev Debug
8247
}
8348
} catch {
8449
Write-Information "Could not send alerts to email: $($_.Exception.message)"
@@ -89,35 +54,8 @@ function Push-SchedulerCIPPNotifications {
8954
Write-Information $($config | ConvertTo-Json)
9055
Write-Information $config.webhook
9156
if ($Config.webhook -ne '' -and $null -ne $CurrentLog) {
92-
switch -wildcard ($config.webhook) {
93-
94-
'*webhook.office.com*' {
95-
$Log = $Currentlog | ConvertTo-Html -frag | Out-String
96-
$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. <br><br>$Log`"}"
97-
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
98-
}
99-
100-
'*slack.com*' {
101-
$Log = $Currentlog | ForEach-Object {
102-
$JSonBody = @"
103-
{"blocks":[{"type":"header","text":{"type":"plain_text","text":"New Alert from CIPP","emoji":true}},{"type":"section","fields":[{"type":"mrkdwn","text":"*DateTime:*\n$($_.Timestamp)"},{"type":"mrkdwn","text":"*Tenant:*\n$($_.Tenant)"},{"type":"mrkdwn","text":"*API:*\n$($_.API)"},{"type":"mrkdwn","text":"*User:*\n$($_.Username)."}]},{"type":"section","text":{"type":"mrkdwn","text":"*Message:*\n$($_.Message)"}}]}
104-
"@
105-
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
106-
}
107-
}
108-
109-
'*discord.com*' {
110-
$Log = $Currentlog | ConvertTo-Html -frag | Out-String
111-
$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. $Log`"}"
112-
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
113-
}
114-
default {
115-
$Log = $Currentlog | ConvertTo-Json -Compress
116-
$JSonBody = $Log
117-
Invoke-RestMethod -Uri $config.webhook -Method POST -ContentType 'Application/json' -Body $JSONBody
118-
}
119-
}
120-
Write-LogMessage -API 'Alerts' -tenant $Tenant -message "Sent Webhook to $($config.webhook)" -sev Debug
57+
$JSONContent = $Currentlog | ConvertTo-Json -Compress
58+
Send-CIPPAlert -Type 'webhook' -JSONContent $JSONContent -TenantFilter $Tenant -APIName 'Alerts'
12159
}
12260

12361
$UpdateLogs = $CurrentLog | ForEach-Object {
@@ -135,13 +73,11 @@ function Push-SchedulerCIPPNotifications {
13573
if ($config.sendtoIntegration) {
13674
try {
13775
foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) {
138-
$HTMLLog = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant | ConvertTo-Html -frag) -replace '<table>', '<table class=blueTable>' | Out-String
139-
$Alert = @{
140-
TenantId = $Tenant
141-
AlertText = "<style>table.blueTable{border:1px solid #1C6EA4;background-color:#EEE;width:100%;text-align:left;border-collapse:collapse}table.blueTable td,table.blueTable th{border:1px solid #AAA;padding:3px 2px}table.blueTable tbody td{font-size:13px}table.blueTable tr:nth-child(even){background:#D0E4F5}table.blueTable thead{background:#1C6EA4;background:-moz-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:-webkit-linear-gradient(top,#5592bb 0,#327cad 66%,#1C6EA4 100%);background:linear-gradient(to bottom,#5592bb 0,#327cad 66%,#1C6EA4 100%);border-bottom:2px solid #444}table.blueTable thead th{font-size:15px;font-weight:700;color:#FFF;border-left:2px solid #D0E4F5}table.blueTable thead th:first-child{border-left:none}table.blueTable tfoot{font-size:14px;font-weight:700;color:#FFF;background:#D0E4F5;background:-moz-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:-webkit-linear-gradient(top,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);background:linear-gradient(to bottom,#dcebf7 0,#d4e6f6 66%,#D0E4F5 100%);border-top:2px solid #444}table.blueTable tfoot td{font-size:14px}table.blueTable tfoot .links{text-align:right}table.blueTable tfoot .links a{display:inline-block;background:#1C6EA4;color:#FFF;padding:2px 8px;border-radius:5px}</style> $($htmllog)"
142-
AlertTitle = "$tenant CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
143-
}
144-
New-CippExtAlert -Alert $Alert
76+
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant | ConvertTo-Html -frag)
77+
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table'
78+
$Title = "$tenant CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
79+
Send-CIPPAlert -Type 'psa' -Title $Title -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
80+
14581
$UpdateLogs = $CurrentLog | ForEach-Object {
14682
$_.SentAsAlert = $true
14783
$_

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomData.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,13 @@ function Invoke-ExecCustomData {
334334
}
335335
}
336336
}
337+
'ListAvailableAttributes' {
338+
$TargetObject = $Request.Query.targetObject ?? 'All'
339+
$AvailableAttributes = Get-CippCustomDataAttributes -TargetObject $TargetObject
340+
$Body = @{
341+
Results = @($AvailableAttributes)
342+
}
343+
}
337344
default {
338345
$Body = @{
339346
Results = @(

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Function Invoke-ExecAddGDAPRole {
2222
@{ label = 'Cloud App Security Administrator'; value = '892c5842-a9a6-463a-8041-72aa08ca3cf6' },
2323
@{ label = 'Cloud Device Administrator'; value = '7698a772-787b-4ac8-901f-60d6b08affd2' },
2424
@{ label = 'Teams Administrator'; value = '69091246-20e8-4a56-aa4d-066075b2a7a8' },
25-
@{ label = 'Sharepoint Administrator'; value = 'f28a1f50-f6e7-4571-818b-6a12f2af6b6c' },
25+
@{ label = 'SharePoint Administrator'; value = 'f28a1f50-f6e7-4571-818b-6a12f2af6b6c' },
2626
@{ label = 'Authentication Policy Administrator'; value = '0526716b-113d-4c15-b2c8-68e3c22b9f80' },
2727
@{ label = 'Privileged Role Administrator'; value = 'e8611ab8-c189-46e8-94e1-60213ab1f814' },
2828
@{ label = 'Privileged Authentication Administrator'; value = '7be44c8a-adaf-4e2a-84d6-ab2649e08a13' }

Modules/CIPPCore/Public/Get-CIPPMFAState.ps1

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ function Get-CIPPMFAState {
66
$APIName = 'Get MFA Status',
77
$Headers
88
)
9-
$PerUserMFAState = Get-CIPPPerUserMFA -TenantFilter $TenantFilter -AllUsers $true
10-
$users = foreach ($user in (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$top=999&$select=id,UserPrincipalName,DisplayName,accountEnabled,assignedLicenses' -tenantid $TenantFilter)) {
9+
#$PerUserMFAState = Get-CIPPPerUserMFA -TenantFilter $TenantFilter -AllUsers $true
10+
$users = foreach ($user in (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/users?$top=999&$select=id,UserPrincipalName,DisplayName,accountEnabled,assignedLicenses,perUserMfaState' -tenantid $TenantFilter)) {
1111
[PSCustomObject]@{
1212
UserPrincipalName = $user.UserPrincipalName
1313
isLicensed = [boolean]$user.assignedLicenses.skuid
1414
accountEnabled = $user.accountEnabled
1515
DisplayName = $user.DisplayName
1616
ObjectId = $user.id
17+
perUserMfaState = $user.perUserMfaState
1718
}
1819
}
1920

@@ -40,7 +41,7 @@ function Get-CIPPMFAState {
4041
if ($null -ne $MFARegistration) {
4142
$CASuccess = $true
4243
try {
43-
$CAPolicies = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $TenantFilter -ErrorAction Stop )
44+
$CAPolicies = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies?$top=999' -tenantid $TenantFilter -ErrorAction Stop )
4445
foreach ($Policy in $CAPolicies) {
4546
$IsMFAControl = $policy.grantControls.builtincontrols -eq 'mfa' -or $Policy.grantControls.authenticationStrength.requirementsSatisfied -eq 'mfa' -or $Policy.grantControls.customAuthenticationFactors -eq 'RequireDuoMfa'
4647
$IsAllApps = [bool]($Policy.conditions.applications.includeApplications -eq 'All')
@@ -98,7 +99,7 @@ function Get-CIPPMFAState {
9899
}
99100
}
100101

101-
$PerUser = if ($null -eq $PerUserMFAState) { $null } else { ($PerUserMFAState | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).PerUserMFAState }
102+
$PerUser = $_.PerUserMFAState
102103

103104
$MFARegUser = if ($null -eq ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.userPrincipalName).isMFARegistered) { $false } else { ($MFARegistration | Where-Object -Property UserPrincipalName -EQ $_.userPrincipalName) }
104105

Modules/CIPPCore/Public/Get-CIPPPerUserMFA.ps1

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,10 @@ function Get-CIPPPerUserMFA {
88
)
99
try {
1010
if ($AllUsers -eq $true) {
11-
$AllUsers = New-graphGetRequest -Uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=UserPrincipalName,Id" -tenantid $tenantfilter
12-
$Requests = foreach ($id in $AllUsers.userPrincipalName) {
13-
@{
14-
id = $int++
15-
method = 'GET'
16-
url = "users/$id/authentication/requirements"
17-
}
18-
}
19-
$Requests = New-GraphBulkRequest -tenantid $tenantfilter -scope 'https://graph.microsoft.com/.default' -Requests @($Requests) -asapp $true
20-
if ($Requests.body) {
21-
$UsersWithoutMFA = $Requests.body | Select-Object peruserMFAState, @{Name = 'UserPrincipalName'; Expression = { [System.Web.HttpUtility]::UrlDecode($_.'@odata.context'.split("'")[1]) } }
22-
return $UsersWithoutMFA
23-
}
11+
$AllUsers = New-graphGetRequest -Uri "https://graph.microsoft.com/v1.0/users?`$top=999&`$select=UserPrincipalName,Id,perUserMfaState" -tenantid $tenantfilter
12+
return $AllUsers
2413
} else {
25-
$MFAState = New-graphGetRequest -Uri "https://graph.microsoft.com/beta/users/$($userId)/authentication/requirements" -tenantid $tenantfilter
14+
$MFAState = New-graphGetRequest -Uri "https://graph.microsoft.com/v1.0/users/$($userId)?`$select=UserPrincipalName,Id,perUserMfaState" -tenantid $tenantfilter
2615
return [PSCustomObject]@{
2716
PerUserMFAState = $MFAState.perUserMfaState
2817
UserPrincipalName = $userId
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
function Get-CippCustomDataAttributes {
2+
<#
3+
.SYNOPSIS
4+
Get the custom data attributes for CIPP
5+
.DESCRIPTION
6+
This function is used to get the custom data attributes for CIPP
7+
#>
8+
[CmdletBinding()]
9+
param(
10+
$TargetObject = 'All'
11+
)
12+
$CustomDataTable = Get-CippTable -tablename 'CustomData'
13+
$CustomDataEntities = Get-CIPPAzDataTableEntity @CustomDataTable
14+
$AvailableAttributes = foreach ($CustomDataEntity in $CustomDataEntities) {
15+
$Type = $CustomDataEntity.PartitionKey
16+
$CustomData = $CustomDataEntity.JSON | ConvertFrom-Json
17+
if ($CustomData) {
18+
if ($Type -eq 'SchemaExtension') {
19+
$Name = $CustomData.id
20+
foreach ($TargetObject in $CustomData.targetTypes) {
21+
[PSCustomObject]@{
22+
name = $Name
23+
type = $Type
24+
targetObject = $TargetObject.ToLower()
25+
properties = $CustomData.properties
26+
}
27+
}
28+
} elseif ($Type -eq 'DirectoryExtension') {
29+
$Name = $CustomData.RowKey
30+
foreach ($TargetObject in $CustomData.targetObjects) {
31+
[PSCustomObject]@{
32+
name = $Name
33+
type = $Type
34+
targetObject = $TargetObject
35+
dataType = $CustomData.dataType
36+
isMultiValued = $CustomData.isMultiValued
37+
}
38+
}
39+
}
40+
}
41+
}
42+
43+
if ($TargetObject -eq 'All') {
44+
return $AvailableAttributes
45+
} else {
46+
return $AvailableAttributes | Where-Object { $_.targetObject -eq $TargetObject }
47+
}
48+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ function New-ClassicAPIGetRequest($TenantID, $Uri, $Method = 'GET', $Resource =
1818
'X-Requested-With' = 'XMLHttpRequest'
1919
}
2020
$Data
21-
if ($noPagination) { $nextURL = $null } else { $nextURL = $data.NextLink }
21+
if ($noPagination -or $null -eq $data.NextLink) { $nextURL = $null } else { $nextURL = $data.NextLink }
2222
} catch {
2323
throw "Failed to make Classic Get Request $_"
2424
}
25-
} until ($null -eq $NextURL)
25+
} until ($null -eq $NextURL -or ' ' -eq $NextURL)
2626
return $ReturnedData
2727
} else {
2828
Write-Error 'Not allowed. You cannot manage your own tenant or tenants not under your scope'
2929
}
30-
}
30+
}

0 commit comments

Comments
 (0)