Skip to content

Commit

Permalink
Merge pull request #14 from KelvinTegelaar/dev
Browse files Browse the repository at this point in the history
[pull] dev from KelvinTegelaar:dev
  • Loading branch information
GeekBoxIT authored Jun 10, 2024
2 parents 7d31ac5 + 737493a commit a05f397
Show file tree
Hide file tree
Showing 70 changed files with 2,892 additions and 403 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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ function Get-CIPPRolePermissions {
[PSCustomObject]@{
Role = $Role.RowKey
Permissions = $Permissions.PSObject.Properties.Value
AllowedTenants = $Role.AllowedTenants | ConvertFrom-Json
AllowedTenants = if ($Role.AllowedTenants) { $Role.AllowedTenants | ConvertFrom-Json } else { @() }
BlockedTenants = if ($Role.BlockedTenants) { $Role.BlockedTenants | ConvertFrom-Json } else { @() }
}
} else {
throw "Role $RoleName not found."
Expand Down
112 changes: 67 additions & 45 deletions Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,91 @@ function Test-CIPPAccess {
}
}
}
if (($CustomRoles | Measure-Object).Count -gt 0 ) {
if (($CustomRoles | Measure-Object).Count -gt 0) {
$Tenants = Get-Tenants -IncludeErrors
$PermissionsFound = $false
$PermissionSet = foreach ($CustomRole in $CustomRoles) {
try {
Get-CIPPRolePermissions -Role $CustomRole
$PermissionsFound = $true
} catch {
Write-Information $_.Exception.Message
continue
}
}
if ($TenantList.IsPresent) {
$AllowedTenants = foreach ($Permission in $PermissionSet) {
foreach ($Tenant in $Permission.AllowedTenants) {
$Tenant
}
}
return $AllowedTenants
}

if (($PermissionSet | Measure-Object).Count -eq 0) {
return $true
} else {
$FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint
$Help = Get-Help $FunctionName
# Check API for required role
$APIRole = $Help.Role
foreach ($Role in $PermissionSet) {
# Loop through each custom role permission and check API / Tenant access
$TenantAllowed = $false
$APIAllowed = $false
foreach ($Perm in $Role.Permissions) {
if ($Perm -match $APIRole) {
$APIAllowed = $true
break
if ($PermissionsFound) {
if ($TenantList.IsPresent) {
$LimitedTenantList = foreach ($Permission in $PermissionSet) {
if (($Permission.AllowedTenants | Measure-Object).Count -eq 0 -and ($Permission.BlockedTenants | Measure-Object).Count -eq 0) {
return @('AllTenants')
} else {
if ($Permission.AllowedTenants -contains 'AllTenants') {
$Permission.AllowedTenants = $Tenants.customerId
}
$Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ }
}
}
if ($APIAllowed) {
# Check tenant level access
if ($Role.AllowedTenants -contains 'AllTenants') {
$TenantAllowed = $true
} elseif ($Request.Query.TenantFilter -eq 'AllTenants' -or $Request.Body.TenantFilter -eq 'AllTenants') {
$TenantAllowed = $false
} 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
Write-Information ($LimitedTenantList | ConvertTo-Json)
return $LimitedTenantList
}

if ($Tenant) {
$TenantAllowed = $Role.AllowedTenants -contains $Tenant
if (!$TenantAllowed) { continue }
if (($PermissionSet | Measure-Object).Count -eq 0) {
return $true
} else {
$FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint
$Help = Get-Help $FunctionName
# Check API for required role
$APIRole = $Help.Role
foreach ($Role in $PermissionSet) {
# Loop through each custom role permission and check API / Tenant access
$TenantAllowed = $false
$APIAllowed = $false
foreach ($Perm in $Role.Permissions) {
if ($Perm -match $APIRole) {
$APIAllowed = $true
break
} else {
}
}
if ($APIAllowed) {
# Check tenant level access
if (($Role.BlockedTenants | Measure-Object).Count -eq 0 -and $Role.AllowedTenants -contains 'AllTenants') {
$TenantAllowed = $true
break
} elseif ($Request.Query.TenantFilter -eq 'AllTenants' -or $Request.Body.TenantFilter -eq 'AllTenants') {
$TenantAllowed = $false
} 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
} else {
$AllowedTenants = $Role.AllowedTenants
}

if ($Tenant) {
$TenantAllowed = $AllowedTenants -contains $Tenant -and $Role.BlockedTenants -notcontains $Tenant
if (!$TenantAllowed) { continue }
break
} else {
$TenantAllowed = $true
break
}
}
}
}
if (!$APIAllowed) {
throw "Access to this CIPP API endpoint is not allowed, the '$($Role.Role)' custom role does not have the required permission: $APIRole"
}
if (!$TenantAllowed) {
throw 'Access to this tenant is not allowed'
} else {
return $true
}
}
if (!$APIAllowed) {
throw "Access to this CIPP API endpoint is not allowed, the '$($Role.Role)' custom role does not have the required permission: $APIRole"
}
if (!$TenantAllowed) {
throw 'Access to this tenant is not allowed'
} else {
return $true
} else {
# No permissions found for any roles
if ($TenantList.IsPresent) {
return @('AllTenants')
}
return $true
}
} else {
return $true
Expand Down
62 changes: 62 additions & 0 deletions Modules/CIPPCore/Public/Clear-CippDurables.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function Clear-CippDurables {
[CmdletBinding(SupportsShouldProcess = $true)]
Param()
# Collect info
$StorageContext = New-AzStorageContext -ConnectionString $env:AzureWebJobsStorage
$FunctionName = $env:WEBSITE_SITE_NAME

# Get orchestrators
$InstancesTable = Get-CippTable -TableName ('{0}Instances' -f $FunctionName)
$HistoryTable = Get-CippTable -TableName ('{0}History' -f $FunctionName)
$Yesterday = (Get-Date).AddDays(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
$Filter = "CreatedTime ge datetime'$Yesterday' or RuntimeStatus eq 'Pending' or RuntimeStatus eq 'Running'"
$Instances = Get-CippAzDataTableEntity @InstancesTable -Filter $Filter

$Queues = Get-AzStorageQueue -Context $StorageContext -Name ('{0}*' -f $FunctionName) | Select-Object -Property Name, ApproximateMessageCount, QueueClient

$RunningQueues = $Queues | Where-Object { $_.ApproximateMessageCount -gt 0 }
foreach ($Queue in $RunningQueues) {
Write-Information "- Removing queue: $($Queue.Name), message count: $($Queue.ApproximateMessageCount)"
if ($PSCmdlet.ShouldProcess($Queue.Name, 'Clear Queue')) {
$Queue.QueueClient.ClearMessagesAsync()
}
}

$QueueTable = Get-CippTable -TableName 'CippQueue'
$CippQueue = Invoke-ListCippQueue
$QueueEntities = foreach ($Queue in $CippQueue) {
if ($Queue.Status -eq 'Running') {
$Queue.TotalTasks = $Queue.CompletedTasks
$Queue | Select-Object -Property PartitionKey, RowKey, TotalTasks
}
}
if (($QueueEntities | Measure-Object).Count -gt 0) {
if ($PSCmdlet.ShouldProcess('Queues', 'Mark Failed')) {
Update-AzDataTableEntity @QueueTable -Entity $QueueEntities
}
}

$CippQueueTasks = Get-CippTable -TableName 'CippQueueTasks'
$RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "Status eq 'Running'" -Property RowKey, PartitionKey, Status
if (($RunningTasks | Measure-Object).Count -gt 0) {
if ($PSCmdlet.ShouldProcess('Tasks', 'Mark Failed')) {
$UpdatedTasks = foreach ($Task in $RunningTasks) {
$Task.Status = 'Failed'
$Task
}
Update-AzDataTableEntity @CippQueueTasks -Entity $UpdatedTasks
}
}

Remove-AzDataTable @InstancesTable
Remove-AzDataTable @HistoryTable
$BlobContainer = '{0}-largemessages' -f $Function.Name
if (Get-AzStorageContainer -Name $BlobContainer -Context $StorageContext -ErrorAction SilentlyContinue) {
Write-Information "- Removing blob container: $BlobContainer"
if ($PSCmdlet.ShouldProcess($BlobContainer, 'Remove Blob Container')) {
Remove-AzStorageContainer -Name $BlobContainer -Context $StorageContext -Confirm:$false -Force
}
}
$null = Get-CippTable -TableName ('{0}History' -f $FunctionName)
Write-Information 'Durable Orchestrators and Queues have been cleared'
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function Push-PublicWebhookProcess {
if ($Webhook.Type -eq 'GraphSubscription') {
Invoke-CippGraphWebhookProcessing -Data ($Webhook.Data | ConvertFrom-Json) -CIPPID $Webhook.CIPPID -WebhookInfo ($Webhook.Webhookinfo | ConvertFrom-Json)
} elseif ($Webhook.Type -eq 'AuditLog') {
Invoke-CippWebhookProcessing -TenantFilter $Webhook.TenantFilter -Data ($Webhook.Data | ConvertFrom-Json) -CIPPPURL $Webhook.CIPPURL
Invoke-CippWebhookProcessing -TenantFilter $Webhook.TenantFilter -Data ($Webhook.Data | ConvertFrom-Json) -CIPPURL $Webhook.CIPPURL
} elseif ($Webhook.Type -eq 'PartnerCenter') {
Invoke-CippPartnerWebhookProcessing -Data ($Webhook.Data | ConvertFrom-Json)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ function Push-Schedulerwebhookcreation {
$item
)
$Table = Get-CIPPTable -TableName 'SchedulerConfig'
$WebhookTable = Get-CIPPTable -TableName 'WebhookTable'
$WebhookTable = Get-CIPPTable -TableName 'webhookTable'

#Write-Information ($item | ConvertTo-Json -Depth 10)
$Row = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($item.SchedulerRow)'"
if (!$Row) {
Write-Host "No row found for $($item.SchedulerRow). Full received item was $($item | ConvertTo-Json)"
Expand All @@ -34,7 +35,7 @@ function Push-Schedulerwebhookcreation {
$NewSub = New-CIPPGraphSubscription -TenantFilter $Tenant -EventType $Row.webhookType -BaseURL $Row.CIPPURL -auditLogAPI $true
if ($NewSub.Success -and $Row.tenantid -ne 'AllTenants') {
Remove-AzDataTableEntity @Table -Entity $Row
} else {
} else {
Write-Host "Failed to create webhook for $Tenant - $($Row.webhookType) - $($_.Exception.Message)"
Write-LogMessage -message "Failed to create webhook for $Tenant - $($Row.webhookType)" -Sev 'Error' -LogData $_.Exception
}
Expand All @@ -47,5 +48,5 @@ function Push-Schedulerwebhookcreation {
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,24 @@ function Push-UpdateTenants {
Write-Host 'Update Tenants already running'
return
}
$Queue = New-CippQueueEntry -Name 'Update Tenants' -Reference $QueueReference
$Queue = New-CippQueueEntry -Name 'Update Tenants' -Reference $QueueReference -TotalTasks 1
try {
$QueueTask = @{
QueueId = $Queue.RowKey
Name = 'Get tenant list'
Status = 'Running'
}
$TaskStatus = Set-CippQueueTask @QueueTask
$QueueTask.TaskId = $TaskStatus.RowKey
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Running'
Get-Tenants | Out-Null
Get-Tenants -IncludeAll -TriggerRefresh | Out-Null
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Completed'
$QueueTask.Status = 'Completed'
Set-CippQueueTask @QueueTask
} catch {
Write-Host "Queue Error: $($_.Exception.Message)"
Update-CippQueueEntry -RowKey $Queue.RowKey -Status 'Failed'
$QueueTask.Status = 'Failed'
Set-CippQueueTask @QueueTask
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,13 @@ function Invoke-ExecDurableFunctions {
$HistoryTable = Get-CippTable -TableName ('{0}History' -f $FunctionName)
if ($Request.Query.PartitionKey) {
$HistoryEntities = Get-CIPPAzDataTableEntity @HistoryTable -Filter "PartitionKey eq '$($Request.Query.PartitionKey)'" -Property RowKey, PartitionKey
Remove-AzDataTableEntity @HistoryTable -Entity $HistoryEntities
if ($HistoryEntities) {
Remove-AzDataTableEntity @HistoryTable -Entity $HistoryEntities
}
$Instance = Get-CIPPAzDataTableEntity @InstancesTable -Filter "PartitionKey eq '$($Request.Query.PartitionKey)'" -Property RowKey, PartitionKey
Remove-AzDataTableEntity @InstancesTable -Entity $Instance
if ($Instance) {
Remove-AzDataTableEntity @InstancesTable -Entity $Instance
}
$Body = [PSCustomObject]@{
Results = 'Orchestrator {0} purged successfully' -f $Request.Query.PartitionKey
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using namespace System.Net

Function Invoke-ExecListBackup {
<#
.FUNCTIONALITY
Entrypoint
.ROLE
CIPP.Backup.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)

$Result = Get-CIPPBackup -type $Request.body.Type -TenantFilter $Request.body.TenantFilter
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Alerts' -message $request.body.text -Sev $request.body.Severity
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = @($Result)
})

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using namespace System.Net

Function Invoke-ExecSetCIPPAutoBackup {
<#
.FUNCTIONALITY
Entrypoint
.ROLE
CIPP.Backup.Read
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
if ($Request.query.Enabled -eq 'True') {
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
$AutomatedCIPPBackupTask = Get-AzDataTableEntity @table -Filter "Name eq 'Automated CIPP Backup'"
$task = @{
RowKey = $AutomatedCIPPBackupTask.RowKey
PartitionKey = 'ScheduledTask'
}
Remove-AzDataTableEntity @Table -Entity $task | Out-Null

$TaskBody = @{
TenantFilter = 'AllTenants'
Name = 'Automated CIPP Backup'
Command = @{
value = 'New-CIPPBackup'
label = 'New-CIPPBackup'
}
Parameters = @{ backupType = 'CIPP' }
ScheduledTime = $unixtime
Recurrence = '1d'
}
Add-CIPPScheduledTask -Task $TaskBody -hidden $false
$Result = @{ 'Results' = 'Scheduled Task Successfully created' }
}
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Alerts' -message $request.body.text -Sev $request.body.Severity
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $Result
})

}
Loading

0 comments on commit a05f397

Please sign in to comment.