Skip to content

Commit

Permalink
Merge pull request #71 from KelvinTegelaar/dev
Browse files Browse the repository at this point in the history
[pull] dev from KelvinTegelaar:dev
  • Loading branch information
kris6673 authored Jul 8, 2024
2 parents 4c46034 + 09931d9 commit 6390541
Show file tree
Hide file tree
Showing 71 changed files with 1,963 additions and 586 deletions.
38 changes: 36 additions & 2 deletions Cache_SAMSetup/PermissionsTranslator.json
Original file line number Diff line number Diff line change
Expand Up @@ -1004,8 +1004,15 @@
"description": "Allows the app to create, read, update, and delete events of all calendars without a signed-in user.",
"displayName": "Read and write calendars in all mailboxes",
"id": "ef54d2bf-783f-4e0f-bca1-3210c0444d99",
"origin": "Application",
"value": "Calendars.ReadWrite"
"origin": "Application (Office 365 Exchange Online)",
"value": "Calendars.ReadWrite.All"
},
{
"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.",
"displayName": "Read and write all user mailbox settings",
"id": "f9156939-25cd-4ba8-abfe-7fabcf003749",
"origin": "Application (Office 365 Exchange Online)",
"value": "Mailbox.Settings.ReadWrite"
},
{
"description": "Allows the app to read your organization's user flows, without a signed-in user.",
Expand Down Expand Up @@ -5286,6 +5293,24 @@
"userConsentDisplayName": "Read Threat and Vulnerability Management vulnerability information",
"value": "Exchange.Manage"
},
{
"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",
"displayName": "Read and write user and shared calendars",
"id": "bbd1ca91-75e0-4814-ad94-9c5dbbae3415",
"Origin": "Delegated (Office 365 Exchange Online)",
"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",
"userConsentDisplayName": "Read and write to your and shared calendars",
"value": "Calendars.ReadWrite.All"
},
{
"description": "Allows the app to create, read, update, and delete user's mailbox settings. Does not include permission to send mail.",
"displayName": "Read and write user mailbox settings",
"id": "2e83d72d-8895-4b66-9eea-abb43449ab8b",
"Origin": "Delegated (Office 365 Exchange Online)",
"userConsentDescription": "Allows the app to read, update, create, and delete your mailbox settings.",
"userConsentDisplayName": "Read and write to your mailbox settings",
"value": "MailboxSettings.ReadWrite"
},
{
"description": "Allows the app to have full control of all site collections on behalf of the signed-in user.",
"displayName": "Manage Sharepoint Online",
Expand All @@ -5312,5 +5337,14 @@
"userConsentDescription": "Access Microsoft Teams and Skype for Business data as the signed in user",
"userConsentDisplayName": "Access Microsoft Teams and Skype for Business data based on the user's role membership",
"value": "user_impersonation"
},
{
"description": "Read and write all on-premises directory synchronization information",
"displayName": "Read and write all on-premises directory synchronization information",
"id": "c2d95988-7604-4ba1-aaed-38a5f82a51c7",
"Origin": "Delegated",
"userConsentDescription": "Access Microsoft Teams and Skype for Business data as the signed in user",
"userConsentDisplayName": "Access Microsoft Teams and Skype for Business data based on the user's role membership",
"value": "OnPremDirectorySynchronization.ReadWrite.All"
}
]
12 changes: 11 additions & 1 deletion Cache_SAMSetup/SAMManifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
]
},
"requiredResourceAccess": [
{
"resourceAppId": "aeb86249-8ea3-49e2-900b-54cc8e308f85",
"resourceAccess": [
{ "id": "fc946a4f-bc4d-413b-a090-b2c86113ec4f", "type": "Scope" }
]
},
{
"resourceAppId": "fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd",
"resourceAccess": [
Expand Down Expand Up @@ -159,7 +165,11 @@
"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
"resourceAccess": [
{ "id": "ab4f2b77-0b06-4fc1-a9de-02113fc2ab7c", "type": "Scope" },
{ "id": "dc50a0fb-09a3-484d-be87-e023b12c6440", "type": "Role" }
{ "id": "bbd1ca91-75e0-4814-ad94-9c5dbbae3415", "type": "Scope" },
{ "id": "2e83d72d-8895-4b66-9eea-abb43449ab8b", "type": "Scope" },
{ "id": "dc50a0fb-09a3-484d-be87-e023b12c6440", "type": "Role" },
{ "id": "ef54d2bf-783f-4e0f-bca1-3210c0444d99", "type": "Role" },
{ "id": "f9156939-25cd-4ba8-abfe-7fabcf003749", "type": "Role" }
]
},
{
Expand Down
6 changes: 3 additions & 3 deletions Durable_BECRun/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Write-Host "Working on $UserName"
try {
$startDate = (Get-Date).AddDays(-7)
$endDate = (Get-Date)
$auditLog = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AdminAuditLogConfig').UnifiedAuditLogIngestionEnabled
$auditLog = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AdminAuditLogConfig').UnifiedAuditLogIngestionEnabled
$7dayslog = if ($auditLog -eq $false) {
$ExtractResult = 'AuditLog is disabled. Cannot perform full analysis'
} else {
Expand Down Expand Up @@ -40,10 +40,10 @@ try {
Write-Host "Retrieved $($logsTenant.count) logs" -ForegroundColor Yellow
$logsTenant
} while ($LogsTenant.count % 5000 -eq 0 -and $LogsTenant.count -ne 0)
$ExtractResult = 'Succesfully extracted logs from auditlog'
$ExtractResult = 'Successfully extracted logs from auditlog'
}
Try {
$URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$SuspectUser')&`$top=1&`$orderby=createdDateTime desc"
$URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$SuspectUser')&`$top=1&`$orderby=createdDateTime desc"
$LastSignIn = New-GraphGetRequest -uri $URI -tenantid $TenantFilter -noPagination $true -verbose | Select-Object @{ Name = 'CreatedDateTime'; Expression = { $(($_.createdDateTime | Out-String) -replace '\r\n') } },
id,
@{ Name = 'AppDisplayName'; Expression = { $_.resourceDisplayName } },
Expand Down
3 changes: 2 additions & 1 deletion Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ function Add-CIPPApplicationPermission {
$Tenantfilter
)
if ($ApplicationId -eq $ENV:ApplicationID -and $Tenantfilter -eq $env:TenantID) {
return @('Cannot modify application permissions for CIPP-SAM on partner tenant')
#return @('Cannot modify application permissions for CIPP-SAM on partner tenant')
$RequiredResourceAccess = 'CIPPDefaults'
}
Set-Location (Get-Item $PSScriptRoot).FullName
if ($RequiredResourceAccess -eq 'CIPPDefaults') {
Expand Down
138 changes: 111 additions & 27 deletions Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,138 @@ function Add-CIPPAzDataTableEntity {
[switch]$Force,
[switch]$CreateTableIfNotExists
)


$MaxRowSize = 500000 - 100 # Maximum size of an entity
$MaxSize = 30kb # Maximum size of a property value

foreach ($SingleEnt in $Entity) {
try {
Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt -ErrorAction Stop
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt -ErrorAction Stop
} catch [System.Exception] {
if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge') {
try {
$MaxSize = 30kb
$largePropertyName = $null
$largePropertyNames = [System.Collections.ArrayList]::new()
$entitySize = 0
foreach ($key in $SingleEnt.Keys) {
if ($SingleEnt[$key].Length -gt $MaxSize) {
$largePropertyName = $key
break
$propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString())
$entitySize = $entitySize + $propertySize
if ($propertySize -gt $MaxSize) {
$largePropertyNames.Add($key)
}

}

if ($largePropertyName) {
$dataString = $SingleEnt[$largePropertyName]
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
$splitData = 0..($splitCount - 1) | ForEach-Object {
$start = $_ * $MaxSize
$dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))
}
if ($largePropertyNames.Count -gt 0) {
$splitInfoList = [System.Collections.ArrayList]@()
foreach ($largePropertyName in $largePropertyNames) {
$dataString = $SingleEnt[$largePropertyName]
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
$splitData = [System.Collections.ArrayList]@()
for ($i = 0; $i -lt $splitCount; $i++) {
$start = $i * $MaxSize
$splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null
}

$splitPropertyNames = [System.Collections.ArrayList]@()
for ($i = 0; $i -lt $splitData.Count; $i++) {
$splitPropertyNames.Add("${largePropertyName}_Part$i") > $null
}

$splitPropertyNames = 1..$splitData.Count | ForEach-Object {
"${largePropertyName}_Part$_"
$splitInfo = @{
OriginalHeader = $largePropertyName
SplitHeaders = $splitPropertyNames
}
$splitInfoList.Add($splitInfo) > $null
$SingleEnt.Remove($largePropertyName)

for ($i = 0; $i -lt $splitData.Count; $i++) {
$SingleEnt[$splitPropertyNames[$i]] = $splitData[$i]
}
}

$splitInfo = @{
OriginalHeader = $largePropertyName
SplitHeaders = $splitPropertyNames
$SingleEnt['SplitOverProps'] = ($splitInfoList | ConvertTo-Json).ToString()
}

# Check if the entity is still too large
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
if ($entitySize -gt $MaxRowSize) {
$rows = [System.Collections.ArrayList]@()
$originalPartitionKey = $SingleEnt.PartitionKey
$originalRowKey = $SingleEnt.RowKey
$entityIndex = 0

while ($entitySize -gt $MaxRowSize) {
Write-Host "Entity size is $entitySize. Splitting entity into multiple parts."
$newEntity = @{}
$newEntity['PartitionKey'] = $originalPartitionKey
if ($entityIndex -eq 0) {
$newEntity['RowKey'] = $originalRowKey
} else {
$newEntity['RowKey'] = "$($originalRowKey)-part$entityIndex"
}
$newEntity['OriginalEntityId'] = $originalRowKey
$newEntity['PartIndex'] = $entityIndex
$entityIndex++

$propertiesToRemove = [System.Collections.ArrayList]@()
foreach ($key in $SingleEnt.Keys) {
$newEntitySize = [System.Text.Encoding]::UTF8.GetByteCount($($newEntity | ConvertTo-Json))
if ($newEntitySize -lt $MaxRowSize) {
$propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString())
if ($propertySize -gt $MaxRowSize) {
$dataString = $SingleEnt[$key]
$splitCount = [math]::Ceiling($dataString.Length / $MaxSize)
$splitData = [System.Collections.ArrayList]@()
for ($i = 0; $i -lt $splitCount; $i++) {
$start = $i * $MaxSize
$splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null
}

$splitPropertyNames = [System.Collections.ArrayList]@()
for ($i = 0; $i -lt $splitData.Count; $i++) {
$splitPropertyNames.Add("${key}_Part$i") > $null
}

for ($i = 0; $i -lt $splitData.Count; $i++) {
$newEntity[$splitPropertyNames[$i]] = $splitData[$i]
}
} else {
$newEntity[$key] = $SingleEnt[$key]
}
$propertiesToRemove.Add($key) > $null
}
}

foreach ($prop in $propertiesToRemove) {
$SingleEnt.Remove($prop)
}

$rows.Add($newEntity) > $null
$entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json))
}
$SingleEnt['SplitOverProps'] = ($splitInfo | ConvertTo-Json).ToString()
$SingleEnt.Remove($largePropertyName)

for ($i = 0; $i -lt $splitData.Count; $i++) {
$SingleEnt[$splitPropertyNames[$i]] = $splitData[$i]
if ($SingleEnt.Count -gt 0) {
$SingleEnt['RowKey'] = "$($originalRowKey)-part$entityIndex"
$SingleEnt['OriginalEntityId'] = $originalRowKey
$SingleEnt['PartIndex'] = $entityIndex
$SingleEnt['PartitionKey'] = $originalPartitionKey

$rows.Add($SingleEnt) > $null
}

Add-AzDataTableEntity -context $Context -force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt
foreach ($row in $rows) {
Write-Host "current entity is $($row.RowKey) with $($row.PartitionKey). Our size is $([System.Text.Encoding]::UTF8.GetByteCount($($row | ConvertTo-Json)))"
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $row
}
} else {
Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt
}

} catch {
throw "Error processing entity: $($_.Exception.Message)."
throw "Error processing entity: $($_.Exception.Message) Linenumner: $($_.InvocationInfo.ScriptLineNumber)"
}
} else {
Write-Host "THE ERROR IS $($_.Exception.ErrorCode)"

Write-Host "THE ERROR IS $($_.Exception.ErrorCode). The size of the entity is $entitySize."
throw $_
}
}
Expand Down
22 changes: 19 additions & 3 deletions Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ function Add-CIPPDelegatedPermission {
param(
$RequiredResourceAccess,
$ApplicationId,
$NoTranslateRequired,
$Tenantfilter
)
Write-Host 'Adding Delegated Permissions'
Set-Location (Get-Item $PSScriptRoot).FullName

if ($ApplicationId -eq $ENV:ApplicationID -and $Tenantfilter -eq $env:TenantID) {
return @('Cannot modify delgated permissions for CIPP-SAM on partner tenant')
#return @('Cannot modify delgated permissions for CIPP-SAM on partner tenant')
$RequiredResourceAccess = 'CIPPDefaults'
}

if ($RequiredResourceAccess -eq 'CIPPDefaults') {
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
$AdditionalPermissions = Get-Content '.\AdditionalPermissions.json' | ConvertFrom-Json
$RequiredResourceAccess = $RequiredResourceAccess + ($AdditionalPermissions | Where-Object { $RequiredResourceAccess.resourceAppId -notcontains $_.resourceAppId })
}
$Translator = Get-Content '.\PermissionsTranslator.json' | ConvertFrom-Json
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Tenantfilter -skipTokenCache $true
Expand All @@ -22,10 +26,22 @@ function Add-CIPPDelegatedPermission {

$CurrentDelegatedScopes = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/oauth2PermissionGrants" -skipTokenCache $true -tenantid $Tenantfilter

foreach ($App in $requiredResourceAccess) {
foreach ($App in $RequiredResourceAccess) {
$svcPrincipalId = $ServicePrincipalList | Where-Object -Property AppId -EQ $App.resourceAppId
$AdditionalScopes = ($AdditionalPermissions | Where-Object -Property resourceAppId -EQ $App.resourceAppId).resourceAccess
if (!$svcPrincipalId) { continue }
$NewScope = ($Translator | Where-Object { $_.id -in $App.ResourceAccess.id }).value -join ' '
if ($AdditionalScopes) {
$NewScope = (($Translator | Where-Object { $_.id -in $App.ResourceAccess.id }).value + $AdditionalScopes.id | Select-Object -Unique) -join ' '
Write-Host "NEW SCOPE: $NewScope"
} else {
if ($NoTranslateRequired) {
$NewScope = $App.resourceAccess | ForEach-Object { $_.id } -join ' '
} else {
$NewScope = ($Translator | Where-Object { $_.id -in $App.resourceAccess.id }).value -join ' '
}
$NewScope = ($Translator | Where-Object { $_.id -in $App.ResourceAccess.id }).value -join ' '
}

$OldScope = ($CurrentDelegatedScopes | Where-Object -Property Resourceid -EQ $svcPrincipalId.id)

if (!$OldScope) {
Expand Down
8 changes: 6 additions & 2 deletions Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ function Add-CIPPScheduledTask {
[CmdletBinding()]
param(
[pscustomobject]$Task,
[bool]$Hidden
[bool]$Hidden,
[string]$SyncType = $null
)

$Table = Get-CIPPTable -TableName 'ScheduledTasks'
Expand Down Expand Up @@ -49,10 +50,13 @@ function Add-CIPPScheduledTask {
Hidden = [bool]$Hidden
Results = 'Planned'
}
if ($SyncType) {
$entity.SyncType = $SyncType
}
try {
Add-CIPPAzDataTableEntity @Table -Entity $entity -Force
} catch {
return "Could not add task: $($_.Exception.Message)"
}
return "Successfully added task: $($entity.Name)"
}
}
15 changes: 15 additions & 0 deletions Modules/CIPPCore/Public/AdditionalPermissions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"resourceAppId": "00000003-0000-0ff1-ce00-000000000000",
"resourceAccess": [{ "id": "AllProfiles.Manage", "type": "Scope" }]
},
{
"resourceAppId": "fb78d390-0c51-40cd-8e17-fdbfab77341b",
"resourceAccess": [
{ "id": "AdminApi.AccessAsUser.All", "type": "Scope" },
{ "id": "FfoPowerShell.AccessAsUser.All", "type": "Scope" },
{ "id": "RemotePowerShell.AccessAsUser.All", "type": "Scope" },
{ "id": "VivaFeatureAccessPolicy.Manage.All", "type": "Scope" }
]
}
]
Loading

0 comments on commit 6390541

Please sign in to comment.