Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] dev from KelvinTegelaar:dev #78

Merged
merged 12 commits into from
Jul 25, 2024
7 changes: 7 additions & 0 deletions Modules/CIPPCore/Public/AdditionalPermissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@
{
"resourceAppId": "00000003-0000-0ff1-ce00-000000000000",
"resourceAccess": [{ "id": "AllProfiles.Manage", "type": "Scope" }]
},
{
"resourceAppId": "00000006-0000-0ff1-ce00-000000000000",
"resourceAccess": [
{ "id": "M365AdminPortal.IntegratedApps.ReadWrite", "type": "Scope" },
{ "id": "user_impersonation", "type": "Scope" }
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,33 @@ function Push-Schedulerwebhookcreation {
)
$Table = Get-CIPPTable -TableName 'SchedulerConfig'
$WebhookTable = Get-CIPPTable -TableName 'webhookTable'

#Write-Information ($item | ConvertTo-Json -Depth 10)
$Tenant = $Item.Tenant
$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)"
Write-Information "No row found for $($item.SchedulerRow). Full received item was $($item | ConvertTo-Json)"
return
} else {
if ($Row.tenantid -eq 'AllTenants') {
$Tenants = (Get-Tenants).defaultDomainName
Write-Information "Working on $Tenant - $($Item.Tenantid)"
#use the queueitem to see if we already have a webhook for this tenant + webhooktype. If we do, delete this row from SchedulerConfig.
$Webhook = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq '$Tenant' and Version eq '3' and Resource eq '$($Row.webhookType)'"
if ($Webhook) {
Write-Information "Found existing webhook for $Tenant - $($Row.webhookType)"
if ($Row.tenantid -ne 'AllTenants') {
Remove-AzDataTableEntity @Table -Entity $Row
}
} else {
$Tenants = (Get-Tenants | Where-Object { $_.customerId -eq $Row.tenantid }).defaultDomainName
}
foreach ($Tenant in $Tenants) {
Write-Host "Working on $Tenant - $($Row.tenantid)"
#use the queueitem to see if we already have a webhook for this tenant + webhooktype. If we do, delete this row from SchedulerConfig.
$Webhook = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq '$Tenant' and Version eq '3' and Resource eq '$($Row.webhookType)'"
if ($Webhook) {
Write-Host "Found existing webhook for $Tenant - $($Row.webhookType)"
if ($Row.tenantid -ne 'AllTenants') {
Write-Information "No existing webhook for $Tenant - $($Row.webhookType) - Time to create."
try {
$NewSub = New-CIPPGraphSubscription -TenantFilter $Tenant -EventType $Row.webhookType -auditLogAPI $true
if ($NewSub.Success -and $Row.tenantid -ne 'AllTenants') {
Remove-AzDataTableEntity @Table -Entity $Row
} else {
Write-Information "Failed to create webhook for $Tenant - $($Row.webhookType) - $($_.Exception.Message)"
}
} else {
Write-Host "No existing webhook for $Tenant - $($Row.webhookType) - Time to create."
try {
$NewSub = New-CIPPGraphSubscription -TenantFilter $Tenant -EventType $Row.webhookType -auditLogAPI $true
if ($NewSub.Success -and $Row.tenantid -ne 'AllTenants') {
Remove-AzDataTableEntity @Table -Entity $Row
} else {
Write-Host "Failed to create webhook for $Tenant - $($Row.webhookType) - $($_.Exception.Message)"
}
} catch {
Write-Host "Failed to create webhook for $Tenant - $($Row.webhookType): $($_.Exception.Message)"
}

} catch {
Write-Information "Failed to create webhook for $Tenant - $($Row.webhookType): $($_.Exception.Message)"
}
}
}

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

if ($Request.Body.TenantID -notmatch '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') {
$Body = @{Results = "Tenant ID $($Request.Body.TenantID) is not a valid GUID." }
$StatusCode = [HttpStatusCode]::BadRequest
} else {
$Table = Get-CippTable -tablename 'Tenants'
$Tenant = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'Tenants' and RowKey eq '$($Request.Body.TenantID)'" -Property RowKey, PartitionKey, customerId, displayName
if ($Tenant) {
try {
Remove-AzDataTableEntity @Table -Entity $Tenant
$Body = @{Results = "$($Tenant.displayName) ($($Tenant.customerId)) deleted from CIPP. Note: This does not remove the GDAP relationship, see the Tenant Offboarding wizard to perform that action." }
$StatusCode = [HttpStatusCode]::OK
} catch {
$Body = @{Results = "Failed to delete $($Tenant.displayName) ($($Tenant.customerId)) from CIPP. Error: $($_.Exception.Message)" }
$StatusCode = [HttpStatusCode]::InternalServerError
}
} else {
$Body = @{Results = "Tenant $($Request.Body.TenantID) not found in CIPP." }
$StatusCode = [HttpStatusCode]::NotFound
}
}

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = $Body
})
}
35 changes: 16 additions & 19 deletions Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,42 @@ Function Invoke-ListLogs {
[CmdletBinding()]
param($Request, $TriggerMetadata)

$AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
$APIName = $TriggerMetadata.FunctionName
Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug'

$TenantList = Get-Tenants -IncludeErrors
if ($request.Query.Filter -eq 'True') {
$LogLevel = if ($Request.query.Severity) { ($Request.query.Severity).split(',') } else { 'Info', 'Warn', 'Error', 'Critical', 'Alert' }
$PartitionKey = $Request.query.DateFilter
$username = $Request.Query.User
} else {
$LogLevel = 'Info', 'Warn', 'Error', 'Critical', 'Alert'
$PartitionKey = Get-Date -UFormat '%Y%m%d'
$username = '*'
}
$Table = Get-CIPPTable

$ReturnedLog = if ($Request.Query.ListLogs) {

Get-CIPPAzDataTableEntity @Table -Property PartitionKey | Sort-Object -Unique PartitionKey | Select-Object PartitionKey | ForEach-Object {
Get-AzDataTableEntity @Table -Property PartitionKey | Sort-Object -Unique PartitionKey | Select-Object PartitionKey | ForEach-Object {
@{
value = $_.PartitionKey
label = $_.PartitionKey
}
}
} else {
if ($request.Query.Filter -eq 'True') {
$LogLevel = if ($Request.query.Severity) { ($Request.query.Severity).split(',') } else { 'Info', 'Warn', 'Error', 'Critical', 'Alert' }
$PartitionKey = $Request.query.DateFilter
$username = $Request.Query.User
} else {
$LogLevel = 'Info', 'Warn', 'Error', 'Critical', 'Alert'
$PartitionKey = Get-Date -UFormat '%Y%m%d'
$username = '*'
}
$AllowedTenants = Test-CIPPAccess -Request $Request -TenantList
$Filter = "PartitionKey eq '{0}'" -f $PartitionKey
$Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Severity -In $LogLevel -and $_.user -like $username }
$Rows = Get-AzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Severity -In $LogLevel -and $_.user -like $username }
foreach ($Row in $Rows) {

if ($AllowedTenants -notcontains 'AllTenants') {
if ($Row.Tenant -ne 'None') {
$TenantList = Get-Tenants -IncludeErrors
if ($Row.Tenant -ne 'None' -and $Row.Tenant) {
$Tenant = $TenantList | Where-Object -Property defaultDomainName -EQ $Row.Tenant
if ($Tenant.customerId -notin $AllowedTenants) {
if ($Tenant -and $Tenant.customerId -notin $AllowedTenants) {
continue
}
}
}
$LogData = if ($Row.LogData -and (Test-Json -Json $Row.LogData)) {
$LogData = if ($Row.LogData -and (Test-Json -Json $Row.LogData -ErrorAction SilentlyContinue)) {
$Row.LogData | ConvertFrom-Json
} else { $Row.LogData }
[PSCustomObject]@{
Expand All @@ -65,7 +63,6 @@ Function Invoke-ListLogs {
}
}
}

}

Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
Expand Down
64 changes: 37 additions & 27 deletions Modules/CIPPCore/Public/Get-CIPPMFAState.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function Get-CIPPMFAState {
}

$SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $TenantFilter ).IsEnabled
$CAState = New-Object System.Collections.ArrayList
$CAState = [System.Collections.Generic.List[object]]::new()

Try {
$MFARegistration = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/reports/credentialUserRegistrationDetails' -tenantid $TenantFilter)
Expand All @@ -31,22 +31,23 @@ function Get-CIPPMFAState {
$CAPolicies = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $TenantFilter -ErrorAction Stop )

try {
$ExcludeAllUsers = New-Object System.Collections.ArrayList
$ExcludeSpecific = New-Object System.Collections.ArrayList

foreach ($Policy in $CAPolicies) {
if (($policy.grantControls.builtincontrols -eq 'mfa') -or ($policy.grantControls.authenticationStrength.requirementsSatisfied -eq 'mfa') -or ($policy.grantControls.customAuthenticationFactors -eq 'RequireDuoMfa')) {
if ($Policy.conditions.applications.includeApplications -ne 'All') {
Write-Host $Policy.conditions.applications.includeApplications
$CAState.Add("$($policy.displayName) - Specific Applications - $($policy.state)") | Out-Null
$Policy.conditions.users.excludeUsers.foreach({ $ExcludeSpecific.Add($_) | Out-Null })
continue
}
if ($Policy.conditions.users.includeUsers -eq 'All') {
$CAState.Add("$($policy.displayName) - All Users - $($policy.state)") | Out-Null
$Policy.conditions.users.excludeUsers.foreach({ $ExcludeAllUsers.Add($_) | Out-Null })
continue
}
$IsMFAControl = $policy.grantControls.builtincontrols -eq 'mfa' -or $Policy.grantControls.authenticationStrength.requirementsSatisfied -eq 'mfa' -or $Policy.grantControls.customAuthenticationFactors -eq 'RequireDuoMfa'
$IsAllApps = [bool]($Policy.conditions.applications.includeApplications -eq 'All')
$IsAllUsers = [bool]($Policy.conditions.users.includeUsers -eq 'All')
$Platforms = $Policy.conditions.clientAppTypes

if ($IsMFAControl) {
$CAState.Add([PSCustomObject]@{
DisplayName = $Policy.displayName
State = $Policy.state
IncludedApps = $Policy.conditions.applications.includeApplications
IncludedUsers = $Policy.conditions.users.includeUsers
ExcludedUsers = $Policy.conditions.users.excludeUsers
IsAllApps = $IsAllApps
IsAllUsers = $IsAllUsers
Platforms = $Platforms
})
}
}
} catch {
Expand All @@ -59,18 +60,26 @@ function Get-CIPPMFAState {
# Interact with query parameters or the body of the request.
$GraphRequest = $Users | ForEach-Object {
Write-Host 'Processing users'
$UserCAState = New-Object System.Collections.ArrayList
$UserCAState = [System.Collections.Generic.List[object]]::new()
foreach ($CA in $CAState) {
if ($CA -like '*All Users*') {
if ($ExcludeAllUsers -contains $_.ObjectId) { $UserCAState.Add("Excluded from $($policy.displayName) - All Users") | Out-Null }
else { $UserCAState.Add($CA) | Out-Null }
} elseif ($CA -like '*Specific Applications*') {
if ($ExcludeSpecific -contains $_.ObjectId) { $UserCAState.Add("Excluded from $($policy.displayName) - Specific Applications") | Out-Null }
else { $UserCAState.Add($CA) | Out-Null }
if ($CA.IncludedUsers -eq 'All' -or $CA.IncludedUsers -contains $_.ObjectId) {
$UserCAState.Add([PSCustomObject]@{
DisplayName = $CA.DisplayName
UserIncluded = ($CA.ExcludedUsers -notcontains $_.ObjectId)
AllApps = $CA.IsAllApps
PolicyState = $CA.State
Platforms = $CA.Platforms -join ', '
})
}
}
if ($UserCAState.UserIncluded -eq $true -and $UserCAState.PolicyState -eq 'enabled') {
if ($UserCAState.UserIncluded -eq $true -and $UserCAState.PolicyState -eq 'enabled' -and $UserCAState.AllApps) {
$CoveredByCA = 'Enforced - All Apps'
} else {
Write-Host 'Adding to CA'
$UserCAState.Add($CA) | Out-Null
$CoveredByCA = 'Enforced - Specific Apps'
}
} else {
$CoveredByCA = 'Not Enforced'
}

$PerUser = if ($PerUserMFAState -eq $null) { $null } else { ($PerUserMFAState | Where-Object -Property UserPrincipalName -EQ $_.UserPrincipalName).PerUserMFAState }
Expand All @@ -86,8 +95,9 @@ function Get-CIPPMFAState {
PerUser = $PerUser
isLicensed = $_.isLicensed
MFARegistration = $MFARegUser.IsMFARegistered
MFAMethods = $($MFARegUser.authMethods -join ', ')
CoveredByCA = ($UserCAState -join ', ')
MFAMethods = $MFARegUser.authMethods
CoveredByCA = $CoveredByCA
CAPolicies = $UserCAState
CoveredBySD = $SecureDefaultsState
RowKey = [string]($_.UserPrincipalName).replace('#', '')
PartitionKey = 'users'
Expand Down
Loading