Skip to content

Commit

Permalink
Merge branch 'KelvinTegelaar:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
robybrisson authored Jul 5, 2024
2 parents ba34cd1 + b879351 commit 861fb29
Show file tree
Hide file tree
Showing 139 changed files with 2,702 additions and 1,661 deletions.
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
insert_final_newline = true

[*.{ps1, psd1, psm1}]
indent_size = 4
end_of_line = crlf
trim_trailing_whitespace = true

[*.json]
indent_size = 2
end_of_line = crlf
trim_trailing_whitespace = true

[*.{md, txt}]
end_of_line = crlf
max_line_length = off
trim_trailing_whitespace = false
39 changes: 39 additions & 0 deletions .github/workflows/dev_cippacnqv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy Powershell project to Azure Function App - cippacnqv

on:
push:
branches:
- dev
workflow_dispatch:

env:
AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root

jobs:
deploy:
runs-on: windows-latest
permissions:
id-token: write #This is required for requesting the JWT

steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@v4

- name: Login to Azure
uses: azure/login@v1
with:
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_6085081ED1124B799258E9FF743FF4B9 }}
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_9BDB2DDBFAFA4BC19C20A58B204BFAF3 }}
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_02B5224812794971B05EDD557AF2B867 }}

- name: 'Run Azure Functions Action'
uses: Azure/functions-action@v1
id: fa
with:
app-name: 'cippacnqv'
slot-name: 'Production'
package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}

10 changes: 4 additions & 6 deletions BestPracticeAnalyser_OrchestrationStarter/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ if ($Request.Query.TenantFilter) {
$TenantList = Get-Tenants
$Name = 'Best Practice Analyser (All Tenants)'
}
$CippRoot = (Get-Item $PSScriptRoot).Parent.FullName
$TemplatesLoc = Get-ChildItem "$CippRoot\Config\*.BPATemplate.json"
$Templates = $TemplatesLoc | ForEach-Object {
$Template = $(Get-Content $_) | ConvertFrom-Json
$Template.Name
}

$BPATemplateTable = Get-CippTable -tablename 'templates'
$Filter = "PartitionKey eq 'BPATemplate'"
$Templates = ((Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json).Name

$BPAReports = foreach ($Tenant in $TenantList) {
foreach ($Template in $Templates) {
Expand Down
10 changes: 4 additions & 6 deletions BestPracticeAnalyser_OrchestrationStarterTimer/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ if ($env:DEV_SKIP_BPA_TIMER) {

$TenantList = Get-Tenants

$CippRoot = (Get-Item $PSScriptRoot).Parent.FullName
$TemplatesLoc = Get-ChildItem "$CippRoot\Config\*.BPATemplate.json"
$Templates = $TemplatesLoc | ForEach-Object {
$Template = $(Get-Content $_) | ConvertFrom-Json
$Template.Name
}
$BPATemplateTable = Get-CippTable -tablename 'templates'
$Filter = "PartitionKey eq 'BPATemplate'"
$Templates = ((Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json).Name


$BPAReports = foreach ($Tenant in $TenantList) {
foreach ($Template in $Templates) {
Expand Down
388 changes: 184 additions & 204 deletions Cache_SAMSetup/SAMManifest.json

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@ function Get-CIPPAlertQuotaUsed {
} catch {
return
}
$AlertData | ForEach-Object {
if ($_.StorageUsedInBytes -eq 0) { return }
$OverQuota = $AlertData | ForEach-Object {
if ($_.StorageUsedInBytes -eq 0 -or $_.prohibitSendReceiveQuotaInBytes -eq 0) { return }
$PercentLeft = [math]::round(($_.storageUsedInBytes / $_.prohibitSendReceiveQuotaInBytes) * 100)
if ($InputValue) { $Value = [int]$InputValue } else { $Value = 90 }
try {
if ([int]$InputValue -gt 0) {
$Value = [int]$InputValue
} else {
$Value = 90
}
} catch {
$Value = 90
}
if ($PercentLeft -gt $Value) {
"$($_.userPrincipalName): Mailbox is more than $($value)% full. Mailbox is $PercentLeft% full"
}

}
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData

}
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $OverQuota
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ function Get-CIPPAlertSharepointQuota {
$TenantFilter
)
Try {
$tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $TenantFilter | Where-Object { $_.isInitial -eq $true }).id.Split('.')[0]
$tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/sites/root' -asApp $true -tenantid $TenantFilter).id.Split('.')[0]
$sharepointToken = (Get-GraphToken -scope "https://$($tenantName)-admin.sharepoint.com/.default" -tenantid $TenantFilter)
$sharepointToken.Add('accept', 'application/json')
$sharepointQuota = (Invoke-RestMethod -Method 'GET' -Headers $sharepointToken -Uri "https://$($tenantName)-admin.sharepoint.com/_api/StorageQuotas()?api-version=1.3.2" -ErrorAction Stop).value
} catch {
return
}
if ($sharepointQuota) {
if ($InputValue -Is [Boolean]) { $Value = 90 } else { $Value = $InputValue }
try {
if ([int]$InputValue -gt 0) { $Value = [int]$InputValue } else { $Value = 90 }
} catch {
$Value = 90
}
$UsedStoragePercentage = [int](($sharepointQuota.GeoUsedStorageMB / $sharepointQuota.TenantStorageMB) * 100)
if ($UsedStoragePercentage -gt $Value) {
$AlertData = "SharePoint Storage is at $($UsedStoragePercentage)%. Your alert threshold is $($Value)%"
Expand Down
6 changes: 2 additions & 4 deletions Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ function Test-CIPPAccess {
$Request,
[switch]$TenantList
)

if ($Request.Params.CIPPEndpoint -eq 'ExecSAMSetup') { return $true }
if (!$Request.Headers.'x-ms-client-principal') {
# Direct API Access
$CustomRoles = @('CIPP-API')
Expand Down Expand Up @@ -47,7 +47,6 @@ function Test-CIPPAccess {
$Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
}
}
Write-Information ($LimitedTenantList | ConvertTo-Json)
return $LimitedTenantList
}

Expand Down Expand Up @@ -77,11 +76,10 @@ function Test-CIPPAccess {
} else {
$Tenant = ($Tenants | Where-Object { $Request.Query.TenantFilter -eq $_.customerId -or $Request.Body.TenantFilter -eq $_.customerId -or $Request.Query.TenantFilter -eq $_.defaultDomainName -or $Request.Body.TenantFilter -eq $_.defaultDomainName }).customerId
if ($Role.AllowedTenants -contains 'AllTenants') {
$AllowedTenants = $Tenants
$AllowedTenants = $Tenants.customerId
} else {
$AllowedTenants = $Role.AllowedTenants
}

if ($Tenant) {
$TenantAllowed = $AllowedTenants -contains $Tenant -and $Role.BlockedTenants -notcontains $Tenant
if (!$TenantAllowed) { continue }
Expand Down
1 change: 1 addition & 0 deletions Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function Invoke-ListCippQueue {
$TotalCompleted = $TaskStatus.Completed ?? 0
$TotalFailed = $TaskStatus.Failed ?? 0
$TotalRunning = $TaskStatus.Running ?? 0
if ($Queue.TotalTasks -eq 0) { $Queue.TotalTasks = 1 }

[PSCustomObject]@{
PartitionKey = $Queue.PartitionKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ function Push-BPACollectData {
param($Item)

$TenantName = Get-Tenants | Where-Object -Property defaultDomainName -EQ $Item.Tenant
$CippRoot = (Get-Item $PSScriptRoot).Parent.Parent.Parent.Parent.Parent.Parent.FullName
$TemplatesLoc = Get-ChildItem "$CippRoot\Config\*.BPATemplate.json"
$BPATemplateTable = Get-CippTable -tablename 'templates'
$Filter = "PartitionKey eq 'BPATemplate'"
$TemplatesLoc = (Get-CIPPAzDataTableEntity @BPATemplateTable -Filter $Filter).JSON | ConvertFrom-Json

$Templates = $TemplatesLoc | ForEach-Object {
$Template = $(Get-Content $_) | ConvertFrom-Json
$Template = $_
[PSCustomObject]@{
Data = $Template
Name = $Template.Name
Style = $Template.Style
}
}
$Table = Get-CippTable -tablename 'cachebpav2'

Write-Host "Working on BPA for $($TenantName.displayName) with GUID $($TenantName.customerId) - Report ID $($Item.Template)"
$Template = $Templates | Where-Object -Property Name -EQ -Value $Item.Template
# Build up the result object that will be stored in tables
$Result = @{
Expand All @@ -39,13 +41,13 @@ function Push-BPACollectData {
}
if ($Field.parameters.psobject.properties.name) {
$field.Parameters | ForEach-Object {
Write-Information "Doing: $($_.psobject.properties.name) with value $($_.psobject.properties.value)"
$paramsField[$_.psobject.properties.name] = $_.psobject.properties.value
}
}
$FieldInfo = New-GraphGetRequest @paramsField | Where-Object $filterscript | Select-Object $field.ExtractFields
}
'Exchange' {
Write-Host "Trying to execute $($field.Command) for $($TenantName.displayName) with GUID $($TenantName.customerId)"
if ($field.Command -notlike 'get-*') {
Write-LogMessage -API 'BPA' -tenant $tenant -message 'The BPA only supports get- exchange commands. A set or update command was used.' -sev Error
break
Expand Down Expand Up @@ -93,6 +95,7 @@ function Push-BPACollectData {
}
'JSON' {
if ($FieldInfo -eq $null) { $JsonString = '{}' } else { $JsonString = (ConvertTo-Json -Depth 15 -InputObject $FieldInfo -Compress) }
Write-Host "Adding $($field.Name) to table with value $JsonString"
$Result.Add($field.Name, $JSONString)
}
'string' {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function Push-DomainAnalyserDomain {
}
Set-DnsResolver -Resolver $Resolver

$Domain = $DomainObject.rowKey
$Domain = $DomainObject.RowKey

try {
$Tenant = $DomainObject.TenantDetails | ConvertFrom-Json -ErrorAction Stop
Expand Down Expand Up @@ -250,7 +250,7 @@ function Push-DomainAnalyserDomain {
# Final Write to Output
Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "DNS Analyser Finished For $Domain" -sev Info
} catch {
Write-LogMessage -API -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "Error saving domain $Domain to table " -sev Error -LogData (Get-CippException -Exception $_)
Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "Error saving domain $Domain to table " -sev Error -LogData (Get-CippException -Exception $_)
}
return $null
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function Push-DomainAnalyserTenant {
return
} else {
try {
$Domains = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains' -tenantid $Tenant.customerId | Where-Object { ($_.id -notlike '*.microsoftonline.com' -and $_.id -NotLike '*.exclaimer.cloud' -and $_.id -Notlike '*.excl.cloud' -and $_.id -NotLike '*.codetwo.online' -and $_.id -NotLike '*.call2teams.com' -and $_.isVerified) }
$Domains = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains' -tenantid $Tenant.customerId | Where-Object { ($_.id -notlike '*.microsoftonline.com' -and $_.id -NotLike '*.exclaimer.cloud' -and $_.id -Notlike '*.excl.cloud' -and $_.id -NotLike '*.codetwo.online' -and $_.id -NotLike '*.call2teams.com' -and $_.isVerified) }

$TenantDomains = foreach ($d in $Domains) {
[PSCustomObject]@{
Expand All @@ -38,9 +38,11 @@ function Push-DomainAnalyserTenant {
}
}

Write-Information ($TenantDomains | ConvertTo-Json -Depth 10)

$DomainCount = ($TenantDomains | Measure-Object).Count
if ($DomainCount -gt 0) {
Write-Host "$DomainCount tenant Domains"
Write-Host "############# $DomainCount tenant Domains"
$TenantDomainObjects = [System.Collections.Generic.List[object]]::new()
try {
foreach ($TenantDomain in $TenantDomains) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ function Push-ExecScheduledCommand {
$TableDesign = '<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>'
$FinalResults = if ($results -is [array] -and $results[0] -is [string]) { $Results | ConvertTo-Html -Fragment -Property @{ l = 'Text'; e = { $_ } } } else { $Results | ConvertTo-Html -Fragment }
$HTML = $FinalResults -replace '<table>', "This alert is for tenant $tenant. <br /><br /> $TableDesign<table class=blueTable>" | Out-String
$title = "$TaskType - $($task.Name) - $tenant"
$title = "$TaskType - $tenant - $($task.Name)"
Write-Host 'Scheduler: Sending the results to the target.'
Write-Host "The content of results is: $Results"
switch -wildcard ($task.PostExecution) {
'*psa*' { Send-CIPPAlert -Type 'psa' -Title $title -HTMLContent $HTML }
'*email*' { Send-CIPPAlert -Type 'email' -Title $title -HTMLContent $HTML }
'*psa*' { Send-CIPPAlert -Type 'psa' -Title $title -HTMLContent $HTML -TenantFilter $tenant }
'*email*' { Send-CIPPAlert -Type 'email' -Title $title -HTMLContent $HTML -TenantFilter $tenant }
'*webhook*' {
$Webhook = [PSCustomObject]@{
'Tenant' = $tenant
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
function Push-AuditLogBundleProcessing {
Param($Item)

try {
$AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles'
$AuditLogBundle = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and RowKey eq '$($Item.ContentId)'"
if ($AuditLogBundle.ProcessingStatus -ne 'Pending') {
Write-Information 'Audit log bundle already processed'
return
}
try {
$AuditLogTest = Test-CIPPAuditLogRules -TenantFilter $Item.TenantFilter -LogType $AuditLogBundle.ContentType -ContentUri $AuditLogBundle.ContentUri
$AuditLogBundle.ProcessingStatus = 'Completed'
$AuditLogBundle.MatchedRules = [string](ConvertTo-Json -Compress -Depth 10 -InputObject $AuditLogTest.MatchedRules)
$AuditLogBundle.MatchedLogs = $AuditLogTest.MatchedLogs
} catch {
$AuditLogBundle.ProcessingStatus = 'Failed'
$AuditLogBundle | Add-Member -NotePropertyName Error -NotePropertyValue $_.InvocationInfo.PositionMessage -TypeName string
}
try {
Add-CIPPAzDataTableEntity @AuditBundleTable -Entity $AuditLogBundle -Force
} catch {
Write-Host ( 'Error logging audit bundle: {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
}

$DataToProcess = ($AuditLogTest).DataToProcess
Write-Information "Webhook: Data to process found: $($DataToProcess.count) items"
foreach ($AuditLog in $DataToProcess) {
Write-Information "Processing $($AuditLog.operation)"
$Webhook = @{
Data = $AuditLog
CIPPURL = [string]$AuditLogBundle.CIPPURL
TenantFilter = $Item.TenantFilter
}
Invoke-CippWebhookProcessing @Webhook
}
} catch {
Write-Host ( 'Audit log error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
function Push-AuditLogTenant {
Param($Item)

$AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles'
$SchedulerConfig = Get-CIPPTable -TableName 'SchedulerConfig'
$CIPPURL = Get-CIPPAzDataTableEntity @SchedulerConfig -Filter "PartitionKey eq 'webhookcreation'" | Select-Object -First 1 -ExpandProperty CIPPURL
$WebhookTable = Get-CippTable -tablename 'webhookTable'
$Webhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and Version eq '3'" | Where-Object { $_.Resource -match '^Audit' }
$ExistingBundles = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and ContentType eq '$ContentType'"

$NewBundles = [System.Collections.Generic.List[object]]::new()
foreach ($Webhook in $Webhooks) {
$TenantFilter = $Webhook.PartitionKey
$LogType = $Webhook.Resource
Write-Information "Querying for $LogType on $TenantFilter"
$ContentBundleQuery = @{
TenantFilter = $TenantFilter
ContentType = $LogType
StartTime = $Item.StartTime
EndTime = $Item.EndTime
}
$LogBundles = Get-CIPPAuditLogContentBundles @ContentBundleQuery

foreach ($Bundle in $LogBundles) {
if ($ExistingBundles.RowKey -notcontains $Bundle.contentId) {
$NewBundles.Add([PSCustomObject]@{
PartitionKey = $TenantFilter
RowKey = $Bundle.contentId
DefaultDomainName = $TenantFilter
ContentType = $Bundle.contentType
ContentUri = $Bundle.contentUri
ContentCreated = $Bundle.contentCreated
ContentExpiration = $Bundle.contentExpiration
CIPPURL = [string]$CIPPURL
ProcessingStatus = 'Pending'
MatchedRules = ''
MatchedLogs = 0
})
}
}
}

if (($NewBundles | Measure-Object).Count -gt 0) {
Add-CIPPAzDataTableEntity @AuditBundleTable -Entity $NewBundles
Write-Information ($NewBundles | ConvertTo-Json -Depth 5 -Compress)

$Batch = $NewBundles | Select-Object @{Name = 'ContentId'; Expression = { $_.RowKey } }, @{Name = 'TenantFilter'; Expression = { $_.PartitionKey } }, @{Name = 'FunctionName'; Expression = { 'AuditLogBundleProcessing' } }
$InputObject = [PSCustomObject]@{
OrchestratorName = 'AuditLogs'
Batch = @($Batch)
SkipLog = $true
}
$InstanceId = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
Write-Host "Started orchestration with ID = '$InstanceId'"
}

}
Loading

0 comments on commit 861fb29

Please sign in to comment.