Skip to content

Commit

Permalink
Merge pull request #34 from KelvinTegelaar/master
Browse files Browse the repository at this point in the history
[pull] master from KelvinTegelaar:master
  • Loading branch information
pull[bot] authored Jun 9, 2024
2 parents 94e74b7 + 017b742 commit 5c24a3a
Show file tree
Hide file tree
Showing 69 changed files with 2,870 additions and 403 deletions.
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
})

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Function Invoke-ListScheduledItems {
# Write to the Azure Functions log stream.
Write-Host 'PowerShell HTTP trigger function processed a request.'
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
if ($Request.query.Showhidden -eq 'true') {
if ($Request.Query.Showhidden -eq $true) {
$HiddenTasks = $false
} else {
$HiddenTasks = $true
Expand All @@ -24,7 +24,11 @@ Function Invoke-ListScheduledItems {
$Tasks = $Tasks | Where-Object -Property TenantId -In $AllowedTenants
}
$ScheduledTasks = foreach ($Task in $tasks) {
$Task.Parameters = $Task.Parameters | ConvertFrom-Json
if ($Task.Parameters) {
$Task.Parameters = $Task.Parameters | ConvertFrom-Json -ErrorAction SilentlyContinue
} else {
$Task | Add-Member -NotePropertyName Parameters -NotePropertyValue @{}
}
$Task
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ Function Invoke-RemoveScheduledItem {
RowKey = $Request.Query.ID
PartitionKey = 'ScheduledTask'
}


$Table = Get-CIPPTable -TableName 'ScheduledTasks'
Remove-AzDataTableEntity @Table -Entity $task

Expand Down
Loading

0 comments on commit 5c24a3a

Please sign in to comment.