Skip to content

Commit 2535454

Browse files
authored
Merge branch 'KelvinTegelaar:master' into master
2 parents d44afe2 + bd57189 commit 2535454

319 files changed

Lines changed: 13212 additions & 2296 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.

.vscode/extensions.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"recommendations": [
3+
"editorconfig.editorconfig"
4+
]
5+
}

Cache_SAMSetup/PermissionsTranslator.json

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,15 @@
10041004
"description": "Allows the app to create, read, update, and delete events of all calendars without a signed-in user.",
10051005
"displayName": "Read and write calendars in all mailboxes",
10061006
"id": "ef54d2bf-783f-4e0f-bca1-3210c0444d99",
1007-
"origin": "Application",
1008-
"value": "Calendars.ReadWrite"
1007+
"origin": "Application (Office 365 Exchange Online)",
1008+
"value": "Calendars.ReadWrite.All"
1009+
},
1010+
{
1011+
"description": "Allows the app to create, read, update, and delete user's mailbox settings without a signed-in user. Does not include permission to send mail.",
1012+
"displayName": "Read and write all user mailbox settings",
1013+
"id": "f9156939-25cd-4ba8-abfe-7fabcf003749",
1014+
"origin": "Application (Office 365 Exchange Online)",
1015+
"value": "Mailbox.Settings.ReadWrite"
10091016
},
10101017
{
10111018
"description": "Allows the app to read your organization's user flows, without a signed-in user.",
@@ -5286,6 +5293,24 @@
52865293
"userConsentDisplayName": "Read Threat and Vulnerability Management vulnerability information",
52875294
"value": "Exchange.Manage"
52885295
},
5296+
{
5297+
"description": "Allows the app to create, read, update and delete events in all calendars in the organization user has permissions to access. This includes delegate and shared calendars",
5298+
"displayName": "Read and write user and shared calendars",
5299+
"id": "bbd1ca91-75e0-4814-ad94-9c5dbbae3415",
5300+
"Origin": "Delegated (Office 365 Exchange Online)",
5301+
"userConsentDescription": "Allows the app to read, update, create and delete events in all calendars in your organization you have permissions to access. This includes delegate and shared calendars",
5302+
"userConsentDisplayName": "Read and write to your and shared calendars",
5303+
"value": "Calendars.ReadWrite.All"
5304+
},
5305+
{
5306+
"description": "Allows the app to create, read, update, and delete user's mailbox settings. Does not include permission to send mail.",
5307+
"displayName": "Read and write user mailbox settings",
5308+
"id": "2e83d72d-8895-4b66-9eea-abb43449ab8b",
5309+
"Origin": "Delegated (Office 365 Exchange Online)",
5310+
"userConsentDescription": "Allows the app to read, update, create, and delete your mailbox settings.",
5311+
"userConsentDisplayName": "Read and write to your mailbox settings",
5312+
"value": "MailboxSettings.ReadWrite"
5313+
},
52895314
{
52905315
"description": "Allows the app to have full control of all site collections on behalf of the signed-in user.",
52915316
"displayName": "Manage Sharepoint Online",
@@ -5312,5 +5337,14 @@
53125337
"userConsentDescription": "Access Microsoft Teams and Skype for Business data as the signed in user",
53135338
"userConsentDisplayName": "Access Microsoft Teams and Skype for Business data based on the user's role membership",
53145339
"value": "user_impersonation"
5340+
},
5341+
{
5342+
"description": "Read and write all on-premises directory synchronization information",
5343+
"displayName": "Read and write all on-premises directory synchronization information",
5344+
"id": "c2d95988-7604-4ba1-aaed-38a5f82a51c7",
5345+
"Origin": "Delegated",
5346+
"userConsentDescription": "Access Microsoft Teams and Skype for Business data as the signed in user",
5347+
"userConsentDisplayName": "Access Microsoft Teams and Skype for Business data based on the user's role membership",
5348+
"value": "OnPremDirectorySynchronization.ReadWrite.All"
53155349
}
53165350
]

Cache_SAMSetup/SAMManifest.json

Lines changed: 194 additions & 181 deletions
Large diffs are not rendered by default.

Durable_BECRun/run.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Write-Host "Working on $UserName"
1010
try {
1111
$startDate = (Get-Date).AddDays(-7)
1212
$endDate = (Get-Date)
13-
$auditLog = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AdminAuditLogConfig').UnifiedAuditLogIngestionEnabled
13+
$auditLog = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AdminAuditLogConfig').UnifiedAuditLogIngestionEnabled
1414
$7dayslog = if ($auditLog -eq $false) {
1515
$ExtractResult = 'AuditLog is disabled. Cannot perform full analysis'
1616
} else {
@@ -40,10 +40,10 @@ try {
4040
Write-Host "Retrieved $($logsTenant.count) logs" -ForegroundColor Yellow
4141
$logsTenant
4242
} while ($LogsTenant.count % 5000 -eq 0 -and $LogsTenant.count -ne 0)
43-
$ExtractResult = 'Succesfully extracted logs from auditlog'
43+
$ExtractResult = 'Successfully extracted logs from auditlog'
4444
}
4545
Try {
46-
$URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$SuspectUser')&`$top=1&`$orderby=createdDateTime desc"
46+
$URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$SuspectUser')&`$top=1&`$orderby=createdDateTime desc"
4747
$LastSignIn = New-GraphGetRequest -uri $URI -tenantid $TenantFilter -noPagination $true -verbose | Select-Object @{ Name = 'CreatedDateTime'; Expression = { $(($_.createdDateTime | Out-String) -replace '\r\n') } },
4848
id,
4949
@{ Name = 'AppDisplayName'; Expression = { $_.resourceDisplayName } },

Modules/CIPPCore/CIPPCore.psm1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ $Functions = $Public + $Private
44
foreach ($import in @($Functions)) {
55
try {
66
. $import.FullName
7-
}
8-
catch {
7+
} catch {
98
Write-Error -Message "Failed to import function $($import.FullName): $_"
109
}
1110
}

Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,25 @@ function Add-CIPPApplicationPermission {
66
$Tenantfilter
77
)
88
if ($ApplicationId -eq $ENV:ApplicationID -and $Tenantfilter -eq $env:TenantID) {
9-
return @('Cannot modify application permissions for CIPP-SAM on partner tenant')
9+
#return @('Cannot modify application permissions for CIPP-SAM on partner tenant')
10+
$RequiredResourceAccess = 'CIPPDefaults'
1011
}
1112
Set-Location (Get-Item $PSScriptRoot).FullName
1213
if ($RequiredResourceAccess -eq 'CIPPDefaults') {
1314
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
1415
}
15-
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter
16+
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
1617
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
1718
if (!$ourSVCPrincipal) {
1819
#Our Service Principal isn't available yet. We do a sleep and reexecute after 3 seconds.
1920
Start-Sleep -Seconds 5
20-
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter
21+
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
2122
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
2223
}
2324

2425
$Results = [System.Collections.ArrayList]@()
2526

26-
$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $Tenantfilter -skipTokenCache $true
27+
$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $Tenantfilter -skipTokenCache $true -NoAuthCheck $true
2728

2829
$Grants = foreach ($App in $RequiredResourceAccess) {
2930
$svcPrincipalId = $ServicePrincipalList | Where-Object -Property AppId -EQ $App.resourceAppId
@@ -40,12 +41,13 @@ function Add-CIPPApplicationPermission {
4041
$counter = 0
4142
foreach ($Grant in $Grants) {
4243
try {
43-
$SettingsRequest = New-GraphPOSTRequest -body ($Grant | ConvertTo-Json) -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignedTo" -tenantid $Tenantfilter -type POST
44+
$SettingsRequest = New-GraphPOSTRequest -body (ConvertTo-Json -InputObject $Grant -Depth 5) -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignedTo" -tenantid $Tenantfilter -type POST -NoAuthCheck $true
4445
$counter++
4546
} catch {
46-
$Results.add("Failed to grant $($Grant.appRoleId) to $($Grant.resourceId): $($_.Exception.Message)") | Out-Null
47+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
48+
$Results.add("Failed to grant $($Grant.appRoleId) to $($Grant.resourceId): $ErrorMessage") | Out-Null
4749
}
4850
}
4951
"Added $counter Application permissions to $($ourSVCPrincipal.displayName)"
5052
return $Results
51-
}
53+
}

Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1

Lines changed: 113 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,139 @@ function Add-CIPPAzDataTableEntity {
66
[switch]$Force,
77
[switch]$CreateTableIfNotExists
88
)
9-
9+
10+
$MaxRowSize = 500000 - 100 # Maximum size of an entity
11+
$MaxSize = 30kb # Maximum size of a property value
12+
1013
foreach ($SingleEnt in $Entity) {
1114
try {
12-
Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt -ErrorAction Stop
15+
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt -ErrorAction Stop
1316
} catch [System.Exception] {
14-
if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge') {
17+
if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge' -or $_.Exception.ErrorCode -eq 'RequestBodyTooLarge') {
1518
try {
16-
$MaxSize = 30kb
17-
$largePropertyName = $null
19+
$largePropertyNames = [System.Collections.ArrayList]::new()
20+
$entitySize = 0
1821
foreach ($key in $SingleEnt.Keys) {
19-
if ($SingleEnt[$key].Length -gt $MaxSize) {
20-
$largePropertyName = $key
21-
break
22+
$propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString())
23+
$entitySize = $entitySize + $propertySize
24+
if ($propertySize -gt $MaxSize) {
25+
$largePropertyNames.Add($key)
2226
}
27+
2328
}
2429

25-
if ($largePropertyName) {
26-
$dataString = $SingleEnt[$largePropertyName]
27-
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
28-
$splitData = 0..($splitCount - 1) | ForEach-Object {
29-
$start = $_ * $MaxSize
30-
$dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))
31-
}
30+
if ($largePropertyNames.Count -gt 0) {
31+
$splitInfoList = [System.Collections.ArrayList]@()
32+
foreach ($largePropertyName in $largePropertyNames) {
33+
$dataString = $SingleEnt[$largePropertyName]
34+
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
35+
$splitData = [System.Collections.ArrayList]@()
36+
for ($i = 0; $i -lt $splitCount; $i++) {
37+
$start = $i * $MaxSize
38+
$splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null
39+
}
40+
41+
$splitPropertyNames = [System.Collections.ArrayList]@()
42+
for ($i = 0; $i -lt $splitData.Count; $i++) {
43+
$splitPropertyNames.Add("${largePropertyName}_Part$i") > $null
44+
}
3245

33-
$splitPropertyNames = 1..$splitData.Count | ForEach-Object {
34-
"${largePropertyName}_Part$_"
46+
$splitInfo = @{
47+
OriginalHeader = $largePropertyName
48+
SplitHeaders = $splitPropertyNames
49+
}
50+
$splitInfoList.Add($splitInfo) > $null
51+
$SingleEnt.Remove($largePropertyName)
52+
53+
for ($i = 0; $i -lt $splitData.Count; $i++) {
54+
$SingleEnt[$splitPropertyNames[$i]] = $splitData[$i]
55+
}
3556
}
3657

37-
$splitInfo = @{
38-
OriginalHeader = $largePropertyName
39-
SplitHeaders = $splitPropertyNames
58+
$SingleEnt['SplitOverProps'] = ($splitInfoList | ConvertTo-Json -Compress).ToString()
59+
}
60+
61+
# Check if the entity is still too large
62+
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
63+
if ($entitySize -gt $MaxRowSize) {
64+
$rows = [System.Collections.ArrayList]@()
65+
$originalPartitionKey = $SingleEnt.PartitionKey
66+
$originalRowKey = $SingleEnt.RowKey
67+
$entityIndex = 0
68+
69+
while ($entitySize -gt $MaxRowSize) {
70+
Write-Information "Entity size is $entitySize. Splitting entity into multiple parts."
71+
$newEntity = @{}
72+
$newEntity['PartitionKey'] = $originalPartitionKey
73+
if ($entityIndex -eq 0) {
74+
$newEntity['RowKey'] = $originalRowKey
75+
} else {
76+
$newEntity['RowKey'] = "$($originalRowKey)-part$entityIndex"
77+
}
78+
$newEntity['OriginalEntityId'] = $originalRowKey
79+
$newEntity['PartIndex'] = $entityIndex
80+
$entityIndex++
81+
82+
$propertiesToRemove = [System.Collections.ArrayList]@()
83+
foreach ($key in $SingleEnt.Keys) {
84+
$newEntitySize = [System.Text.Encoding]::UTF8.GetByteCount($($newEntity | ConvertTo-Json))
85+
if ($newEntitySize -lt $MaxRowSize) {
86+
$propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString())
87+
if ($propertySize -gt $MaxRowSize) {
88+
$dataString = $SingleEnt[$key]
89+
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
90+
$splitData = [System.Collections.ArrayList]@()
91+
for ($i = 0; $i -lt $splitCount; $i++) {
92+
$start = $i * $MaxSize
93+
$splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null
94+
}
95+
96+
$splitPropertyNames = [System.Collections.ArrayList]@()
97+
for ($i = 0; $i -lt $splitData.Count; $i++) {
98+
$splitPropertyNames.Add("${key}_Part$i") > $null
99+
}
100+
101+
for ($i = 0; $i -lt $splitData.Count; $i++) {
102+
$newEntity[$splitPropertyNames[$i]] = $splitData[$i]
103+
}
104+
} else {
105+
$newEntity[$key] = $SingleEnt[$key]
106+
}
107+
$propertiesToRemove.Add($key) > $null
108+
}
109+
}
110+
111+
foreach ($prop in $propertiesToRemove) {
112+
$SingleEnt.Remove($prop)
113+
}
114+
115+
$rows.Add($newEntity) > $null
116+
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
40117
}
41-
$SingleEnt['SplitOverProps'] = ($splitInfo | ConvertTo-Json).ToString()
42-
$SingleEnt.Remove($largePropertyName)
43118

44-
for ($i = 0; $i -lt $splitData.Count; $i++) {
45-
$SingleEnt[$splitPropertyNames[$i]] = $splitData[$i]
119+
if ($SingleEnt.Count -gt 0) {
120+
$SingleEnt['RowKey'] = "$($originalRowKey)-part$entityIndex"
121+
$SingleEnt['OriginalEntityId'] = $originalRowKey
122+
$SingleEnt['PartIndex'] = $entityIndex
123+
$SingleEnt['PartitionKey'] = $originalPartitionKey
124+
125+
$rows.Add($SingleEnt) > $null
46126
}
47127

48-
Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt
128+
foreach ($row in $rows) {
129+
Write-Information "current entity is $($row.RowKey) with $($row.PartitionKey). Our size is $([System.Text.Encoding]::UTF8.GetByteCount($($row | ConvertTo-Json)))"
130+
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $row
131+
}
132+
} else {
133+
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt
49134
}
50135

51136
} catch {
52-
throw "Error processing entity: $($_.Exception.Message)."
137+
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
138+
throw "Error processing entity: $ErrorMessage Linenumber: $($_.InvocationInfo.ScriptLineNumber)"
53139
}
54140
} else {
55-
Write-Host "THE ERROR IS $($_.Exception.ErrorCode)"
56-
141+
Write-Information "THE ERROR IS $($_.Exception.ErrorCode). The size of the entity is $entitySize."
57142
throw $_
58143
}
59144
}

Modules/CIPPCore/Public/Add-CIPPBPAField.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ function Add-CIPPBPAField {
3030
$Result["$fieldName"] = [bool]$FieldValue
3131
}
3232
'JSON' {
33-
if ($FieldValue -eq $null) { $JsonString = '{}' } else { $JsonString = (ConvertTo-Json -Depth 15 -InputObject $FieldValue -Compress) }
33+
if ($null -eq $FieldValue) { $JsonString = '{}' } else { $JsonString = (ConvertTo-Json -Depth 15 -InputObject $FieldValue -Compress) }
3434
$Result[$fieldName] = [string]$JsonString
3535
}
3636
'string' {
3737
$Result[$fieldName], [string]$FieldValue
3838
}
3939
}
4040
Add-CIPPAzDataTableEntity @Table -Entity $Result -Force
41-
}
41+
}

0 commit comments

Comments
 (0)