Skip to content

Commit

Permalink
Merge pull request #4 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 Aug 21, 2024
2 parents cd126c6 + 2b7fe4c commit af613b4
Show file tree
Hide file tree
Showing 32 changed files with 857 additions and 422 deletions.
10 changes: 5 additions & 5 deletions Config/SharePoint.BPATemplate.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@
},
{
"name": "Resharing by external users",
"value": "isResharingByExternalUsersEnabled",
"formatter": "reverseBool"
"value": "SharepointSettings.isResharingByExternalUsersEnabled",
"formatter": "bool"
},
{
"name": "Allow users to sync from unmanaged devices",
"value": "SharepointSettings.isUnmanagedSyncAppForTenantRestricted",
"formatter": "bool"
"formatter": "reverseBool"
},
{
"name": "Site creation by standards users enabled",
"name": "Site creation by standard users enabled",
"value": "SharepointSettings.isSiteCreationEnabled",
"formatter": "reverseBool"
"formatter": "bool"
},
{
"name": "Deleted user data rention(days)",
Expand Down
21 changes: 20 additions & 1 deletion Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,26 @@ function Add-CIPPApplicationPermission {
}
Set-Location (Get-Item $PSScriptRoot).FullName
if ($RequiredResourceAccess -eq 'CIPPDefaults') {
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
#$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess

$Permissions = Get-CippSamPermissions -NoDiff
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()

foreach ($AppId in $Permissions.Permissions.PSObject.Properties.Name) {
$AppPermissions = @($Permissions.Permissions.$AppId.applicationPermissions)
$Resource = @{
resourceAppId = $AppId
resourceAccess = [System.Collections.Generic.List[object]]::new()
}
foreach ($Permission in $AppPermissions) {
$Resource.ResourceAccess.Add(@{
id = $Permission.id
type = 'Role'
})
}

$RequiredResourceAccess.Add($Resource)
}
}
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
Expand Down
43 changes: 32 additions & 11 deletions Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,31 @@ function Add-CIPPDelegatedPermission {
}

if ($RequiredResourceAccess -eq 'CIPPDefaults') {
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
$AdditionalPermissions = Get-Content '.\AdditionalPermissions.json' | ConvertFrom-Json
$Permissions = Get-CippSamPermissions -NoDiff
$NoTranslateRequired = $Permissions.Type -eq 'Table'
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()
foreach ($AppId in $Permissions.Permissions.PSObject.Properties.Name) {
$DelegatedPermissions = @($Permissions.Permissions.$AppId.delegatedPermissions)
$ResourceAccess = [System.Collections.Generic.List[object]]::new()
foreach ($Permission in $DelegatedPermissions) {
$ResourceAccess.Add(@{
id = $Permission.value
type = 'Scope'
})
}
$Resource = @{
resourceAppId = $AppId
resourceAccess = @($ResourceAccess)
}
$RequiredResourceAccess.Add($Resource)
}

if ($Tenantfilter -eq $env:TenantID) {
$RequiredResourceAccess = $RequiredResourceAccess + ($AdditionalPermissions | Where-Object { $RequiredResourceAccess.resourceAppId -notcontains $_.resourceAppId })
} else {
# remove the partner center permission if not pushing to partner tenant
$RequiredResourceAccess = $RequiredResourceAccess | Where-Object { $_.resourceAppId -ne 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd' }
}
$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 -NoAuthCheck $true
Expand All @@ -46,16 +61,22 @@ function Add-CIPPDelegatedPermission {
continue
}
}
$AdditionalScopes = ($AdditionalPermissions | Where-Object -Property resourceAppId -EQ $App.resourceAppId).resourceAccess | Where-Object -Property type -EQ 'Scope'

$DelegatedScopes = $App.resourceAccess | Where-Object -Property type -EQ 'Scope'
if ($AdditionalScopes) {
$NewScope = (@(($Translator | Where-Object { $_.id -in $DelegatedScopes.id }).value) + @($AdditionalScopes.id | Select-Object -Unique)) -join ' '
if ($NoTranslateRequired) {
$NewScope = @($DelegatedScopes | ForEach-Object { $_.id } | Sort-Object -Unique) -join ' '
} else {
if ($NoTranslateRequired) {
$NewScope = @($DelegatedScopes | ForEach-Object { $_.id } | Sort-Object -Unique) -join ' '
} else {
$NewScope = @(($Translator | Where-Object { $_.id -in $DelegatedScopes.id }).value | Sort-Object -Unique) -join ' '
$NewScope = foreach ($Scope in $DelegatedScopes.id) {
if ($Scope -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') {
$TranslatedScope = ($Translator | Where-Object -Property id -EQ $Scope).value
if ($TranslatedScope) {
$TranslatedScope
}
} else {
$Scope
}
}
$NewScope = (@($NewScope) | Sort-Object -Unique) -join ' '
}

$OldScope = ($CurrentDelegatedScopes | Where-Object -Property Resourceid -EQ $svcPrincipalId.id)
Expand Down Expand Up @@ -83,7 +104,7 @@ function Add-CIPPDelegatedPermission {
# Added permissions
$Added = ($Compare | Where-Object { $_.SideIndicator -eq '=>' }).InputObject -join ' '
$Removed = ($Compare | Where-Object { $_.SideIndicator -eq '<=' }).InputObject -join ' '
$Results.add("Successfully updated permissions for $($svcPrincipalId.displayName). $(if ($Added) { "Added: $Added"}) $(if ($Removed) { "Removed: $Removed"})")
$Results.add("Successfully updated permissions for $($svcPrincipalId.displayName). $(if ($Added) { "Added: $Added"}) $(if ($Removed) { "Removed: $Removed"})")
}
}

Expand Down
4 changes: 4 additions & 0 deletions Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ function Add-CIPPScheduledTask {
$task.Recurrence.value
}

if ([int64]$task.ScheduledTime -eq 0 -or [string]::IsNullOrEmpty($task.ScheduledTime)) {
$task.ScheduledTime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
}

$entity = @{
PartitionKey = [string]'ScheduledTask'
TaskState = [string]'Planned'
Expand Down
44 changes: 44 additions & 0 deletions Modules/CIPPCore/Public/Alerts/Get-CIPPAlertHuntressRogueApps.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function Get-CIPPAlertHuntressRogueApps {
<#
.SYNOPSIS
Check for rogue apps in a Tenant
.DESCRIPTION
This function checks for rogue apps in the tenant by comparing the service principals in the tenant with a list of known rogue apps provided by Huntress.
.FUNCTIONALITY
Entrypoint
.LINK
https://huntresslabs.github.io/rogueapps/
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false)]
[Alias('input')]
$InputValue,
$TenantFilter
)

try {
$RogueApps = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/huntresslabs/rogueapps/main/public/rogueapps.json'
$RogueAppFilter = $RogueApps.appId -join "','"
$ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId in ('$RogueAppFilter')" -tenantid $TenantFilter

if (($ServicePrincipals | Measure-Object).Count -gt 0) {
$AlertData = foreach ($ServicePrincipal in $ServicePrincipals) {
$RogueApp = $RogueApps | Where-Object { $_.appId -eq $ServicePrincipal.appId }
[pscustomobject]@{
'App Name' = $RogueApp.appDisplayName
'App Id' = $RogueApp.appId
'Description' = $RogueApp.description
'Enabled' = $ServicePrincipal.accountEnabled
'Created' = $ServicePrincipal.createdDateTime
'Tags' = $RogueApp.tags -join ', '
'References' = $RogueApp.references -join ', '
'Huntress Added' = $RogueApp.dateAdded
}
}
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
}
} catch {
#Write-AlertMessage -tenant $($TenantFilter) -message "Failed to check for rogue apps for $($TenantFilter): $(Get-NormalizedError -message $_.Exception.message)"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function Push-ExecScheduledCommand {
Entrypoint
#>
param($Item)
$item = $Item | ConvertTo-Json -Depth 100 | ConvertFrom-Json
Write-Host "We are going to be running a scheduled task: $($Item.TaskInfo | ConvertTo-Json -Depth 10)"

$Table = Get-CippTable -tablename 'ScheduledTasks'
Expand Down Expand Up @@ -99,8 +100,16 @@ function Push-ExecScheduledCommand {
'(\d+)d$' { [int64]$matches[1] * 86400 }
default { throw "Unsupported recurrence format: $($task.Recurrence)" }
}

if ($secondsToAdd -gt 0) {
$unixtimeNow = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
if ([int64]$task.ScheduledTime -lt ($unixtimeNow - $secondsToAdd)) {
$task.ScheduledTime = $unixtimeNow
}
}

$nextRunUnixTime = [int64]$task.ScheduledTime + [int64]$secondsToAdd
Write-Host "The job is recurring and should occur again at: $nextRunUnixTime"
Write-Host "The job is recurring. It was scheduled for $($task.ScheduledTime). The next runtime should be $nextRunUnixTime"
Update-AzDataTableEntity @Table -Entity @{
PartitionKey = $task.PartitionKey
RowKey = $task.RowKey
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
function Push-AuditLogTenant {
Param($Item)

# Get Table contexts
$AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles'
$SchedulerConfig = Get-CIPPTable -TableName 'SchedulerConfig'
$CIPPURL = Get-CIPPAzDataTableEntity @SchedulerConfig -Filter "PartitionKey eq 'webhookcreation'" | Select-Object -First 1 -ExpandProperty CIPPURL
$SchedulerConfig = Get-CippTable -TableName 'SchedulerConfig'
$WebhookTable = Get-CippTable -tablename 'webhookTable'
$ConfigTable = Get-CippTable -TableName 'WebhookRules'

# Query CIPPURL for linking
$CIPPURL = Get-CIPPAzDataTableEntity @SchedulerConfig -Filter "PartitionKey eq 'webhookcreation'" | Select-Object -First 1 -ExpandProperty CIPPURL

# Get all webhooks for the tenant
$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'"
$ConfigTable = Get-CIPPTable -TableName 'WebhookRules'

# Get webhook rules
$ConfigEntries = Get-CIPPAzDataTableEntity @ConfigTable

# Date filter for existing bundles
$LastHour = (Get-Date).AddHours(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss')

$NewBundles = [System.Collections.Generic.List[object]]::new()
foreach ($Webhook in $Webhooks) {
# only process webhooks that are configured in the webhookrules table
Expand All @@ -28,6 +37,7 @@ function Push-AuditLogTenant {
EndTime = $Item.EndTime
}
$LogBundles = Get-CIPPAuditLogContentBundles @ContentBundleQuery
$ExistingBundles = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and ContentType eq '$LogType' and Timestamp ge datetime'$($LastHour)'"

foreach ($Bundle in $LogBundles) {
if ($ExistingBundles.RowKey -notcontains $Bundle.contentId) {
Expand Down Expand Up @@ -61,5 +71,4 @@ function Push-AuditLogTenant {
$InstanceId = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
Write-Host "Started orchestration with ID = '$InstanceId'"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
function Invoke-ExecServicePrincipals {
<#
.FUNCTIONALITY
Entrypoint
.ROLE
CIPP.Core.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)

$TenantFilter = $env:TenantId

$Success = $true

$Action = $Request.Query.Action ?? 'Default'
try {
switch ($Request.Query.Action) {
'Create' {
$Action = 'Create'
if ($Request.Query.AppId -match '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$') {
$Body = @{
'appId' = $Request.Query.AppId
} | ConvertTo-Json -Compress
try {
$Results = New-GraphPostRequest -Uri 'https://graph.microsoft.com/beta/servicePrincipals' -tenantid $TenantFilter -type POST -body $Body
} catch {
$Results = "Unable to create service principal: $($_.Exception.Message)"
$Success = $false
}
} else {
$Results = 'Invalid AppId'
$Success = $false
}
}
default {
if ($Request.Query.AppId) {
$Action = 'Get'
$Results = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($Request.Query.AppId)')" -tenantid $TenantFilter -NoAuthCheck $true
} else {
$Action = 'List'
$Results = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/servicePrincipals?$top=999&$orderby=displayName&$count=true' -ComplexFilter -tenantid $TenantFilter -NoAuthCheck $true
}
}
}
} catch {
$Results = $_.Exception.Message
$Success = $false
}

$Metadata = @{
'Action' = $Action
'Success' = $Success
}

if ($Request.Query.AppId) {
$Metadata.AppId = $Request.Query.AppId
}

$Body = @{
'Results' = $Results
'Metadata' = $Metadata
}

$Json = $Body | ConvertTo-Json -Depth 10 -Compress
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $Json
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

Function Invoke-ExecOffloadFunctions {
<#
.FUNCTIONALITY
Entrypoint
.ROLE
CIPP.SuperAdmin.ReadWrite
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)

$roles = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json).userRoles
if ('superadmin' -notin $roles) {
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::Forbidden
Body = @{ error = 'You do not have permission to perform this action.' }
})
return
} else {
$Table = Get-CippTable -tablename 'Config'

if ($Request.Query.Action -eq 'ListCurrent') {
$CurrentState = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'OffloadFunctions' and RowKey eq 'OffloadFunctions'"
$CurrentState = if (!$CurrentState) {
[PSCustomObject]@{
OffloadFunctions = $false
}
} else {
[PSCustomObject]@{
OffloadFunctions = $CurrentState.state
}
}
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $CurrentState
})
} else {
Add-CIPPAzDataTableEntity @Table -Entity @{
PartitionKey = 'OffloadFunctions'
RowKey = 'OffloadFunctions'
state = $request.Body.OffloadFunctions
} -Force

if ($Request.Body.OffloadFunctions) {
$Results = 'Enabled Offload Functions'
} else {
$Results = 'Disabled Offload Functions'
}
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = @{ results = $Results }
})
}

}
}
Loading

0 comments on commit af613b4

Please sign in to comment.